생성일: 2019년 11월 26일
수정일: 2023년 07월 25일
수정일: 2023년 07월 25일
4clojure - Longest Increasing Sub-Seq (53)
문제
(= (__ [1 0 1 2 3 0 4 5]) [0 1 2 3])
(= (__ [5 6 1 3 2 7]) [5 6])
(= (__ [2 3 3 4 5]) [3 4 5])
(= (__ [7 6 5 4]) [])
풀이
(fn [x]
(let [v (->> (rest coll)
(reduce #(if (= (inc (last (last %))) %2) (conj % (conj (last %) %2)) (conj % [%2])) [[(first coll)]])
(filter (fn [x] (> (count x) 1)))
(sort)
(last))]
(if (nil? v) [] v)))
풀이과정
reduce를 사용해서 하면 될 것 같으면서도 잘 안된다.
(reduce #(if (> (last (last %)) %2) (conj (last %) %2)) [[1]] [0 1 2 3 0 4 5])
;; Execution error (IllegalArgumentException) at user/eval45$fn (REPL:1). Don't know how to create ISeq from: java.lang.Long
위 오류에 대해서는 중간에 사용하는 함수의 구조를 뜯어보면 알 수 있다.
(last [[1]])
;; [1]
(conj (last [[1]]) 0)
;; [1 0]
위와 같은 식으로 분리가 되기 때문에 반복 될 수록 구조가 맞지 않는 현상이었다.
전체를 남기지 않고 중간에 순서가 있는 값들만 남기면 될 것 같다고 생각을 했다.
(reduce #(if (> (last %) %2) (conj % %2) (conj [] %2)) [1] [0 1 2 3 0 4 5])
;; [5]
vector의 중첩에 대한 문제를 해결 하기 위해서 아래와 같은 형식으로 수정을 했다.
(reduce #(if (> (last (last %)) %2) [(conj (last %) %2)] (conj % [%2])) [[1]] [0 1 2 3 0 4 5])
;; [[3 0] [4] [5]]
(reduce #(if (< (last (last %)) %2) [(conj (last %) %2)] (conj % [%2])) [[1]] [0 1 2 3 0 4 5])
;; [[0 4 5]]
결과적으로는 순차적인 값의 길이를 찾는 방식으로 해야되는데 생각처럼 잘 안되고 있다.
아래 방식으로 일단 식은 만들어봤다
(reduce #(if (< (last (last %)) %2) (conj % (conj (last %) %2)) (conj % [%2])) [[1]] [0 1 2 3 0 4 5])
;; [[1] [0] [0 1] [0 1 2] [0 1 2 3] [0] [0 4] [0 4 5]]
여기에서 sort를 하고 마지막 값을 가져오면 해결 될 것 같다.
(last (sort (reduce #(if (= (inc (last (last %))) %2) (conj % (conj (last %) %2)) (conj % [%2])) [[1]] [0 1 2 3 0 4 5])))
;; [0 1 2 3]
테스트는 거의 통과 했는데 마지막 테스트에서 []값에 대한 처리가 되어 있지 않아 실패를 하였다.
그리고 아래는 위 형식을 검증하기 위한 식이다.
(fn [x]
(last (sort (reduce #(if (= (inc (last (last %))) %2) (conj % (conj (last %) %2)) (conj % [%2])) [[(first x)]] (rest x)))))
어차피 순차적인 값의 길이가 제일 긴 값이 필요한 문제이므로 1개 이상일때의 배열만 필터링을 하는 것이 맞는 것 같다
(filter (fn [x] (> (count x) 1)) (reduce #(if (= (inc (last (last %))) %2) (conj % (conj (last %) %2)) (conj % [%2])) [[1]] [0 1 2 3 0 4 5]))
;; ([0 1] [0 1 2] [0 1 2 3] [4 5])
그리고 나머지는 last sort로 처리를 하면 될 것 같은데 if 가 필요하므로 let으로 local을 만들어 검증을 하였다.
마지막 테스트 때문에 좀 깔끔하게 끝내진 못한 것 같지만 좀 더 깔끔하게 풀기위한 여지는 남겨두려고 한다.
(fn [x]
(let [v (last
(sort
(filter
(fn [x] (> (count x) 1))
(reduce #(if (= (inc (last (last %))) %2) (conj % (conj (last %) %2)) (conj % [%2])) [[(first x)]] (rest x)))))]
(if (nil? v) [] v)))
thread last로 정리 한다.
(fn [x]
(let [v (->> (rest coll)
(reduce #(if (= (inc (last (last %))) %2) (conj % (conj (last %) %2)) (conj % [%2])) [[(first coll)]])
(filter (fn [x] (> (count x) 1)))
(sort)
(last))]
(if (nil? v) [] v)))