생성일: 2020년 01월 01일
수정일: 2023년 08월 22일
수정일: 2023년 08월 22일
4clojure - Perfect Numbers (80)
문제
(= (__ 6) true)
(= (__ 7) false)
(= (__ 496) true)
(= (__ 500) false)
(= (__ 8128) true)
풀이
(fn [x]
(let [y (filter #(= (mod x %) 0) (range 1 (+ (int (Math/sqrt x)) 1)))]
(->> (reduce #(conj % (quot x %2)) y y)
(filter #(not= x %))
(apply +)
(= x))))
풀이과정
완전수를 구하는 문제이다. 제곱근의 약수를 구한 다음에 그 수와 나눠지는 수들을 저장 후 자신을 제외한 나머지 수의 합을 구하는 방법을 사용 했다.
제곱근 이상으로는 약수가 반복적이므로 제곱근에 대한 수를 구했다.
(take (int (Math/sqrt 28)) (iterate inc 1))
;; (1 2 3 4 5)
여기에 나눠서 나머지가 0이되는 값을 구했다.
(filter #(= (mod 28 %) 0) (take (int (Math/sqrt 28)) (iterate inc 1)))
;; (1 2 4)
그 후, 제곱근 이상의 약수를 구했다.
(reduce #(conj % (quot 28 %2)) (filter #(= (mod 28 %) 0) (take (int (Math/sqrt 28)) (iterate inc 1))) [1 2 4])
;; (7 14 28 1 2 4)
자기 자신은 걸러내고
(filter #(not= 28 %) (reduce #(conj % (quot 28 %2)) (filter #(= (mod 28 %) 0) (take (int (Math/sqrt 28)) (iterate inc 1))) [1 2 4]))
;; (7 14 1 2 4)
그 값들을 더해주면 된다.
(apply + (filter #(not= 28 %) (reduce #(conj % (quot 28 %2)) (filter #(= (mod 28 %) 0) (take (int (Math/sqrt 28)) (iterate inc 1))) [1 2 4])))
;; 28
이것을 테스트 하기 위한 함수 이다.
(fn [x]
(let [y (filter #(= (mod x %) 0) (take (int (Math/sqrt x)) (iterate inc 1)))]
(->> (reduce #(conj % (quot x %2)) y y)
(filter #(not= x %))
(apply +)
(= x))))
좀 길게 쓴 감이 없지않아 있긴 하지만 약수를 구하는 방법과 그것을 활용하는 그리고, 전통적인 for를 활용하는 방법을 사용하지 않았다는 데에서 뿌듯함을 느끼고 있다.