생성일: 2019년 12월 16일
수정일: 2023년 08월 10일

4clojure - Merge with a Function (69)

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

문제

(= (__ * {:a 2, :b 3, :c 4} {:a 2} {:b 2} {:c 5})
   {:a 4, :b 6, :c 20})

(= (__ - {1 10, 2 20} {1 3, 2 10, 3 15})
   {1 7, 2 10, 3 15})

(= (__ concat {:a [3], :b [6]} {:a [4 5], :c [8 9]} {:b [7]})
   {:a [3 4 5], :b [6 7], :c [8 9]})

제한: merge-with

풀이

(fn a [f & args]
	(let [k (keys (apply merge args))
		  ca (fn [c coll] 
				(let [v (filter #(not= % nil) (map #(% c) coll))]
					(if (> (count v) 1) {c (apply f v)} 
						{c (first v)})))] 
		(loop [ke k
				result {}]
			(if (empty? ke) result
				(recur (rest ke) (into result (ca (first ke) args)))))))

풀이 과정

첫번째 식에 대한 풀이를 이렇게 하면 되지 않을까 해서 만들어 봤다.

(assoc {:a 2 :b 3 :c 4} :a (* ({:a 2 :b 3 :c 4} :a) 2))
;; {:a 4, :b 3, :c 4}

근데 위의 식을 reduce로 엮어서 하려리 잘 되지 않는다..

우선 아래의 순서대로 알고리즘을 작성을 하는 것이 좋을 것 같다.

  1. 모든 항목을 찾는다.
  2. 같은 항목을 가진 값에 연산을 적용 한다.
  3. 2를 반복 한다.

없는 항목이 없도록 모든 항목을 찾는다.

(keys (merge {:a 2, :b 3, :c 4} {:a 2} {:b 2} {:c 5}))
;; (:a :b :c)

같은 항목을 가진 값에 연산을 적용 한다.

(apply * (filter #(not= % nil) (map :a '({:a 2, :b 3, :c 4} {:a 2} {:b 2} {:c 5}))))
;; 4

숫자에 대한 연산이 되지 않아 아래와 같이 변경 한다.

(apply * (filter #(not= % nil) (map #(% :a) '({:a 2, :b 3, :c 4} {:a 2} {:b 2} {:c 5}))))
;; 4

그리고 알고리즘은 아래와 같이 변경 된다.

  1. 모든 항목을 찾는다.
  2. 2개 이상의 같은 항목을 가진 값에 연산을 적용 한다.
  3. 2를 반복 한다.
(fn a [f & args]
	(let [k (keys (apply merge args))
		  ca (fn [c coll] 
				(let [v (filter #(not= % nil) (map #(% c) 									coll))]
					(if (> (count v) 1) {c (apply f v)} 
						{c (first v)})))] 
		(loop [ke k
				result {}]
			(if (empty? ke) result
				(recur (rest ke) (into result (ca (first ke) args)))))))	
                	

생각했던 알고리즘에 비해서 계산식이 너무 복잡하게 나왔다. 이런 것이 잘못된 개념화를 나타내는 것이라는 생각이 든다. 좀 더 개념화를 잘 하기 위해서는 어떤 것을 해야할까? 내가 이 문제를 푸는데 있어서 생각했던 마음가짐이 무엇이었는지 생각해 보는 것도 의미가 있을 것 같다. 나도 모르게 빨리 풀어야한다는 급한 마음에서 이런 풀이가 나온 것 같고, 좀 더 개념화를 위해서 생각을 하는 시간이 더 필요하다는 것을 알게 된 것 같다.

짧게 문제를 푼 사람들은 어떤 개념화를 했는지 분석해보는 것도 의미가 있을 것 같다.

  1. 항목을 선택 한다.
  2. 공통된 항목이 여러개 있으면 값의 연산을 수행한다.
  3. 1을 반복 한다. 이런 개념화를 하지 않았을까?하는 추측을 해본다.
Tags: 4clojure Today I Learn