파이썬 셀프 넘버(백준 BOJ 4673)


내용 이해는 했지만 어떻게 풀어야할지 고민했던 문제라 기록해서 다시 볼 겸 남긴다!


문제

셀프 넘버는 1949년 인도 수학자 D.R. Kaprekar가 이름 붙였다. 양의 정수 n에 대해서 d(n)을 n과 n의 각 자리수를 더하는 함수라고 정의하자. 예를 들어, d(75) = 75+7+5 = 87이다.

양의 정수 n이 주어졌을 때, 이 수를 시작해서 n, d(n), d(d(n)), d(d(d(n))), …과 같은 무한 수열을 만들 수 있다.

예를 들어, 33으로 시작한다면 다음 수는 33 + 3 + 3 = 39이고, 그 다음 수는 39 + 3 + 9 = 51, 다음 수는 51 + 5 + 1 = 57이다. 이런식으로 다음과 같은 수열을 만들 수 있다.

33, 39, 51, 57, 69, 84, 96, 111, 114, 120, 123, 129, 141, …

n을 d(n)의 생성자라고 한다. 위의 수열에서 33은 39의 생성자이고, 39는 51의 생성자, 51은 57의 생성자이다. 생성자가 한 개보다 많은 경우도 있다. 예를 들어, 101은 생성자가 2개(91과 100) 있다.

생성자가 없는 숫자를 셀프 넘버라고 한다. 100보다 작은 셀프 넘버는 총 13개가 있다. 1, 3, 5, 7, 9, 20, 31, 42, 53, 64, 75, 86, 97

10000보다 작거나 같은 셀프 넘버를 한 줄에 하나씩 출력하는 프로그램을 작성하시오.


입력

입력은 없다.


출력

10,000보다 작거나 같은 셀프 넘버를 한 줄에 하나씩 증가하는 순서로 출력한다.


예제 입력


예제 출력

1
3
5
7
9
20
31
42
53
64
 |
 |       <-- a lot more numbers
 |
9903
9914
9925
9927
9938
9949
9960
9971
9982
9993


풀어보기

# 셀프넘버 = 전체숫자(1~10000) - 생성자(다른 숫자를 생성할 수 있는 수)
number = set(range(1, 10001)) # 1~10000 정수
not_self_number = set() # 셀프 넘버가 아닌 값을 받을 공간 

for i in range(1, 10001): # 10000번 동안
    for j in str(i): # i를 str로 변환
        i += int(j)  # 쪼갠 i를 j에 담아 i에 더하기 99(i) + 9(int(j)) + 9(int(j))
    not_self_number.add(i) # 셀프 넘버가 아닌 공간에 i값을 넣기
self_number = number - not_self_number # 셀프 넘버 = 전체 숫자 - 셀프넘버가 아닌 것

for k in sorted(self_number): # set은 정렬이 되어있지 않아 정렬한 값을 k에 넣어줌 
    print(k) # 출력

우선 위의 문제 내용을 봤을 때 셀프 넘버를 어떻게 구해야하는지 생각해봤다.

전체 숫자가 1~10000이면 이 범위 내에 33(33+3+3), 39(39+3+9)같이 생성자들이 무수히 많을것이다.

셀프 넘버는 생성자를 가지지 않는 숫자니까 셀프 넘버 = 전체 숫자 - 생성자 가 될것이다.


그 다음으로 생성자를 구해야 하는데 33이라면 33+3+3이 되어야 한다.

전체 숫자를 str로 형변환 후에 쪼갠 값을 j에 담아서 i에 각각 누적시켰다.


누적된 i의 값을 not_self_number에 저장시키고 number(전체 숫자) - not_self_number(셀프넘버가 아닌 값)으로 self_number 값을 저장한다.


마지막으로 예제 출력은 1에서 부터 오름차순으로 출력되는데 오늘 배운것처럼 set에 담긴 값은 순서가 없기 때문에 오름차순으로 나오지 않는다. 그래서 sorted() 함수로 정렬시킨 값을 k에 담아서 출력했다.

관심있을 포스팅