생성일: 2019년 11월 16일
수정일: 2022년 10월 29일

4clojure - Rotate Sequence (44)

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

문제

(= (__ 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))))
Tags: 4clojure Today I Learn