생성일: 2020년 01월 01일
수정일: 2023년 08월 22일

4clojure - Perfect Numbers (80)

  1. 문제
  2. 풀이
    1. 풀이과정

문제

(= (__ 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를 활용하는 방법을 사용하지 않았다는 데에서 뿌듯함을 느끼고 있다.

Tags: 4clojure Today I Learn