aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammad S Anwar <Mohammad.Anwar@yahoo.com>2022-11-20 21:52:13 +0000
committerGitHub <noreply@github.com>2022-11-20 21:52:13 +0000
commitc64e83912f3b4135bdd45f9e8c473285089e6d72 (patch)
treea8c936998101fad714af946ebc15455968883716
parent07cf8dc598ab7c592e03457334e9bd72de2a7f40 (diff)
parentc35f713f4f3adf7099264f94ff54eb3065b0f7db (diff)
downloadperlweeklychallenge-club-c64e83912f3b4135bdd45f9e8c473285089e6d72.tar.gz
perlweeklychallenge-club-c64e83912f3b4135bdd45f9e8c473285089e6d72.tar.bz2
perlweeklychallenge-club-c64e83912f3b4135bdd45f9e8c473285089e6d72.zip
Merge pull request #7109 from tylerw/tw/challenge-191
Ch191: implement Tasks 1 & 2 in Clojure
-rw-r--r--challenge-191/tyler-wardhaugh/clojure/README.md41
-rw-r--r--challenge-191/tyler-wardhaugh/clojure/bb.edn68
-rw-r--r--challenge-191/tyler-wardhaugh/clojure/build.clj19
-rw-r--r--challenge-191/tyler-wardhaugh/clojure/deps.edn15
-rw-r--r--challenge-191/tyler-wardhaugh/clojure/src/c191/t1.clj17
-rw-r--r--challenge-191/tyler-wardhaugh/clojure/src/c191/t2.clj41
-rw-r--r--challenge-191/tyler-wardhaugh/clojure/test/c191/t1_test.clj15
-rw-r--r--challenge-191/tyler-wardhaugh/clojure/test/c191/t2_test.clj11
8 files changed, 227 insertions, 0 deletions
diff --git a/challenge-191/tyler-wardhaugh/clojure/README.md b/challenge-191/tyler-wardhaugh/clojure/README.md
new file mode 100644
index 0000000000..56385ea8ab
--- /dev/null
+++ b/challenge-191/tyler-wardhaugh/clojure/README.md
@@ -0,0 +1,41 @@
+# c191
+
+The Weekly Challenge — #191 — Tyler Wardhaugh
+
+## Usage
+
+Clojure ([installation instructions](https://clojure.org/guides/getting_started#_clojure_installer_and_cli_tools)) required for `clojure` commands; Babashka ([installation instructions](https://github.com/babashka/babashka#quickstart)) required for the `bb` commands.
+
+Run Task #1:
+
+ $ clojure -M:t1 COLL
+ # ... or ...
+ $ bb run task-1 COLL
+
+ # Alternatively, to run it via Babashka:
+ $ bb run task-1-bb COLL
+
+Run Task #2:
+
+ $ clojure -M:t2 N
+ # ... or ...
+ $ bb run task-2 N
+
+ # Alternatively, to run it via Babashka:
+ $ bb run task-2-bb N
+
+Run the project's tests (which are samples from the task descriptions):
+
+ $ clojure -T:build test
+ # ... or ...
+ $ bb run test
+
+View available tasks Babashka can run:
+
+ $ bb tasks
+
+## License
+
+Copyright © 2022 Tyler Wardhaugh
+
+Distributed under the Eclipse Public License version 1.0.
diff --git a/challenge-191/tyler-wardhaugh/clojure/bb.edn b/challenge-191/tyler-wardhaugh/clojure/bb.edn
new file mode 100644
index 0000000000..ee227e4c53
--- /dev/null
+++ b/challenge-191/tyler-wardhaugh/clojure/bb.edn
@@ -0,0 +1,68 @@
+{
+ :paths ["src" "resources"]
+ :deps {c191/c191 {:local/root "."}}
+
+ :tasks
+ {
+ :requires ([clojure.java.io :as io]
+ [clojure.edn :as edn]
+ [babashka.fs :as fs])
+ :init (do
+ (defn get-first-form
+ [file]
+ (with-open [r (-> file fs/file io/reader)
+ pr (java.io.PushbackReader. r)]
+ (edn/read pr)))
+
+ (defn get-task-ns
+ [task]
+ (let [glob-target (format "src/*/%s.clj" (name task))
+ file (->> glob-target (fs/glob ".") first)]
+ (-> file get-first-form second str)))
+
+ (defn run-task-clj
+ [task args]
+ (apply clojure (str "-M:" task) args))
+
+ (defn run-task-bb
+ ([task args] (run-task-bb task args (get-task-ns task)))
+ ([task args task-ns]
+ (let [bb-cmd (format "bb -m %s " task-ns)]
+ (apply shell bb-cmd args))))
+
+ (defn bb-no-go
+ [task & _]
+ (binding [*out* *err*]
+ (let [task-num (-> task name last (Character/digit 10))]
+ (println
+ (str "error: can't run Task " task-num
+ " via Babashka because it depends"
+ " on some incompatible libraries."))))
+ (System/exit 1)))
+
+ clean {:doc "Clean out temporary files"
+ :task (do (clojure "-T:build" "clean")
+ (run! fs/delete-tree
+ [".nrepl-port" ".cpcache" ".lsp" ".clj-kondo"]))}
+
+ generate-jar {:doc "Generate JAR file"
+ :task (clojure "-X:jar")}
+
+ test {:doc "Run tests"
+ :task (clojure "-T:build test")}
+
+ c**** {:doc "CHALLENGE TASKS"}
+
+ task-1 {:doc "Run Task 1 (via clojure)"
+ :task (run-task-clj :t1 *command-line-args*)}
+
+ task-1-bb {:doc "Run Task 1 (via Babashka)"
+ :task (run-task-bb :t1 *command-line-args*)}
+
+ task-2 {:doc "Run Task 2 (via clojure)"
+ :task (run-task-clj :t2 *command-line-args*)}
+
+ task-2-bb {:doc "Run Task 2 (via Babashka)"
+ :task (run-task-bb :t2 *command-line-args*)}
+ }
+}
diff --git a/challenge-191/tyler-wardhaugh/clojure/build.clj b/challenge-191/tyler-wardhaugh/clojure/build.clj
new file mode 100644
index 0000000000..6a8c4c19e5
--- /dev/null
+++ b/challenge-191/tyler-wardhaugh/clojure/build.clj
@@ -0,0 +1,19 @@
+(ns build
+ (:refer-clojure :exclude [test])
+ (:require [org.corfield.build :as bb]))
+
+(def lib 'net.clojars.c191/c191)
+(def version "0.1.0-SNAPSHOT")
+(def main 'c191.c191)
+
+(defn test "Run the tests." [opts]
+ (bb/run-tests opts))
+
+(def clean bb/clean)
+
+(defn ci "Run the CI pipeline of tests (and build the uberjar)." [opts]
+ (-> opts
+ (assoc :lib lib :version version :main main)
+ (bb/run-tests)
+ (bb/clean)
+ (bb/uber)))
diff --git a/challenge-191/tyler-wardhaugh/clojure/deps.edn b/challenge-191/tyler-wardhaugh/clojure/deps.edn
new file mode 100644
index 0000000000..bbf2435dec
--- /dev/null
+++ b/challenge-191/tyler-wardhaugh/clojure/deps.edn
@@ -0,0 +1,15 @@
+{:paths ["src" "resources"]
+ :deps {org.clojure/clojure {:mvn/version "1.11.1"}}
+ :aliases
+ {:t1 {:main-opts ["-m" "c191.t1"]}
+ :t2 {:main-opts ["-m" "c191.t2"]}
+ :build {:deps {io.github.seancorfield/build-clj
+ {:git/tag "v0.8.3" :git/sha "7ac1f8d"
+ ;; since we're building an app uberjar, we do not
+ ;; need deps-deploy for clojars.org deployment:
+ :deps/root "slim"}}
+ :ns-default build}
+ :test {:extra-paths ["test"]
+ :extra-deps {org.clojure/test.check {:mvn/version "1.1.1"}
+ io.github.cognitect-labs/test-runner
+ {:git/tag "v0.5.1" :git/sha "dfb30dd"}}}}}
diff --git a/challenge-191/tyler-wardhaugh/clojure/src/c191/t1.clj b/challenge-191/tyler-wardhaugh/clojure/src/c191/t1.clj
new file mode 100644
index 0000000000..5539037748
--- /dev/null
+++ b/challenge-191/tyler-wardhaugh/clojure/src/c191/t1.clj
@@ -0,0 +1,17 @@
+(ns c191.t1
+ (:require [clojure.edn :as edn]))
+
+(def DEFAULT-INPUT [[1 2 3 4]])
+
+(defn twice-largest
+ [coll]
+ (let [[biggest second-biggest] (sort > coll)]
+ (when (and biggest second-biggest)
+ (<= (* 2 second-biggest) biggest))))
+
+(defn -main
+ "Run Task 1 with a given input COLL, defaulting to the first example from
+ the task description."
+ [& args]
+ (let [[COLL] (or (some->> args (map edn/read-string)) DEFAULT-INPUT)]
+ (println (if (twice-largest COLL) 1 -1))))
diff --git a/challenge-191/tyler-wardhaugh/clojure/src/c191/t2.clj b/challenge-191/tyler-wardhaugh/clojure/src/c191/t2.clj
new file mode 100644
index 0000000000..ca02691adc
--- /dev/null
+++ b/challenge-191/tyler-wardhaugh/clojure/src/c191/t2.clj
@@ -0,0 +1,41 @@
+(ns c191.t2
+ (:require [clojure.edn :as edn]))
+
+(def DEFAULT-INPUT [2])
+
+; adapted from: https://rosettacode.org/wiki/Determinant_and_permanent#Common_Lisp
+(defn permanent'
+ [mf rows skip-cols]
+ (let [source (range (count (first rows)))
+ f (fn [result col]
+ (if (skip-cols col)
+ result
+ (if (nil? (next rows))
+ (reduced (nth (first rows) col))
+ (+ result (* (nth (first rows) col)
+ (mf mf (next rows) (conj skip-cols col)))))))]
+ (reduce f 0 source)))
+
+(let [mf (memoize permanent')]
+ (def permanent #(mf mf % #{})))
+
+(defn generate-cute-matrix
+ [n]
+ (->> (for [i (range 1 (inc n))
+ j (range 1 (inc n))]
+ (if (or (zero? (mod i j)) (zero? (mod j i))) 1 0))
+ (partition n)))
+
+; adapted from: https://oeis.org/A320843 ("PROG" entry)
+(defn cute-list
+ [n]
+ (if (zero? n)
+ 1
+ (-> n generate-cute-matrix permanent)))
+
+(defn -main
+ "Run Task 2 with a given input N, defaulting to the first example from
+ the task description."
+ [& args]
+ (let [[N] (or (some->> args (map edn/read-string)) DEFAULT-INPUT)]
+ (println (cute-list N))))
diff --git a/challenge-191/tyler-wardhaugh/clojure/test/c191/t1_test.clj b/challenge-191/tyler-wardhaugh/clojure/test/c191/t1_test.clj
new file mode 100644
index 0000000000..4a034f8a25
--- /dev/null
+++ b/challenge-191/tyler-wardhaugh/clojure/test/c191/t1_test.clj
@@ -0,0 +1,15 @@
+(ns c191.t1-test
+ (:require [clojure.test :refer [deftest is testing]]
+ [c191.t1 :refer [twice-largest]]))
+
+(deftest task-1
+ (testing "Task 1 produces the correct results (description)"
+ (is (false? (twice-largest [1 2 3 4])))
+ (is (true? (twice-largest [1 2 0 5])))
+ (is (true? (twice-largest [2 6 3 1])))
+ (is (false? (twice-largest [4 5 2 3])))))
+
+(deftest task-1
+ (testing "Additional tests for twice-largest"
+ (is (nil? (twice-largest [1])))
+ (is (nil? (twice-largest [])))))
diff --git a/challenge-191/tyler-wardhaugh/clojure/test/c191/t2_test.clj b/challenge-191/tyler-wardhaugh/clojure/test/c191/t2_test.clj
new file mode 100644
index 0000000000..7c242c795c
--- /dev/null
+++ b/challenge-191/tyler-wardhaugh/clojure/test/c191/t2_test.clj
@@ -0,0 +1,11 @@
+(ns c191.t2-test
+ (:require [clojure.test :refer [deftest is testing]]
+ [c191.t2 :refer [cute-list]]))
+
+; "Cute List" results for n = 0 .. 15
+; from: https://oeis.org/A320843/list
+(def A320843 [1 1 2 3 8 10 36 41 132 250 700 750 4010 4237 10680 24679])
+
+(deftest task-2
+ (testing "Task 2 produces the correct results"
+ (is (= A320843 (map cute-list (range 16))))))