생성일: 2019년 11월 26일
수정일: 2023년 07월 25일

4clojure - Longest Increasing Sub-Seq (53)

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

문제

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