루나의 TIL 기술 블로그

프로그래머스 level 1 이상한 문자 만들기

|

걸린 시간 : 3시간

문제 설명

문자열 s는 한 개 이상의 단어로 구성되어 있습니다. 각 단어는 하나 이상의 공백문자로 구분되어 있습니다. 각 단어의 짝수번째 알파벳은 대문자로, 홀수번째 알파벳은 소문자로 바꾼 문자열을 리턴하는 함수, solution을 완성하세요.

문자열 전체의 짝/홀수 인덱스가 아니라, 단어(공백을 기준)별로 짝/홀수 인덱스를 판단해야합니다.
첫 번째 글자는 0번째 인덱스로 보아 짝수번째 알파벳으로 처리해야 합니다.

입출력 예

s return
"try hello world" "TrY HeLlO WoRlD"

사고과정

이중 for문을 돌려서 처리한다.

def solution(s):
    arr = s.split() #[try, hello, world]
    arr1 =[]
    arr2 =[]
    for i in arr:#[try]
        for j in range(0,len(i)):#t
            if j%2 == 0:
                arr1.append(i[j].upper())#짝수면대문자
            else:
                arr1.append(i[j].lower())#홀수면소문자
            print(arr1)
            ''.join(arr1)
    arr2 = ' '.join(arr1)
    print(arr2)
    return arr2

이렇게 하니까 출력값이 “T r Y H e L l O W o R l D”라고 나왔다. 변수 이름을 좀 더 직관적으로 고치고,
print문을 중간중간 넣어서 중간과정을 체크하고,
new_word를 배열이 아닌 문자열로 선언하고 위치를 for문 안으로 옮겼다.

이중 for문을 돌리면서 i를 숫자로 할 지, 배열의 원소로 할지에 대해서 다시한 번 생각해봤고

list, string 을 가지고 append, +=, join을 해가면서 한시간정도 삽질을했다.
join은 배열을 합쳐서 문자열로 만들어준다는 것을 다시 한 번 체득했다.

결과값이 TrY HeLlO WoRlD 라고 잘 나오는데 다른 테스트케이스에서는 틀렸다고 나와서
질문하기를 살펴보니까 split(‘ ‘)을 안쓰고 split()을 쓰면 공백이 여러개일때 하나로 합쳐져서 틀리는것이라고 해서 split() 대신에 split(‘ ‘)을 넣어줬더니 통과되었다!

제출 답안

def solution(s):
    arr = s.split(' ') #['try', 'hello', 'world']
    arr2 =[]
    for word in arr: # 여기서 word는 try, hello, world가 된다. 
        print(word) # 문자열 try 출력
        new_word ="" 
        # 이 변수는 재사용하기때문에 새로고침하기 위해서 첫째 for문 사용 이후에 넣어줘야한다.
        for i in range(0,len(word)):# 여기서 i는 0,1,2가 된다.
            if i%2 == 0:
                new_word += word[i].upper()#짝수면대문자
            else:
                new_word += word[i].lower()#홀수면소문자
        arr2.append(''.join(new_word)) 
        #한 글자씩 모아서 문자열로 만든 new_word들을 배열에 넣어준다.
        answer = ' '.join(arr2) #이 배열을 문자열로 바꿔준다.
    print(answer)
    return answer

모범 답안

def toWeirdCase(s):
    return " ".join(map(lambda x: "".join([a.lower() if i % 2 else a.upper() for i, a in enumerate(x)]), s.split(" ")))

주요 포인트 및 생각해볼 점

enumerate함수를 이용한 풀이를 찾아서 설명을 한 번 더 들어보고 이용해봐야겠다.

프로그래머스 level 1 비밀지도

|

문제 설명

네오는 평소 프로도가 비상금을 숨겨놓는 장소를 알려줄 비밀지도를 손에 넣었다. 그런데 이 비밀지도는 숫자로 암호화되어 있어 위치를 확인하기 위해서는 암호를 해독해야 한다. 다행히 지도 암호를 해독할 방법을 적어놓은 메모도 함께 발견했다.

1.지도는 한 변의 길이가 n인 정사각형 배열 형태로, 각 칸은 “공백”(“ “) 또는 “벽”(“#”) 두 종류로 이루어져 있다.
2.전체 지도는 두 장의 지도를 겹쳐서 얻을 수 있다. 각각 “지도 1”과 “지도 2”라고 하자. 지도 1 또는 지도 2 중 어느 하나라도 벽인 부분은 전체 지도에서도 벽이다. 지도 1과 지도 2에서 모두 공백인 부분은 전체 지도에서도 공백이다.
3.”지도 1”과 “지도 2”는 각각 정수 배열로 암호화되어 있다.
4.암호화된 배열은 지도의 각 가로줄에서 벽 부분을 1, 공백 부분을 0으로 부호화했을 때 얻어지는 이진수에 해당하는 값의 배열이다.

원래의 비밀지도를 해독하여 ‘#’, 공백으로 구성된 문자열 배열로 출력하라.

비밀 지도

입출력 예

매개변수
n 5
arr1 [9, 20, 28, 18, 11]
arr2 [30, 1, 21, 17, 28]
출력 ["#####","# # #", "### #", "# ##", "#####"]

사고과정

1.일단 수들을 이진수로 바꾸고
2.바뀐 수들을 비교해서 둘 중에 하나라도 1이면
3.1로 새 배열에 저장한다.

def solution(n, arr1, arr2):
    arr3 = []
    arr4 = []
    for i in range(0, n):
        arr3.append(bin(arr1[i]))
        arr4.append(bin(arr2[i]))
    #여기까지 1번

2번을 어떻게할지 모르겠어서 다른 블로그를 참고했는데 두 수를 더하는 방법이 있길래 (두수를 더하는 방법을 사용한 아이티가든 블로그) 어떻게 그렇게 하는것인지 의문이 들었다. 다른 답안에서는 zip과 or(|)를 사용했다.

모범 답안

def solution(n, arr1, arr2):
    answer = []

    for i,j in zip(arr1, arr2):
        ans = str(bin(i|j)[2:])#2진수 표시인 ob제거
        ans = ans.zfill(n)#자릿수를 맞춰주는 zfill이라는게 있었다!
        ans = ans.replace('1', '#')
        ans = ans.replace('0', ' ')
        answer.append(ans)
    return answer

주요 포인트 및 생각해볼 점

이렇게 발견한 함수들은 잊어버리지 않을 것 같다. 오랜시간 고민했는데 간단하게 함수를 사용해서 풀 수 있었어서, 너무 오래 고민하지 말아야겠다는 생각이 들었다.

마크업에서 | 이걸 치면 표를 만들 수 있다는 사실을 발견했다.

백준 1101 Fly me to the Alpha Centauri

|

문제 설명

우현이는 어린 시절, 지구 외의 다른 행성에서도 인류들이 살아갈 수 있는 미래가 오리라 믿었다. 그리고 그가 지구라는 세상에 발을 내려 놓은 지 23년이 지난 지금, 세계 최연소 ASNA 우주 비행사가 되어 새로운 세계에 발을 내려 놓는 영광의 순간을 기다리고 있다.

그가 탑승하게 될 우주선은 Alpha Centauri라는 새로운 인류의 보금자리를 개척하기 위한 대규모 생활 유지 시스템을 탑재하고 있기 때문에, 그 크기와 질량이 엄청난 이유로 최신기술력을 총 동원하여 개발한 공간이동 장치를 탑재하였다. 하지만 이 공간이동 장치는 이동 거리를 급격하게 늘릴 경우 기계에 심각한 결함이 발생하는 단점이 있어서, 이전 작동시기에 k광년을 이동하였을 때는 k-1 , k 혹은 k+1 광년만을 다시 이동할 수 있다.
예를 들어, 이 장치를 처음 작동시킬 경우 -1 , 0 , 1 광년을 이론상 이동할 수 있으나 사실상 음수 혹은 0 거리만큼의 이동은 의미가 없으므로 1 광년을 이동할 수 있으며, 그 다음에는 0 , 1 , 2 광년을 이동할 수 있는 것이다. ( 여기서 다시 2광년을 이동한다면 다음 시기엔 1, 2, 3 광년을 이동할 수 있다.)

김우현은 공간이동 장치 작동시의 에너지 소모가 크다는 점을 잘 알고 있기 때문에 x지점에서 y지점을 향해 최소한의 작동 횟수로 이동하려 한다. 하지만 y지점에 도착해서도 공간 이동장치의 안전성을 위하여 y지점에 도착하기 바로 직전의 이동거리는 반드시 1광년으로 하려 한다.

김우현을 위해 x지점부터 정확히 y지점으로 이동하는데 필요한 공간 이동 장치 작동 횟수의 최솟값을 구하는 프로그램을 작성하라.

사고과정

111, 1234321 이렇게만 움직일 수 있는 우주선을 탄다고 하니까 예시를 써서 규칙을 찾아보자.
12321 이런식으로 된 수열의 합인 이동거리는 등차수열의 합공식을 이용해서 ((3*2/2) *2) -3해서 3의 제곱이다.

이동궤적 이동거리 카운트
1 1 1
11 2 2
111 3 3
121 4 3
1211 5 4
1221 6 4
12211 7 5
12321 9 5
112321 10 6
123221 11 6
123321 12 6
1232221 13 7
1233221 14 7
1233321 15 7
1234321 16 7
1234321 17 7
123454321 25 9
12345654321 36 11

이동거리가 제곱수일 때 카운트는 (이동거리 제곱근 x 2) - 1 의 규칙을 가진다.
제곱수가 아닐때는 어떤 규칙을 가지는지 모르겠어서 다른 블로그를 참고했다.
출처 : 덕봇기의 코딩세상
이동거리의 제곱근만큼 다음 숫자가 나온다고 한다..! (파란색 참고)
그래서 나머지를 제곱근과 비교해서 경우를 세 가지로 나누어볼 수 있다.
1.나머지가 없는 경우
2.나머지가 제곱근보다 작은 경우
3.나머지가 제곱근보다 큰 경우

제출 답안

n = int(input())
for _ in range(n):
    x,y = map(int,input().split())
    distance = y - x

    sqrt = int(distance**0.5) #제곱근
    cnt = sqrt * 2 - 1 #제곱근일 때 카운트

    remainder = distance - sqrt ** 2
    if remainder == 0:
        print(cnt)
    elif remainder <= sqrt:
        print(cnt + 1)
    else:
        print(cnt + 2)

주요 포인트 및 생각해볼 점

사고과정과 문제를 어떻게 풀었는지를 주석과 함께 좀 더 자세하게 기록하는 것도 좋겠다.

프로그래머스 level 1 모의고사

|

문제 설명

수포자는 수학을 포기한 사람의 준말입니다. 수포자 삼인방은 모의고사에 수학 문제를 전부 찍으려 합니다. 수포자는 1번 문제부터 마지막 문제까지 다음과 같이 찍습니다.

1번 수포자가 찍는 방식: 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, … 2번 수포자가 찍는 방식: 2, 1, 2, 3, 2, 4, 2, 5, 2, 1, 2, 3, 2, 4, 2, 5, … 3번 수포자가 찍는 방식: 3, 3, 1, 1, 2, 2, 4, 4, 5, 5, 3, 3, 1, 1, 2, 2, 4, 4, 5, 5, …

1번 문제부터 마지막 문제까지의 정답이 순서대로 들은 배열 answers가 주어졌을 때, 가장 많은 문제를 맞힌 사람이 누구인지 배열에 담아 return 하도록 solution 함수를 작성해주세요.

시험은 최대 10,000 문제로 구성되어있습니다. 문제의 정답은 1, 2, 3, 4, 5중 하나입니다. 가장 높은 점수를 받은 사람이 여럿일 경우, return하는 값을 오름차순 정렬해주세요.

입출력 예

array return
[1,2,3,4,5] [1]
[1,3,2,4,2] [1,2,3]

제출답안

def solution(answers):

    answer = []
    a = [1,2,3,4,5]*2000
    b = [2,1,2,3,2,4,2,5]*1250
    c = [3,3,1,1,2,2,4,4,5,5,]*1000

    a_count = b_count = c_count = 0

    for i in range(0, len(answers)):
        if answers[i] == a[i]:
            a_count += 1
        if answers[i] == b[i]:
            b_count += 1
        if answers[i] == c[i]:
            c_count += 1

    answer_temp = [a_count,b_count,c_count]

    for i, num in enumerate(answer_temp):
        if num == max(answer_temp):
            answer.append(i+1)

    return answer

모범 답안

def solution(answers):
    pattern1 = [1,2,3,4,5]
    pattern2 = [2,1,2,3,2,4,2,5]
    pattern3 = [3,3,1,1,2,2,4,4,5,5]
    score = [0, 0, 0]
    result = []

    for idx, answer in enumerate(answers):
        if answer == pattern1[idx%len(pattern1)]:
            score[0] += 1
        if answer == pattern2[idx%len(pattern2)]:
            score[1] += 1
        if answer == pattern3[idx%len(pattern3)]:
            score[2] += 1

    for idx, s in enumerate(score):
        if s == max(score):
            result.append(idx+1)

    return result

주요 포인트 및 생각해볼 점

모범답안과 꽤 비슷하게 풀었다! enumerate에 대해서 알게되었다. 직접 쓰면서 배우는게 습득에 좋다.

프로그래머스 level 1 정수 내림차순으로 배치하기

|

문제 설명

함수 solution은 정수 n을 매개변수로 입력받습니다. n의 각 자릿수를 큰것부터 작은 순으로 정렬한 새로운 정수를 리턴해주세요. 예를들어 n이 118372면 873211을 리턴하면 됩니다.

입출력 예

n return
118372 873211

제출답안

def solution(n):
    arr = list(str(n))
    arr = sorted(arr, reverse=True)
    answer = int(''.join(arr))
    print(answer)
    return answer

모범 답안

def solution(n):
    ls = list(str(n))
    ls.sort(reverse = True)
    return int("".join(ls))

주요 포인트 및 생각해볼 점

sort 와 sorted, reverse 와 reversed의 차이점을 알아봐야겠다.

프로그래머스 level 1 문자열 내 p와 y의 개수

|

문제 설명

대문자와 소문자가 섞여있는 문자열 s가 주어집니다. s에 ‘p’의 개수와 ‘y’의 개수를 비교해 같으면 True, 다르면 False를 return 하는 solution를 완성하세요. ‘p’, ‘y’ 모두 하나도 없는 경우는 항상 True를 리턴합니다. 단, 개수를 비교할 때 대문자와 소문자는 구별하지 않습니다.

예를 들어 s가 “pPoooyY”면 true를 return하고 “Pyy”라면 false를 return합니다.

입출력 예

s answer
"pPoooyY" true
"Pyy" false

제출답안

def solution(s):
    s = s.lower()
    if s.count('p') == s.count('y'):
        return True
    if s.count('p') == s.count('y') == 0:
        return True
    else:
        return False

모범 답안

def numPY(s):
    return s.lower().count('p') == s.lower().count('y')

주요 포인트 및 생각해볼 점

True 하고 False 좀 더 직접적으로 생각하면서 써봐야겠다.

프로그래머스 level 1 신규아이디추천

|

문제 설명

카카오에 입사한 신입 개발자 네오는 “카카오계정개발팀”에 배치되어, 카카오 서비스에 가입하는 유저들의 아이디를 생성하는 업무를 담당하게 되었습니다. “네오”에게 주어진 첫 업무는 새로 가입하는 유저들이 카카오 아이디 규칙에 맞지 않는 아이디를 입력했을 때, 입력된 아이디와 유사하면서 규칙에 맞는 아이디를 추천해주는 프로그램을 개발하는 것입니다.
다음은 카카오 아이디의 규칙입니다.

아이디의 길이는 3자 이상 15자 이하여야 합니다.
아이디는 알파벳 소문자, 숫자, 빼기(-), 밑줄(_), 마침표(.) 문자만 사용할 수 있습니다.
단, 마침표(.)는 처음과 끝에 사용할 수 없으며 또한 연속으로 사용할 수 없습니다.
“네오”는 다음과 같이 7단계의 순차적인 처리 과정을 통해 신규 유저가 입력한 아이디가 카카오 아이디 규칙에 맞는 지 검사하고 규칙에 맞지 않은 경우 규칙에 맞는 새로운 아이디를 추천해 주려고 합니다.
신규 유저가 입력한 아이디가 new_id 라고 한다면,

1단계 new_id의 모든 대문자를 대응되는 소문자로 치환합니다.
2단계 new_id에서 알파벳 소문자, 숫자, 빼기(-), 밑줄(_), 마침표(.)를 제외한 모든 문자를 제거합니다.
3단계 new_id에서 마침표(.)가 2번 이상 연속된 부분을 하나의 마침표(.)로 치환합니다.
4단계 new_id에서 마침표(.)가 처음이나 끝에 위치한다면 제거합니다.
5단계 new_id가 빈 문자열이라면, new_id에 “a”를 대입합니다.
6단계 new_id의 길이가 16자 이상이면, new_id의 첫 15개의 문자를 제외한 나머지 문자들을 모두 제거합니다.
만약 제거 후 마침표(.)가 new_id의 끝에 위치한다면 끝에 위치한 마침표(.) 문자를 제거합니다.
7단계 new_id의 길이가 2자 이하라면, new_id의 마지막 문자를 new_id의 길이가 3이 될 때까지 반복해서 끝에 붙입니다.

제출답안

def solution(new_id):
    # 1단계
    new_id = new_id.lower()
    # 2단계
    answer = ''
    for word in new_id:
        if word.isalnum() or word in '-_.':
            answer += word
    # 3단계
    while '..' in answer:
        answer = answer.replace('..', '.')
    # 4단계
    answer = answer[1:] if answer[0] == '.' and len(answer) > 1 else answer
    answer = answer[:-1] if answer[-1] == '.' else answer
    # 5단계
    answer = 'a' if answer == '' else answer
    # 6단계
    if len(answer) >= 16:
        answer = answer[:15]
        if answer[-1] == '.':
            answer = answer[:-1]
    # 7단계
    if len(answer) <= 3:
        answer = answer + answer[-1] * (3-len(answer))
    return answer

모범 답안

import re

def solution(new_id):
    st = new_id
    st = st.lower()
    st = re.sub('[^a-z0-9\-_.]', '', st)
    st = re.sub('\.+', '.', st)
    st = re.sub('^[.]|[.]$', '', st)
    st = 'a' if len(st) == 0 else st[:15]
    st = re.sub('^[.]|[.]$', '', st)
    st = st if len(st) > 2 else st + "".join([st[-1] for i in range(3-len(st))])
    return st

주요 포인트 및 생각해볼 점

정규표현식을 살펴봐야겠다.

프로그래머스 level 1 K번째 수, 정렬

|

문제 설명

배열 array의 i번째 숫자부터 j번째 숫자까지 자르고 정렬했을 때, k번째에 있는 수를 구하려 합니다.

예를 들어 array가 [1, 5, 2, 6, 3, 7, 4], i = 2, j = 5, k = 3이라면

array의 2번째부터 5번째까지 자르면 [5, 2, 6, 3]입니다. 1에서 나온 배열을 정렬하면 [2, 3, 5, 6]입니다. 2에서 나온 배열의 3번째 숫자는 5입니다. 배열 array, [i, j, k]를 원소로 가진 2차원 배열 commands가 매개변수로 주어질 때, commands의 모든 원소에 대해 앞서 설명한 연산을 적용했을 때 나온 결과를 배열에 담아 return 하도록 solution 함수를 작성해주세요.

입출력 예

array commands return
[1, 5, 2, 6, 3, 7, 4] [[2, 5, 3], [4, 4, 1], [1, 7, 3]] [5, 6, 3]

사고 과정

입력받은 리스트를 잘라서 정렬한 값을 arr에 넣는다. arr의 주어진 인덱스 값(commands[i][2]-1)을 arr2에 넣는다.

제출답안

def solution(array, commands):
    arr = []
    arr2 = [] 
    for i in range(0, len(commands)):
        arr = array[commands[i][0]-1:commands[i][1]]
        arr = sorted(arr)
        arr2.append(arr[commands[i][2]-1])
    return arr2

모범 답안

def solution(array, commands):
    return list(map(lambda x:sorted(array[x[0]-1:x[1]])[x[2]-1], commands))

주요 포인트 및 생각해볼 점

람다 함수를 쓰는 연습을 해봐야겠다. 알고리즘만 해서그런가 요새 좀 쳐져서 프로젝트나 다른 것을 해보는게 좋겠다.

블로그에 사진이 안 나오는 점을 고쳐야하는데 경로 문제인 것 같다.
-06.24 어쩔 때는 또 잘 나온다. -07.10 /blog 경로에서 스크롤할 때는 잘 나오는데 개별 포스팅을 클릭해서 들어간 경로에서는 사진이 깨지길래 다른 블로그를 보고 경로를 !호텔 전부 이런식으로 수정했더니 잘 나온다.
디스쿠스는 광고가 너무 많아서 삭제했는데 광고없이 댓글기능을 추가할 수 있으면 좋겠다.
-07.15 사람들이 댓글을 달아줬으면 좋겠는데 돈을 내고 디스쿠스를 달까 생각중이다

검색 기능도 있으면 좋겠는데 여러가지 적용해봤지만 아직 실력이 부족한지 잘 적용되지 않았다.
-07.15 내부 검색 기능은 못 구현했지만 구글에서 검색이 가능하게 되었다!

프로그래머스 level 1 가운데 글자 가져오기

|

문제 설명

단어 s의 가운데 글자를 반환하는 함수, solution을 만들어 보세요. 단어의 길이가 짝수라면 가운데 두글자를 반환하면 됩니다.

제출답안

def solution(s):
    l = len(s)
    if l%2 == 0:
        answer = s[int(l/2)-1]+s[int(l/2)]
    else:
        answer = s[int(l/2)]
    return answer

모범 답안

def string_middle(str):
    return str[(len(str)-1)//2:len(str)//2+1]

주요 포인트 및 생각해볼 점

더하기 빼기, 몫을 구하는 연산을 이용해서 홀수와 짝수를 한 번에 처리하다니 멋있다.

프로그래머스 12940 최대공약수와 최소공배수

|

프로그래머스 - 최대공약수와 최소공배수

문제 설명

두 수를 입력받아 두 수의 최대공약수와 최소공배수를 반환하는 함수, solution을 완성해 보세요. 배열의 맨 앞에 최대공약수, 그다음 최소공배수를 넣어 반환하면 됩니다. 예를 들어 두 수 3, 12의 최대공약수는 3, 최소공배수는 12이므로 solution(3, 12)는 [3, 12]를 반환해야 합니다.

사고 과정

약수 리스트, 배수 리스트를 구한다.
리스트 두 개에서 공통으로 가지는 약수 중 가장 큰 수/ 작은 수를 출력한다.

#약수 리스트를 구하는 함수
def divisor(n):
  divisors = []
  for i in range(1, n+1):
      if n%i ==0:
          divisors.append(i)
  return divisors 

#배수 리스트를 구하는 함수
def multiple(m):
    multiples = []
    for i in range(1, 101):
        if i%m ==0:
            multiples.append(i)
    return multiples

#두 수의 최대공약수를 구하는 함수
def max_divisor(n,m):
    max_divisors = []
    for i in divisor(n): 
        if i in divisor(m):
            max_divisors.append(i)
    return max(max_divisors)

#두 수의 최소공배수를 구하는 함수
def min_multiple(n,m):
      min_multiples = []
      for i in multiple(n): 
          if i in multiple(m):
              min_multiples.append(i)
      return min(min_multiples)

def solution(n,m):
    print(max_divisor(n,m), min_multiple(n,m))
    return(max_divisor(n,m), min_multiple(n,m))

n = int(input())
m = int(input())
solution(n,m)

배수 리스트 크기가 너무 크다. 파이썬에 fractions, gcd라는게 있는지 몰랐다.

제출답안

from fractions import gcd
def gcdlcm(a,b):
    return[gcd(a,b), a*b/gcd(a,b)]

최대공약수 = greatest common divisor = gcd
최소공배수 = least common multiple = lcm

최소공배수와 최대공약수

그림에서 알 수 있듯이,
최소공배수 = 두 수의 곱 / 최대공약수 이다.
lcm = a*b / gcd

모범 답안

def gcdlcm(a, b):
    c, d = max(a, b), min(a, b) #둘 중 큰 값, 작은 값
    t = 1
    while t > 0: 
        t = c % d 
        c, d = d, t 
    answer = [c, int(a*b/c)] 

    return answer

최대공약수만 구해지면 주어진 두 수로 최대공약수를 구할 수 있으니까
큰 수를 작은수로 나누어서 나온 나머지로 큰 수를 나눈다.
나머지가 0이 될때까지 계속 반복하면 나머지가 0일 나눈 값이 최대공약수가 된다.
예를 들어서
35%25 = 10
35%10 = 5
35%5 = 0
이면 최대공약수가 5가 된다.

주요 포인트 및 생각해볼 점

수학적인걸 생각해보는건 좋지만 시간이 너무 오래 걸리는 것은 좋지 않다.