셀프넘버 (self-number)
어떤 자연수 n이 있을 때, d(n)을 n의 각 자릿수 숫자들과 n 자신을 더한 숫자라고 정의하자.
예를 들어
d(91) = 9 + 1 + 91 = 101
이 때, n을 d(n)의 제네레이터(generator)라고 한다. 위의 예에서 91은 101의 제네레이터이다.
어떤 숫자들은 하나 이상의 제네레이터를 가지고 있는데, 101의 제네레이터는 91 뿐 아니라 100도 있다. 그런데 반대로, 제네레이터가 없는 숫자들도 있으며, 이런 숫자를 인도의 수학자 Kaprekar가 셀프 넘버(self-number)라 이름 붙였다. 예를 들어 1,3,5,7,9,20,31 은 셀프 넘버 들이다.
1 이상이고 5000 보다 작은 모든 셀프 넘버들의 합을 구하라.
박응용 님 3629
2020년 7월 7일 3:22 오후
15개의 답변이 있습니다. 1 / 2 Page
def find_gen(number):
generator = []
for i in range(1, number):
count=0
for n in str(i):
count += int(n)
count += i
if count == number:
generator.append(i)
return generator
selfnumber = []
for i in range(1,5001):
generator = find_gen(i)
if not generator:
selfnumber.append(i)
print('셀프넘버들')
print(selfnumber)
print('합')
print(sum(selfnumber))
답은 나옵니다만 더 효율적인 방법이 있으면 가차없이 지적해 주시면 좋겠습니다ㅠ
실력을 키우고 싶어요
김영준 님
2020년 7월 8일 6:03 오후
먼저 d(n)을 나타내는 람다를 만듭니다. 리스트 컴프리헨션으로 n
을 문자열로 변환해서 자리수를 나타내는 문자를 하나씩 얻어서 각각 숫자로 바꾼 리스트를 만들고, n
이 있는 리스트를 만들어 두 리스트를 합친 다음, 합을 구합니다.
>>> d = lambda n: sum([int(c) for c in str(n)] + [n])
>>> d(91)
101
다음은 n
이 셀프 넘버인지 확인하는 함수입니다. n
의 제네레이터 리스트를 만들고, 그 길이가 0
이면 n
이 셀프 넘버가 맞으므로 True
를 반환합니다.
def self_number(n):
return len([i for i in range(n) if d(i) == n]) == 0
self_number
가 잘 작동하는지 테스트해봅니다.
>>> self_number(1)
True
>>> self_number(2)
False
>>> self_number(3)
True
...
이제 5000
까지의 합을 구해봅니다. 좀 오래 걸리네요.^^
>>> sum([i for i in range(5000) if self_number(i)])
1227365
최용 님
M 2020년 7월 10일 10:37 오후
제가 지난번에 푼 것이 너무 오래 걸려서 불만이었는데, Fast_Learner 님 풀이를 보고 힌트를 얻었습니다.
d는 지난번에 제가 한 것과 같습니다.
>>> d = lambda n: sum([int(c) for c in str(n)] + [n])
>>> d(91) # 91은 101의 제네레이터
101
제네레이터의 딕셔너리 G를 만듭니다. 딕셔너리 컴프리헨션을 이용했습니다.
>>> G = {n: d(n) for n in range(1, 5001)}
>>> G[91] # 91은 101의 제네레이터
101
>>> G[100] # 100도 101의 제네레이터
101
셀프 넘버의 리스트 S를 만들고 합을 구합니다.
>>> S = [i for i in range(1, 5001) if i not in G.values()]
리스트 대신 세트(set)를 만들 수도 있습니다.
>>> S = set(range(1, 5001)) - set(G.values())
S의 모든 원소의 합을 구합니다.
>>> sum(S)
1227365
최용 님
M 2020년 7월 16일 7:41 오후
1,227,365
2020년 7월 8일 2:23 오후
sum_of_element=[]
sum_of_all=[]
## init
limit_sum=5000
for i in range(1,limit_sum):
sum_of_all.append(i)
def check_value(t):
if (t) > 0 and (t) <= 9 :
sum_of_element.append(t)
def remove_sum(to_remove):
try:
sum_of_all.remove(to_remove)
except:
pass
for i in range(1,limit_sum):
#
t0=i%10
check_value(t0)
t1=(i//10%10)
check_value(t1)
t2=(i//100%10)
check_value(t2)
t3=(i//1000%10)
check_value(t3)
sum_of_element.append(i)
#
remove_sum(sum(sum_of_element))
del sum_of_element[0:]
#print (sum_of_all)
print (sum(sum_of_all))
Python internal function이 익숙치 않아서 풀이가 ..
johlim 님
M 2020년 7월 8일 7:03 오후
def d(n):
digit_sum = sum([int(i) for i in str(n)])
return n + digit_sum
nums = {i for i in range(5000)}
nums_gen_exist = set()
for i in range(1,5000):
if d(i) < 5000:
nums_gen_exist.add(d(i))
nums_gen_not_exist = nums.difference(nums_gen_exist)
print(sum(nums_gen_not_exist))
wjpark11 님
M 2020년 7월 15일 3:50 오후
n = 0
not_self_number = []
self_number = []
while n < 5001:
if n < 10:
x = n + n
elif n < 100:
m = str(n)
n1 = int(m[0])
n2 = int(m[1])
x = n + n1 + n2
elif n < 1000:
m = str(n)
n1 = int(m[0])
n2 = int(m[1])
n3 = int(m[2])
x = n + n1 + n2 + n3
elif n < 5000:
m = str(n)
n1 = int(m[0])
n2 = int(m[1])
n3 = int(m[2])
n4 = int(m[3])
x = n + n1 + n2 + n3 + n4
else:
pass
not_self_number.append(x)
n += 1
for i in range(1,5001):
if i not in not_self_number:
self_number.append(i)
else:
pass
print(sum(self_number))
M 2020년 7월 16일 2:06 오후
a = set()
b = set(range(1, 5000))
for i in range(1, 5000):
for j in str(i):
i = i + int(j)
if i < 5000:
a.add(i)
b = b - a
print(sum(b))
>>>1227365
iirtrtrt 님
M 2020년 8월 2일 8:24 오후
d = (lambda num: num+sum(int(i) for i in str(num)))
numlist = list(range(1,5001))
for num in range(1,5001):
try:
numlist.remove(d(num))
except:
...
print(sum(numlist))
파이썬을 연습하기 좋은 퀴즈인 것 같습니다!!
댓글을 보고 힌트를 얻어 조금 더 짧게 만들어보려고 했는데 아직 초보수준이라 아쉽네요 ㅎㅎ
많이 배우고 갑니다 ㅎㅎ
9iant 님
M 2020년 8월 12일 9:38 오전
파이썬을 시작한지 얼마 되지않아 많이 미숙하지만, 그래도 해보았습니다.
저는 셀프넘버 들을 구하지 않고 셀프넘버들의 합 만 구했습니다.
def d(a) :
result = int(a/1000) + int(a/100)%10 + int(a/10)%10 + a%10 + a
return result
이 함수는 제네레이터를 구하는 함수입니다.
참고로 말하자면 int(a/1000)은 천의자리, int(a/100)%10은 백의자리, int(a/10)%10은 십의자리, a%10은 일의자리를 나타낸겁니다.
왜 만들었는지는 밑에 코드를 보면 아실수 있습니다.
result = 0
gen_number = list(set([d(i) for i in range(1,5000) if d(i) < 5000]))
위에 result는 뒤에 쓸 용도로 0으로 먼저 지정해주었습니다.
gen_number 변수는 d(i)가 5000이 넘지 않을때 d(i) (여기서 i는 1~4999)의 값들을 모두 구한것
에서 set을 취해주어 중복되는 값들을 제거해주고 다시 list를 취해주어 리스트로 변환해주었습니다.
따라서 이 리스트에는 중복되지 않은 제네레이터 밖에 없습니다.
for i in range(0,len(gen_number)) :
result += gen_number[i]
위에 for문은 아까 선언해주었던 result 변수에다가 gen_number 리스트에있는 모든수를 더해 주기위해 썼습니다.
그렇게 된다면 제네레이터만 전부 더한것이 되고, 반대로 말하자면 셀프넘버 만 더하지않은것이 됩니다.
따라서 전체에서 이 수를 빼면 셀프넘버만 더한것의 값이 나옵니다.
all = 0
for i in range(1,5000) :
all += i
위에 for문은 1부터 4999까지의 합을 all에 지정해두기 위해 썼습니다.
result = all - result
위에서 언급한 내용대로 셀프넘버의 합을 구하기 위해 썼습니다.
print(result)
많이 미숙하지만 봐주셔서 감사합니다. 피드백은 환영입니다.
송고쟝 님
M 2020년 8월 25일 9:31 오전