Skip to content

Instantly share code, notes, and snippets.

@return0927
Last active April 22, 2018 06:47
Show Gist options
  • Save return0927/42b234fbda18c6d5ba50c067dd9c01c5 to your computer and use it in GitHub Desktop.
Save return0927/42b234fbda18c6d5ba50c067dd9c01c5 to your computer and use it in GitHub Desktop.
1부터 자연수 n까지의 친화수를 모두 구해줌.
from time import time # 현재 timestamp를 불러오는 함수
"""함수부분"""
def division(n, stack=list(), num=1):
"""
재귀함수의 방법으로
1부터 자연수 n까지의 양의 진약수를 모두 구함.
:param n: 약수를 구하려는 자연수
:param stack: 현재까지 구한 양의 양수 (초기화를 위해 Default로 `list()`를 주어야함)
:param num: 현재 나누려는 수
:return: 양의 진약수를 가진 `list` 객체
"""
if num == 1: # 초기실행일 때
stack = [1] # 스택에 1을 넣고
return division(n, stack, num + 1) # 다음 값으로 넘어감.
# 1과 n을 넣지 않는 이유는, 친화수는 자기 자신을 제외한 진약수를 구해야하기 때문임.
if num > n ** 0.5: # n의 약수를 구할 때, 최적화를 위해서 루트 n 까지만 구하면 됌.
ret = [*set(stack)] # 리스트의 값들 중 중복을 제거함.
# set()은 list를 중복제거된 set의 형태로 리턴, *set()은 그 값들을 전부 나열해줌. 나열한 값을 []로 받으면 결과적으로 중복이 제거된 list가 됌
ret.sort() # set의 특성상 중복은 제거되지만 sort는 되지 않으므로 결과값을 sort해줌. (필수는아님)
return ret # 약수를 갖고있는 stack을 return해줌
if not n % num: # n%num은 약수일 때 False(0)을 반환함. Not을 붙여서 True로 만들어 감지.
stack.append(num) # 나눈 수를 스택에 추가
stack.append(n // num) # 나누어 떨어진 수를 스택에 추가. (이 function이 루트 n까지만 돌기 때문임.)
return division(n, stack, num + 1) # 약수이던 아니던 다음 값으로 넘어감.
"""입력부분"""
search_maximum = input("Search Range Maximum: ")
if not search_maximum.isnumeric(): print("Please input only integer") # string.isnumeric() 함수는 해당 문자열이 숫자로 변환될 수 있는지 여부를 리턴해줌.
search_maximum = int(search_maximum) # 입력값을 int 타입으로 변환
start = time() # 걸린시간 측정용
for n in range(1, search_maximum + 1): # 1부터 입력값 n까지의 for문.
"""함수호출부분"""
n_1 = sum(division(n)) # 현재 n의 진약수를 구한다.
n_2 = sum(division(n_1)) # n의 진약수의 총합의 진약수를 구한다.
"""출력부분"""
if n == n_2 and n < n_1: # 만약 n과 n_1가 친화수(혹은 n과 n_2가 같음)이고, n이 n_1보다 작다면(최적화를 위함)
print([n, n_1]) # 해당 값을 출력한다. list에 넣지 않은 이유는 최적화를 위함.
print("Elapsed Time: {}".format(time() - start)) # 걸린시간 print
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment