Skip to content

Instantly share code, notes, and snippets.

@seltzer1717
Last active June 24, 2021 14:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save seltzer1717/7da77b1dc0944ee4c5e994373544dbc8 to your computer and use it in GitHub Desktop.
Save seltzer1717/7da77b1dc0944ee4c5e994373544dbc8 to your computer and use it in GitHub Desktop.
(ns cloud.seltzer1717.island)
(defn border-fn
[sample]
(let [rows (count sample)
cols (count (first sample))]
(fn [[row col]]
(or (= 0 row)
(= 0 col)
(= (dec rows) row)
(= (dec cols) col)))))
(defn walk-fn
[sample]
(fn [[row col]]
(let [north [(dec row) col]
south [(inc row) col]
east [row (inc col)]
west [row (dec col)]
steps [north south east west]
rows (count sample)
cols (count (first sample))
inbd? (fn [[row col]]
(and (<= 0 row (dec rows))
(<= 0 col (dec cols))))]
(filterv inbd? steps))))
(defn walking-fn
[sample]
(fn [step]
(let [walk (walk-fn sample)
border? (border-fn sample)]
(loop [steps [step]
land #{}]
(if (not-empty steps)
(let [vl (get-in sample (first steps))]
(recur (case vl
0 (subvec steps 1)
1 (apply conj (subvec steps 1)
(filterv #(not (contains? land %))
(walk (first steps)))))
(case vl
0 land
1 (conj land (first steps)))))
land)))))
(defn remove-islands
[sample]
(let [walking (walking-fn sample)
border? (border-fn sample)
rows (count sample)
cols (count (first sample))]
(loop [output sample
shore #{}
island #{}
row 1
col 1]
(if (and (<= 1 row (- rows 2))
(<= 1 col (- cols 2)))
(if (and (not (contains? shore [row col]))
(not (contains? island [row col])))
(let [steps (walking [row col])
island? (not-any? border? steps)]
(recur (if island?
(reduce (fn [output step] (update-in output step (constantly 0)))
output
steps)
output)
(if island? shore (apply conj shore steps))
(if island? (apply conj island steps) island)
(if (= 4 col) (inc row) row)
(if (= 4 col) 1 (inc col))))
(recur output
shore
island
(if (= 4 col) (inc row) row)
(if (= 4 col) 1 (inc col))))
output))))
(ns cloud.seltzer1717.island-test
(:require [clojure.test :as test]
[cloud.seltzer1717.island :as island]))
(test/with-test
(def sample
[[1 0 0 0 0 0]
[0 1 0 1 1 1]
[0 0 1 0 1 0]
[1 1 0 0 1 0]
[1 0 1 1 0 0]
[1 0 0 0 0 1]])
(def border? (island/border-fn sample))
(test/is (= true (border? [0 3])))
(test/is (= true (border? [4 0])))
(test/is (= false (border? [1 3])))
(test/is (= true (border? [1 5])))
(test/is (= true (border? [5 3])))
(def walk (island/walk-fn sample))
(test/is (= [[0 1] [2 1] [1 2] [1 0]] (walk [1 1])))
(test/is (= [[1 2] [3 2] [2 3] [2 1]] (walk [2 2])))
(test/is (= [[2 0] [4 0] [3 1]] (walk [3 0])))
(test/is (= [[1 4] [0 5] [0 3]] (walk [0 4])))
(test/is (= [[4 2] [5 3] [5 1]] (walk [5 2])))
(test/is (= [[2 5] [4 5] [3 4]] (walk [3 5])))
(def walking (island/walking-fn sample))
(test/is (= #{[2 4] [3 4] [1 4] [1 3] [1 5]} (walking [2 4])))
(test/is (= #{[1 1]} (walking [1 1])))
(test/is (= #{} (walking [1 2])))
(test/deftest remove-the-islands
(def sample-output
[[1 0 0 0 0 0]
[0 0 0 1 1 1]
[0 0 0 0 1 0]
[1 1 0 0 1 0]
[1 0 0 0 0 0]
[1 0 0 0 0 1]])
(test/is (= sample-output (island/remove-islands sample)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment