Skip to content

Instantly share code, notes, and snippets.

@JpOnline
Last active November 11, 2020 00:15
Show Gist options
  • Save JpOnline/cf6560e24dd8a4efc060fcb2e1d9b871 to your computer and use it in GitHub Desktop.
Save JpOnline/cf6560e24dd8a4efc060fcb2e1d9b871 to your computer and use it in GitHub Desktop.
(ns ms)
(defn board->pos-map [board]
(into {} (flatten (map-indexed (fn [i line] (map-indexed (fn [j c] {[i j] c}) line)) board))))
(defn stat-pos-map->board [pos-map]
(mapv #(clojure.string/join \space (map second %))
(partition-by ffirst (sort pos-map))))
(defn get-adjacents [pos-map [i j]]
(remove (comp nil? second) (for [fn-i [inc dec identity]
fn-j [inc dec identity]
:when (not= [fn-i fn-j] [identity identity])
:when (#{\? \x} (pos-map [(fn-i i) (fn-j j)]))]
[[(fn-i i) (fn-j j)] (pos-map [(fn-i i) (fn-j j)])])))
(defn process-pos [pos-map pos]
(let [adjacents (get-adjacents pos-map pos)
adj-x (filter (comp #{\x} second) adjacents)
adj-? (filter (comp #{\?} second) adjacents)]
(cond
(= (count adj-?) (- (Integer/parseInt (str (pos-map pos))) (count adj-x)))
(reduce #(assoc %1 %2 \x) pos-map (map first adj-?))
(zero? (- (Integer/parseInt (str (pos-map pos))) (count adj-x)))
(reduce #(assoc %1 %2 \.) pos-map (map first adj-?))
:else
pos-map)))
(defn positions-with-number [pos-map]
(let [ch-nbr? (set (map char (range 49 57)))]
(filter (comp ch-nbr? val) pos-map)))
(defn impossible-board? [pos-map]
(let [poss-with-number (positions-with-number pos-map)
count-? (count (filter (comp #{\?} val) pos-map))
count-adj-x #(count (filter (comp #{\x} second) (get-adjacents pos-map %)))
wrong-nbr-x? (fn [[pos c]]
(not= (count-adj-x pos) (Integer/parseInt (str c))))]
(and (zero? count-?)
(some wrong-nbr-x? poss-with-number))))
(defn process-numbers [pos-map]
(let [poss-with-number (map first (positions-with-number pos-map))
result (reduce process-pos pos-map poss-with-number)]
(cond
(not= pos-map result)
(recur result)
(impossible-board? result)
nil
:else
result)))
(defn possible-results [pos-map]
(loop [[pos-map & pos-maps-to-process] [pos-map]
final-boards []]
(let [pos-map (process-numbers pos-map)
question-pos (filter (comp #{\?} second) pos-map)
expand-questions #(-> (first %)
(as-> pos (assoc pos-map pos \x))
(process-numbers))
new-boards (->> question-pos (map expand-questions) (distinct) (remove empty?))]
(cond
(empty? pos-map)
(distinct final-boards)
(empty? question-pos)
(recur pos-maps-to-process (conj final-boards pos-map))
:else
(recur (concat pos-maps-to-process new-boards) final-boards)))))
(defn compute-stats [pos-map]
(let [possibilities (possible-results pos-map)
ch-nbr? (set (map char (range 49 57)))
position-percentage #(quot (* 100 (count (filter #{\x} (map (fn [possibility] (possibility %)) possibilities)))) (count possibilities))]
(map (fn [[pos c]]
(cond
(= c \?)
[pos (str (position-percentage pos)"%")]
(= c \.)
[pos "..."]
(= c \x)
[pos "-x-"]
(ch-nbr? c)
[pos (str "-"c"-")]
:else
[pos c]))
pos-map)))
(defn print-board [lines-coll]
(print (clojure.string/join \newline lines-coll)))
(defn ps [board]
(-> board board->pos-map compute-stats stat-pos-map->board))
(comment
(ps [".?1.."
"??332"
"23xxx"
"?23?."
"?21??"
"x222?"
"?????"])
(print-board
(stat-pos-map->board
(compute-stats
(board->pos-map
[".?1."
"??3."
"?3xx"
"?23?"
"????"]))))
)
(= ["... 47% -1- ... ..."
"52% 52% -3- -3- -2-"
"-2- -3- -x- -x- -x-"
"94% -2- -3- 42% ..."
"5% -2- -1- 57% 21%"
"-x- -2- -2- -2- 21%"
"10% 63% 21% 57% 21%"]
(ps [".?1.."
"??332"
"23xxx"
"?23?."
"?21??"
"x222?"
"?????"]))
(= (stat-pos-map->board
(compute-stats
(board->pos-map [".1"
"??"])))
["... -1-"
"50% 50%"])
(= (map pos-map->board
(possible-results (board->pos-map [".13?"
"????"])))
'([".13x"
"..xx"]
[".13x"
".x.x"]))
(= (impossible-board? (board->pos-map [".11"
"x.."]))
true)
(= (map pos-map->board
(possible-results (board->pos-map [".11"
"???"])))
'([".11"
".x."]
[".11"
"..x"]))
(= (pos-map->board
(process-numbers (board->pos-map [".11"
"?.?"])))
[".11"
"..x"])
(= (pos-map->board
(process-pos (board->pos-map [".11"
"?.x"]) [0 1]))
[".11"
"..x"])
(= (pos-map->board
(process-pos (board->pos-map [".21"
"?.x"]) [0 1]))
[".21"
"x.x"])
(= (pos-map->board
(process-pos (board->pos-map [".11"
"?.?"]) [0 2]))
[".11"
"?.x"])
(= (pos-map->board
(process-pos (board->pos-map ["..?"
".1?"
"..."]) [1 1]))
["..?"
".1?"
"..."])
(= (pos-map->board
(process-pos (board->pos-map ["..?"
".1?"
"..."]) [1 1]))
["..?"
".1?"
"..."])
(= (pos-map->board
(process-pos (board->pos-map ["..?"
".2?"
"..."]) [1 1]))
["..x"
".2x"
"..."])
(= (pos-map->board
(process-pos (board->pos-map ["???"
"?8?"
"???"]) [1 1]))
["xxx"
"x8x"
"xxx"])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment