Skip to content

Instantly share code, notes, and snippets.

@visibletrap
Last active February 26, 2017 06:36
Show Gist options
  • Save visibletrap/97ecb3a5420986797201a1140a78841c to your computer and use it in GitHub Desktop.
Save visibletrap/97ecb3a5420986797201a1140a78841c to your computer and use it in GitHub Desktop.
(ns my.solve)
(defn prepare-data-structure [arr]
(->> (map-indexed vector arr)
(mapcat
(fn [[i a]]
(map (fn [[j v]] {:val v :idx [i j]})
(map-indexed vector a))))))
(defn expand-adjacents [[i j]]
(set (map (fn [[ifn jfn]] [(ifn i) (jfn j)])
[[dec dec] [dec identity] [dec inc]
[identity dec] [identity inc]
[inc dec] [inc identity] [inc inc]])))
(defn assoc-adjacents [{:keys [idx] :as d}]
(assoc d :adjs (expand-adjacents idx)))
(defn find-group [groups {current-val :val current-adjs :adjs}]
(some (fn [[pos {group-val :val group-indices :member-indices}]]
(when (and (= current-val group-val) (some group-indices current-adjs)) pos))
(map-indexed vector groups)))
(defn distribute-to-group [groups {:keys [val idx] :as e}]
(if-let [pos (find-group groups e)]
(update groups pos (fn [g] (update g :member-indices conj idx)))
(conj groups {:val val :member-indices #{idx}})))
; อธิบายว่าแต่ละขั้นได้ผมลัพธ์เป็นอย่างไรด้านล่าง
(defn adjacent-count [arr]
(->> (prepare-data-structure arr)
(map assoc-adjacents)
(reduce distribute-to-group [])
(map (juxt :val (comp count :member-indices)))))
(adjacent-count [[0, 0, 0, 2, 2],
[1, 1, 7, 4, 4],
[2, 2, 4, 2, 4],
[2, 1, 4, 4, 4],
[2, 7, 7, 4, 4],
[4, 6, 6, 0, 4],
[4, 4, 6, 4, 4],
[4, 4, 6, 4, 4]])
; ([0 3] [2 2] [1 2] [7 1] [4 14] [2 4] [2 1] [1 1] [7 2] [4 5] [6 4] [0 1])
;;;;;;; Explanation starts here
;;;; Step outputs
;;;; ผลลัพธ์ของแต่ละขั้น ยกตัวอย่างมาแค่ 2 บรรทัด output จะได้ไม่ยาวเกินไป
(comment
(->> [[0, 0, 0, 2, 2]
[1, 1, 7, 4, 4]]
; แปลง input ให้เป็น vector 1 มิติ โดยใช้ idx บอกตำแหน่งแทน
(prepare-data-structure)
; ({:val 0, :idx [0 0]} {:val 0, :idx [0 1]} {:val 0, :idx [0 2]}
; {:val 2, :idx [0 3]} {:val 2, :idx [0 4]} {:val 1, :idx [1 0]}
; {:val 1, :idx [1 1]} {:val 7, :idx [1 2]} {:val 4, :idx [1 3]}
; {:val 4, :idx [1 4]})
; ลิสตำแหน่งโดยรอบ idx ไว้ที่ adjs
(map assoc-adjacents)
; ({:val 0, :idx [0 0], :adjs #{[1 0] [-1 0] [1 1] [-1 -1] [1 -1] [-1 1] [0 -1] [0 1]}}
; {:val 0, :idx [0 1], :adjs #{[0 0] [1 0] [-1 0] [1 1] [-1 2] [0 2] [-1 1] [1 2]}}
; {:val 0, :idx [0 2], :adjs #{[1 1] [-1 3] [-1 2] [1 3] [0 3] [-1 1] [1 2] [0 1]}}
; {:val 2, :idx [0 3], :adjs #{[-1 3] [-1 2] [-1 4] [1 4] [1 3] [0 2] [0 4] [1 2]}}
; {:val 2, :idx [0 4], :adjs #{[0 5] [-1 3] [-1 4] [1 4] [-1 5] [1 3] [1 5] [0 3]}}
; {:val 1, :idx [1 0], :adjs #{[0 0] [2 -1] [1 1] [1 -1] [2 0] [2 1] [0 -1] [0 1]}}
; {:val 1, :idx [1 1], :adjs #{[2 2] [0 0] [1 0] [0 2] [2 0] [2 1] [1 2] [0 1]}}
; {:val 7, :idx [1 2], :adjs #{[2 2] [2 3] [1 1] [1 3] [0 3] [0 2] [2 1] [0 1]}}
; {:val 4, :idx [1 3], :adjs #{[2 2] [2 3] [1 4] [0 3] [2 4] [0 2] [0 4] [1 2]}}
; {:val 4, :idx [1 4], :adjs #{[2 3] [2 5] [0 5] [1 3] [1 5] [0 3] [2 4] [0 4]}})
; ดึงทีละตัวมาจับกลุ่มถ้าเจอตัวใกล้เคียง(พิจารณาจาก idx และ adjs) ก็จับมันอยู่กลุ่มเดียวกัน ถ้าไม่มีตัวใกล้เคียงก็สร้างกลุ่มใหม่
(reduce distribute-to-group [])
; [{:val 0, :member-indices #{[0 0] [0 2] [0 1]}}
; {:val 2, :member-indices #{[0 3] [0 4]}}
; {:val 1, :member-indices #{[1 0] [1 1]}}
; {:val 7, :member-indices #{[1 2]}}
; {:val 4, :member-indices #{[1 4] [1 3]}}]
; แปลงให้อยู่ในรูปผลลัพธ์สุดท้ายที่ต้องการ
(map (juxt :val (comp count :member-indices)))))
; ([0 3] [2 2] [1 2] [7 1] [4 2])
;;; Helper function examples
(comment
(expand-adjacents [1 2]))
; #{[2 2] [2 3] [1 1] [1 3] [0 3] [0 2] [2 1] [0 1]}
(comment
(find-group [{:val 1} {:member-indices #{[5 5]}} {:val 0 :member-indices #{[0 0]}} {}]
{:val 0, :idx [0 1], :adjs #{[0 0] [1 0] [-1 0] [1 1] [-1 2] [0 2] [-1 1] [1 2]}}))
; 2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment