수정일: 2022년 10월 29일
4clojure - Rotate Sequence (44)
문제
(= (__ 2 [1 2 3 4 5]) '(3 4 5 1 2))
(= (__ -2 [1 2 3 4 5]) '(4 5 1 2 3))
(= (__ 6 [1 2 3 4 5]) '(2 3 4 5 1))
(= (__ 1 '(:a :b :c)) '(:b :c :a))
(= (__ -4 '(:a :b :c)) '(:c :a :b))
풀이
(fn [n coll]
(let [cnt (count coll)
m (mod n cnt)]
(apply concat (list (drop m coll) (take m coll)))))
풀이 과정
partition-by를 사용하면 그룹으로 묶어주는 방법이 있다고 생각 했다.
(partition-by #(>= 1 %) [1 2 3 4 5])
;; ((1) (2 3 4 5))
위의 결과를 뒤집어서 합치면 되는데 into로 넣는 방법이 생각 났다.
(into '() (partition-by #(>= 1 %) [1 2 3 4 5]))
;; ((2 3 4 5) (1))
이 결과를 가지고 이제 합치기만 하면 되므로 concat을 사용 했다.
(apply concat (into '() (partition-by #(>= 1 %) [1 2 3 4 5])))
;; (2 3 4 5 1)
여기까지의 결과만 보고 잘 된 것이라 생각 했는데 ‘(:a :b :c)에 대한 검증을 통과하지 못하므로 다시 해야된다.
index가 필요하다 판단이 들어서 iterate로 index 조합을 만들었다.
(interleave (iterate inc 0) [1 2 3 4 5])
;; (0 1 1 2 2 3 3 4 4 5)
이렇게 하면 인덱스와 값이 구분이 되지 않으므로 묶는 작업이 필요하다
(partition 2 (interleave (iterate inc 0) [1 2 3 4 5]))
;; ((0 1) (1 2) (2 3) (3 4) (4 5))
만들다보니 보기가 불편해서 ->> 로 보기 편하게 변형 했다.
(->> (interleave (iterate inc 0) [1 2 3 4 5])
(partition 2))
;; ((0 1) (1 2) (2 3) (3 4) (4 5))
이제 first 값을 인덱스로 해서 검증을 하면 된다.
(->> (interleave (iterate inc 0) [1 2 3 4 5])
(partition 2)
(partition-by #(>= 1 (first %))))
;; (((0 1) (1 2)) ((2 3) (3 4) (4 5)))
점점 괄호가 많아지는데 저걸 어떻게 한번에 없애면서 last 값만 가져오는지 고민이 필요하다.
문제를 고민하다가 아무래도 저 안에서 빠져나오지 못할 것 같아서 문제에 대한 search를 했다.
근데 그대로 답을 사용하긴 좀 그래서 mod만 참조를 하고 나머지는 내 생각으로 하기로 했다.
우선 mod는 나머지를 구하는 함수이다. rem과의 차이점은 아래 결과이다.
(mod 6 -5)
;; -4 -> (-5 * -2) + -4
(rem 6 -5)
;; 1 -> (-5 * -1) + 1
(mod 6 -10)
;; -4 -> (-10 * -1) -4
(rem 6 -10)
;; 6 -> (-10 * 0) + 6
위 문제에 있는 vector의 count와 적용을 한다면
(mod -2 5)
;; 3 -> (5 * -1) + 3
(rem -2 5)
;; -2 -> (5 * 0) -2
(mod -4 3)
;; 2 -> (3 * -2) +2
(rem -4 3)
;; -1 -> (3 * -1) -1
풀이를 만들어 보고 나서도 왜 저렇게 계산을 다르게 해야 되는건지 이해가 잘 가지는 않는다. 계산식을 만들어보면서 어떻게 하면 저 값이 나오는지 생각을 하면서 하다보니 수학 공부를 다시 하게 되는 느낌이었다.
last-take를 할 필요 없이 drop을 사용해서도 문제가 간단하게 풀릴수 있을 것 같아서 사용을 했고, flatten 보다는 apply concat을 사용하여 좀 더 내 생각을 넣도록 문제를 풀었다.
(fn [n coll]
(let [cnt (count coll)
m (mod n cnt)]
(apply concat (list (drop m coll) (take m coll)))))
근데 생각을 해보니 아래와 같이 좀 더 줄여서도 가능 할 것 같다.
(fn [n coll]
(let [m (mod n (count coll))]
(concat (drop m coll) (take m coll))))