Last active
November 11, 2020 00:15
-
-
Save JpOnline/cf6560e24dd8a4efc060fcb2e1d9b871 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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