프로젝트 오일러 30

내 이 세상 도처에서 쉴 곳을 찾아보았으나, 마침내 찾아낸, 컴퓨터가 있는 구석방보다 나은 곳은 없더라.

프로젝트 오일러 30

각 자리 숫자를 5제곱해서 더했을 때 자기 자신이 되는 수들의 합은?

문제 자세히 보기: [국어] [영어]

이 문제는 무차별 대입법으로 풀 수 있다. 다만 루프를 무한히 반복하지 않으려면 상한을 알아야 한다. 6자리 수 중 가장 큰 정수는 999,999다. 이 수의 각 자리 숫자를 5제곱해 더하면 354,294가 된다. 즉 6자리 수 중 가장 큰 정수의 각 자릿수를 5제곱해 더해도 354,294보다 큰 수는 못 만든다는 뜻이다.

%math 6 \times 9^5 = 354,294

7자리 수 중 가장 가장 큰 정수는 9,999,999이고, 이 수의 각 자리 숫자를 5제곱해 더하면 413,343이 된다. 즉 7자리 수 중 가장 큰 수에 대해서 각 자리 숫자를 5제곱해 더했을 때 만들어지는 수가 6자리이므로, 7자리 수 중에는 문제의 조건을 만족하는 수가 없다고 할 수 있다.

%math 7 \times 9^5 = 413,343

8자리 이상의 수에 대해서도 마찬가지임을 확인할 수 있다. 따라서 문제의 조건을 만족하는 수는 6자리 이하여야 하며, 6자리 수 중 가장 큰 수인 999,999에 대해 각 자리 숫자를 5제곱해 더했을 때 만들 수 있는 수인 354,294를 상한으로 잡을 수 있다.

나머지는 평이하다. 각 자리 숫자를 5제곱해 더한 값을 구하는 함수는 다음과 같이 작성할 수 있다.

(defn sum-of-5th-power-of-digits [n]
  (->> (digits n)
       (map (fn [x] (pow x 5)))
       (apply +)))

위 함수에서 사용하는 digitspow문제 16에서 설명했다.

풀이는 다음과 같이 작성할 수 있다. 문제에서 1은 제외한다고 했으므로, 2부터 시작해 위에서 구한 상한 354,294까지의 수에 대해 주어진 조건을 만족하는 수만 추려낸 다음 이들의 합을 구하면 된다.

(defn solve []
  (->> (range 2 354294)
       (filter #(= % (sum-of-5th-power-of-digits %)))
       (apply +)))

실행 결과는 다음과 같다.

p030=> (time (solve))
"Elapsed time: 514.028633 msecs"
4438??

참고