친화수 구하기

조회수 1891회
def amicable(num):
    a = 0
    for i in range(3, num):
        if num % i == 0:
            a = a + i
    return a

for j in range(1, 500):
    amicable(j)
for k in range(1, 500):
    amicable(k)

if amicable(j) == amicable(k) and j != k:
    print(j, '의 친화수는', k)

친화수를 구하기 위해 코드를 작성해 보았습니다.
여기서 친화수란 어느 한 수의 진약수를 모두 더하면 다른 수가 되는 것을 말합니다.
EX) 220, 284 인데, 220의 진약수는 1,2,4,5,10,11,20,22,44,55,110이고, 모두 더하면 284가 됩니다. 그리고 이 284의 진약수 1,2,4,71,142를 더하면 220이 됩니다. 이런 수를 친화수라고 하는데요
제가 1부터 500사이의 (먼저 간단하게) 친화수를 구해보려고 코드를 작성해 보았는데
결과가 제대로 나오지 않습니다. 어디가 문제일까요?

  • 제대로된 결과라면 1부터 500까지의 친화수를 모두 출력하는건가요? 그러니까 print를 500회 반복하면 되나요? 편집요청빌런 2020.4.7 15:35
  • 네, 1부터 500까지 존재하는 친화수를 검사하는 것이죠. 결과는 친화수만 print하는 것입니다. 알 수 없는 사용자 2020.4.7 15:42
  • 500아래에서는 284와 220뿐입니다. 알 수 없는 사용자 2020.4.7 15:42

3 답변

  • 우선 작성하신 코드 지적질부터 해보면요.

    def amicable(num):
        a = 0
        for i in range(3, num):
            if num % i == 0:
                a = a + i
        return a
    
    for j in range(1, 500):
        amicable(j)
    for k in range(1, 500):
        amicable(k)
    
    if amicable(j) == amicable(k) and j != k:
        print(j, '의 친화수는', k)
    

    여기서

    if amicable(j) == amicable(k) and j != k:
    

    amicable(j)amicable(k)는 호출 표현식입니다. 전체 코드의 모양을 보면 함수 호출은 앞의 반복문에서 끝났어야 할 것 같은데요. 여기서 다시 한 번 함수를 호출하는건 뭔가... 의도와는 전혀 다르게 작성된것으로 보입니다.

    왜냐면 이 시점에서 jk는 무조건 499이기 때문입니다. amicable(499)는 0이므로 0 == 0이라고 작성한것과 마찬가지죠.

    그리고 이어서 오는 j != k499 != 499 이렇게 되는데, 이 부분 역시 의도와는 전혀 관계 없는 이상한 코드가 됩니다.


    rst = []
    def amicable(num):
        a = 0
        for i in range(3, num):
            if num % i == 0:
                a = a + i
        if a != 0:
            rst.append(a)
    
    for i in range(1, 501):
        amicable(i)
    
    rst.sort()
    print(rst)
    

    이런식으로 진약수의 합을 별도로 저장(여기선 rst)해놓은 후에 다시 뭔가를 해야하지 않을까요?

  • 개인적으로 해봤는데 중복되는 부분들을 줄이려면 신경써야 할 것들이 많네요

    약간 무식한 방법으로 구해볼테니 한번 검토해 보시고 줄일 수 있는 부분들은 한번 줄여보시게 좋을 것 같습니다.

    def amicable(num):
        a = 0
        for i in range(1, num // 2 + 1):
            if num % i == 0:
                a += i
        return a
    
    r = []
    for i in range(500):
        r.append(amicable(i))
    

    우선 약수의 합을 더하는 부분을 보면, 예시로 들어주신 것에는 1과 2도 포함되어 있었기 때문에 for문을 3부터 시작하시면 안 됩니다.

    그리고 모든 수는 그 수의 절반보다 큰 수의 배수가 될 수 없으므로, 굳이 1과 target number 사이의 모든 숫자를 확인할 필요도 없습니다.

    윗 분이 리스트에 저장해서 처리를 하는 것에 대해 힌트를 주셨으니 저는 조금 다른 방법을 말씀드리겠습니다.

    x = amicable(y) && y = amicable(x) && x != y 를 만족하는 x와 y 값을 찾는 것이므로

    for i in range(500):
        a = amicable(i)
        if i == amicable(a) and i != a:
            print(i)
    

    이런 방식으로 구할 수 있습니다.

    직접 돌려보시고, 더 빨리 구하기 위해 할 수 있는 일이 뭐가 있을지도 한번 고민해 보세요 ㅎㅎ

  • 초보일 때에는 함수와 변수이름을 한글로 지어보는 것이 도움이 될 수 있다고 봐요.

    질문자의 코드에서 amicable 은 사실 친화수를 구하는 함수가 아니라, 진약수의합을 구하는 함수죠.

    >>> def 진약수의합(n):
        s = 0
        for i in range(1, n):
            if n%i == 0:
                s += i
        return s
    
    >>> def 친화수쌍구하기(N):
        친화수쌍 = []
        for i in range(N+1):
            s = 진약수의합(i)
            if i == 진약수의합(s):
                친화수쌍.append((i, s))
        return 친화수쌍
    
    >>> 친화수쌍구하기(500)
    [(0, 0), (6, 6), (28, 28), (220, 284), (284, 220), (496, 496)]
    >>> def 친화수쌍구하기(N):
        친화수쌍 = []
        for i in range(N+1):
            s = 진약수의합(i)
            if i != s and i == 진약수의합(s):
                친화수쌍.append((i, s))
        return 친화수쌍
    
    >>> 친화수쌍구하기(500)
    [(220, 284), (284, 220)]
    

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)