파이썬으로 부시자! Python with Coreenee

BAEKJOON 2231

문제

어떤 자연수 N이 있을 때, 그 자연수 N의 분해합은 N과 N을 이루는 각 자리수의 합을 의미한다. 어떤 자연수 M의 분해합이 N인 경우, M을 N의 생성자라 한다. 예를 들어, 245의 분해합은 256(=245+2+4+5)이 된다. 따라서 245는 256의 생성자가 된다. 물론, 어떤 자연수의 경우에는 생성자가 없을 수도 있다. 반대로, 생성자가 여러 개인 자연수도 있을 수 있다. 자연수 N이 주어졌을 때, N의 가장 작은 생성자를 구해내는 프로그램을 작성하시오.

입력

첫째 줄에 자연수 N(1 ≤ N ≤ 1,000,000)이 주어진다.


나의 처음 코드

제일 처음 했던 방법은, 브루트포스에 맞게 주어진 숫자 전부터 1까지 하나하나씩 다 더해보는 것이었다. 정답은 맞았지만, 이렇게 했을 경우에 2216ms 가 걸린다. 지금까지 통과한 문제중에 시간이 제일 오래 걸린 문제였다? 일단 이렇게 통과시키고 다른 코드로 해보기로 했다. 다음은 제일 처음 코드이다.

org_num = int(input()) #입력 받은 숫자
num = org_num #나중에 변형할 것이므로 num에다가 org_num을 대입
creator = 0 #최소 생성자

while True:
    tmp_sum = 0
    if num == 0:
        break
    num -= 1
    tmp_num = str(num)
    for i in tmp_num:
        tmp_sum += int(i)
    tmp_sum += int(tmp_num)
    if tmp_sum == org_num:
        creator = int(tmp_num)

print(creator)

기초로 다시 생각한 코드

생각을 해보면, 어떠한 생성자에서 주어진 숫자가 되려면, max로 더할 수 있는 값이 자리수 만큼, 그리고 그 자리에 들어갈 수 있는 최대 값이 최소의 범위가 될 것이다. 예를 들어 126(3자리)이 주어졌다면, 생성자의 범위는 (3자리의 수 * 최대값 9) 가 될 것이다. 따라서 범위는 126 - 27 = 99가 될 것이다. 우리는 이 99라는 숫자부터 차근차근 찾아서 최소 생성자를 알아보면 될 것이다. 이렇게 했을 경우에는 56ms가 걸린다.

org_num = input() #주어진 수
creator = 0 #최소 생성자
if len(org_num) == 1: #한 자리수라면 생성자가 없으므로 0을 출력하면 된다.
    print(0)
    #그렇지 않을 경우에는 위에서 설명한대로 해주면 된다.
else:
    for i in range(int(org_num) - 9 * len(org_num),
                   int(org_num)):
        num = i
        if i+sum(list(map(int, str(i)))) ==
                 int(org_num): #분해합이 주어진 숫자랑 같으면 정답!
            creator = i
            break
    print(creator)

import math(pow, sqrt)

sum(list)
굳이 포문으로 리스트의 원소를 하나씩 접근할 필요 없이, 주어진 숫자 e.g. 126이면 이것을 문자열로 강제변환후에 정수로 맵핑을 해줘서 리스트로 받은것을, sum()함수를 이용해서 한번에 구할 수 있다.

같은 브루트포스(무식하게 다해보는) 방식이더라도, 조금 더 나은 무식함이 있음을 알고있자!