diff options
| author | Tyler Wardhaugh <twardhaugh@cap-rx.com> | 2021-08-20 15:01:54 -0700 |
|---|---|---|
| committer | Tyler Wardhaugh <twardhaugh@cap-rx.com> | 2021-08-20 15:29:38 -0700 |
| commit | c7e2cecd699ec6e66c65e4632a8be45b13930729 (patch) | |
| tree | 3ed2ce2f7ec5bf95724d3642706169b130e50749 | |
| parent | c59cc827374bbf39f4e0c999aa73c86667541210 (diff) | |
| download | perlweeklychallenge-club-c7e2cecd699ec6e66c65e4632a8be45b13930729.tar.gz perlweeklychallenge-club-c7e2cecd699ec6e66c65e4632a8be45b13930729.tar.bz2 perlweeklychallenge-club-c7e2cecd699ec6e66c65e4632a8be45b13930729.zip | |
Ch126 (Clojure): Task 2
8 files changed, 107 insertions, 12 deletions
diff --git a/challenge-126/tyler-wardhaugh/clojure/README.md b/challenge-126/tyler-wardhaugh/clojure/README.md index 118d7b558d..99185b88b1 100644 --- a/challenge-126/tyler-wardhaugh/clojure/README.md +++ b/challenge-126/tyler-wardhaugh/clojure/README.md @@ -15,7 +15,7 @@ Run the project directly (shows default output from both tasks): Run the project's tests (which are samples from the task descriptions): - $ clojure -M:test:runner + $ clojure -X:test # ... or ... $ bb run test @@ -27,9 +27,9 @@ Run Task #1 with input Run Task #2 with input: - $ clojure -M -m tw.weekly.c126.t2 + $ clojure -M -m tw.weekly.c126.t2 F # ... or ... - $ bb run task-2 + $ bb run task-2 F View available tasks Babashka can run: diff --git a/challenge-126/tyler-wardhaugh/clojure/bb.edn b/challenge-126/tyler-wardhaugh/clojure/bb.edn index 0c49645ba4..463fcb5d14 100644 --- a/challenge-126/tyler-wardhaugh/clojure/bb.edn +++ b/challenge-126/tyler-wardhaugh/clojure/bb.edn @@ -69,7 +69,9 @@ :task (run-task :t2 *command-line-args*)} task-2-bb {:doc "Run Task 2 (via Babashka)" - :task (run-task-bb :t2 *command-line-args*)} + :task (binding [*out* *err*] + (println "error: can't run Task 2 via Babashka because it depends on some incompatible libraries.") + (System/exit 1))} both {:doc "Run both tasks (via clojure)" :task (do diff --git a/challenge-126/tyler-wardhaugh/clojure/deps.edn b/challenge-126/tyler-wardhaugh/clojure/deps.edn index 5b1400b27e..54198fdfe8 100644 --- a/challenge-126/tyler-wardhaugh/clojure/deps.edn +++ b/challenge-126/tyler-wardhaugh/clojure/deps.edn @@ -1,5 +1,6 @@ {:paths ["src" "resources"] - :deps {org.clojure/clojure {:mvn/version "1.10.3"}} + :deps {org.clojure/clojure {:mvn/version "1.10.3"} + net.mikera/core.matrix {:mvn/version "0.62.0"}} :aliases {:test {:extra-paths ["test"] :extra-deps {org.clojure/test.check {:mvn/version "1.1.0"} diff --git a/challenge-126/tyler-wardhaugh/clojure/pom.xml b/challenge-126/tyler-wardhaugh/clojure/pom.xml index 16891bbc7c..968dd8f7e9 100644 --- a/challenge-126/tyler-wardhaugh/clojure/pom.xml +++ b/challenge-126/tyler-wardhaugh/clojure/pom.xml @@ -24,6 +24,11 @@ <artifactId>clojure</artifactId> <version>1.10.3</version> </dependency> + <dependency> + <groupId>net.mikera</groupId> + <artifactId>core.matrix</artifactId> + <version>0.62.0</version> + </dependency> </dependencies> <build> <sourceDirectory>src</sourceDirectory> diff --git a/challenge-126/tyler-wardhaugh/clojure/resources/matrix.txt b/challenge-126/tyler-wardhaugh/clojure/resources/matrix.txt new file mode 100644 index 0000000000..e211219443 --- /dev/null +++ b/challenge-126/tyler-wardhaugh/clojure/resources/matrix.txt @@ -0,0 +1,5 @@ +x * * * x * x x x x +* * * * * * * * * x +* * * * x * x * x * +* * * x x * * * * * +x * * * x * * * * x diff --git a/challenge-126/tyler-wardhaugh/clojure/src/tw/weekly/c126/matrix_util.clj b/challenge-126/tyler-wardhaugh/clojure/src/tw/weekly/c126/matrix_util.clj new file mode 100644 index 0000000000..63da586c8d --- /dev/null +++ b/challenge-126/tyler-wardhaugh/clojure/src/tw/weekly/c126/matrix_util.clj @@ -0,0 +1,44 @@ +(ns tw.weekly.c126.matrix-util + (:require [clojure.java.io :as io] + [clojure.pprint :as pp] + [clojure.string :as str] + [clojure.core.matrix :as m])) + +(defn parse-matrix-file + "Parse a matrix file and return a matrix" + ([matrix-file] + (parse-matrix-file matrix-file (comp))) + ([matrix-file xf] + (with-open [in (io/reader matrix-file)] + (into [] xf (line-seq in))))) + +(defn extend-matrix + "Surround the matrix in a 'border' of 0s. That is, add rows before the first and after the last rows and add columns before + the first and after the last columns." + [mat] + (let [n (m/dimension-count mat 1) + blank-row (vec (repeat (+ n 2) 0)) + step-1 (reduce (fn [mat v] (conj mat (vec (concat [0] v [0])))) [blank-row] mat)] + (conj step-1 blank-row))) + +(defn rotate-matrix + "Rotate a matrix counterclockwise" + [mat] + (-> mat m/transpose reverse)) + +(defn print-matrix + ([mat] + (print-matrix mat true)) + ([mat stream] + (pp/cl-format stream "~{~{~a~^ ~}~%~}" mat))) + +(defn pprint-matrix + "Pretty print a matrix" + [mat] + (let [ks (range (m/dimension-count mat 1)) + tbl (with-out-str + (pp/print-table ks (map (partial zipmap ks) mat)))] + (-> tbl + (str/split #"\n") + (->> (drop 3) + (run! println))))) diff --git a/challenge-126/tyler-wardhaugh/clojure/src/tw/weekly/c126/t2.clj b/challenge-126/tyler-wardhaugh/clojure/src/tw/weekly/c126/t2.clj index 2861e120b7..e85360bcaa 100644 --- a/challenge-126/tyler-wardhaugh/clojure/src/tw/weekly/c126/t2.clj +++ b/challenge-126/tyler-wardhaugh/clojure/src/tw/weekly/c126/t2.clj @@ -1,16 +1,44 @@ (ns tw.weekly.c126.t2 (:require [clojure.edn :as edn] + [clojure.java.io :as io] [clojure.string :as str] - [clojure.math.numeric-tower :refer [abs]])) + [clojure.core.matrix :as m] + [tw.weekly.c126.matrix-util :as mu])) ;;; -; Task description for TASK #2 › Clock Angle +; Task description for TASK #2 › Minesweeper Game ;;; -(def DEFAULT-INPUT []) +(def DEFAULT-INPUT [(io/resource "matrix.txt")]) +(def MINE \x) +(def FREE \*) + +(defn parse + [f] + (->> (mu/parse-matrix-file + f + (map (comp + #(map edn/read-string %) + #(str/split % #" ") + #(str/escape % {MINE -1, FREE 0})))) + (m/array :ndarry))) + +(defn count-neighboring-mines [mat] + (let [emat (mu/extend-matrix mat)] + (fn [[i j] v] + (if (neg? v) + MINE + (->> (m/submatrix emat i 3 j 3) + m/eseq + (filter neg?) + count))))) + +(defn minesweeper + [mat] + (m/emap-indexed (count-neighboring-mines mat) mat)) (defn -main - "Run Task 2 with a given input N, defaulting to the first example from the + "Run Task 2 with a given input, defaulting to the first example from the task description." [& args] - (let [[T] (or args DEFAULT-INPUT)] - )) + (let [[F] (or (some->> args (map (comp io/file edn/read-string))) DEFAULT-INPUT)] + (-> F parse minesweeper mu/print-matrix))) diff --git a/challenge-126/tyler-wardhaugh/clojure/test/tw/weekly/c126_test.clj b/challenge-126/tyler-wardhaugh/clojure/test/tw/weekly/c126_test.clj index 9e7089159c..e7ade128ef 100644 --- a/challenge-126/tyler-wardhaugh/clojure/test/tw/weekly/c126_test.clj +++ b/challenge-126/tyler-wardhaugh/clojure/test/tw/weekly/c126_test.clj @@ -1,7 +1,7 @@ (ns tw.weekly.c126-test (:require [clojure.test :refer [deftest is testing]] [tw.weekly.c126.t1 :refer [count-numbers]] - #_[tw.weekly.c126.t2 :refer []])) + [tw.weekly.c126.t2 :as t2])) (deftest task-1 (testing "Task 1, Count Numbers" @@ -9,3 +9,13 @@ (count-numbers 15))) (is (= "There are 13 numbers between 1 and 25 that don't contain digit 1.\n2, 3, 4, 5, 6, 7, 8, 9, 20, 22, 23, 24, 25" (count-numbers 25))))) + +(deftest task-2 + (testing "Task 2, Minesweeper Game" + (is (= + [[\x 1 0 1 \x 2 \x \x \x \x] + [1 1 0 2 2 4 3 5 5 \x] + [0 0 1 3 \x 3 \x 2 \x 2] + [1 1 1 \x \x 4 1 2 2 2] + [\x 1 1 3 \x 2 0 0 1 \x]] + (-> t2/DEFAULT-INPUT first t2/parse t2/minesweeper))))) |
