Skip to content

Instantly share code, notes, and snippets.

@pallix
Created November 1, 2013 13:51
Show Gist options
  • Save pallix/7265727 to your computer and use it in GitHub Desktop.
Save pallix/7265727 to your computer and use it in GitHub Desktop.
(ns flood.core)
(defn get-row
[matrix y]
(get matrix (- (dec (count matrix)) y)))
(defn assoc-xy
[matrix x y v]
(assoc-in matrix [(- (dec (count matrix)) y) x] v))
(defn get-xy
[matrix x y]
(get (get-row matrix y) x))
(defn print-matrix
[matrix]
(doseq [row matrix]
(println row)))
(defn fill-column
[matrix x high v]
(reduce (fn [matrix level]
(assoc-xy matrix x level v))
matrix
(range high)))
(defn assign-topology
[matrix problem]
(:matrix
(reduce (fn [{:keys [matrix index] :as acc} high]
(assoc acc
:matrix (fill-column matrix index high 1)
:index (inc index)))
{:matrix matrix
:index 0}
problem)))
(defn create-matrix
[problem]
(let [matrix (vec (repeatedly (count problem) #(vec (take 8 (repeat 2)))))
matrix (assign-topology matrix problem)]
matrix))
(defn flooded?
[v]
(= v 2))
(defn dry?
[v]
(= v 0))
(defn flooded-area-in-row
"Returns the indices of the flooded area in a row."
[row]
(reverse
(:area
(reduce (fn [{:keys [area pred-is-flooded index] :as acc} v]
(cond (and (flooded? v) pred-is-flooded)
(let [head (conj (first area) index)]
(assoc acc
:area (conj (rest area) head)
:index (inc index)
:pred-is-flooded true))
(flooded? v)
(assoc acc
:area (conj area [index])
:index (inc index)
:pred-is-flooded true)
:else (assoc acc
:index (inc index)
:pred-is-flooded false)))
{:pred-is-flooded false
:area ()
:index 0}
row))))
(defn flow
[matrix])
(defn can-flow-left?
[matrix x y]
(or (= x 0)
(dry? (get-xy matrix (dec x) y))))
(defn can-flow-right?
[matrix x y]
(or (= x (dec (count matrix)))
(dry? (get-xy matrix (inc x) y))))
(defn can-flow?
[matrix x y]
(and (can-flow-left? matrix x y)
(can-flow-right? matrix x y)))
(defn dry-cell
[matrix x y]
(reduce (fn [matrix offset]
(assoc-xy matrix x (+ y offset) 0))
matrix
(range (- (count matrix) y))))
(defn try-dry-cell
[matrix x y]
(if (or (can-flow-left? matrix x y)
(can-flow-right? matrix x y))
(dry-cell matrix x y)
matrix))
(defn dry-row
[matrix y]
(let [area (flooded-area-in-row (get-row matrix y))]
(reduce (fn [matrix one-area]
(let [front (first one-area)
back (last one-area)
middle (butlast (rest one-area))
matrix (try-dry-cell matrix front y)
matrix (if (nil? middle) matrix
(reduce (fn [matrix x]
(try-dry-cell matrix x y))
matrix middle))
matrix (if (nil? back) matrix
(try-dry-cell matrix back y))]
matrix))
matrix
area)))
(defn dry-matrix
[matrix]
(reduce (fn [matrix y]
(dry-row matrix y))
matrix
(range (count matrix))))
(defn find-solution
[matrix]
(some (fn [[m1 m2]]
(when (= m1 m2)
m1))
(partition 2 (iterate dry-matrix matrix))))
(def problem1 [2 3 1 1 3 2 1 1])
(def problem2 [2 3 1 1 3 2 1 2])
(defn -main
[]
(print-matrix (find-solution (create-matrix problem1))))
;; (-main)
@pallix
Copy link
Author

pallix commented Nov 1, 2013

the dry-row function should call try-dry-cell on the back element before calling it on the middle elements

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment