From ea13d0f250000d70f987cec5e94c3c0e6fddce42 Mon Sep 17 00:00:00 2001 From: Tyler Wardhaugh Date: Wed, 29 Sep 2021 09:41:07 -0700 Subject: Ch132 (Clojure): prep for challenge --- challenge-132/tyler-wardhaugh/clojure/README.md | 14 ++++++-------- challenge-132/tyler-wardhaugh/clojure/pom.xml | 8 ++++---- .../tyler-wardhaugh/clojure/src/tw/weekly/c132/core.clj | 12 ++++++++++++ .../tyler-wardhaugh/clojure/src/tw/weekly/c132/t1.clj | 14 ++++++++++++++ .../tyler-wardhaugh/clojure/src/tw/weekly/c132/t2.clj | 14 ++++++++++++++ .../tyler-wardhaugh/clojure/test/tw/weekly/c132_test.clj | 12 ++++++++++++ 6 files changed, 62 insertions(+), 12 deletions(-) create mode 100644 challenge-132/tyler-wardhaugh/clojure/src/tw/weekly/c132/core.clj create mode 100644 challenge-132/tyler-wardhaugh/clojure/src/tw/weekly/c132/t1.clj create mode 100644 challenge-132/tyler-wardhaugh/clojure/src/tw/weekly/c132/t2.clj create mode 100644 challenge-132/tyler-wardhaugh/clojure/test/tw/weekly/c132_test.clj diff --git a/challenge-132/tyler-wardhaugh/clojure/README.md b/challenge-132/tyler-wardhaugh/clojure/README.md index 064e23e11f..74b8669aa3 100644 --- a/challenge-132/tyler-wardhaugh/clojure/README.md +++ b/challenge-132/tyler-wardhaugh/clojure/README.md @@ -1,7 +1,7 @@ -# tw.weekly.c130 +# tw.weekly.c132 -The Weekly Challenge - #130 - Tyler Wardhaugh +The Weekly Challenge - #132 - Tyler Wardhaugh ## Usage @@ -9,7 +9,7 @@ Clojure ([installation instructions](https://clojure.org/guides/getting_started# Run the project directly (shows default output from both tasks): - $ clojure -M -m tw.weekly.c130.core + $ clojure -M -m tw.weekly.c132.core # ... or ... $ bb run both @@ -21,15 +21,13 @@ Run the project's tests (which are samples from the task descriptions): Run Task #1 with input - $ clojure -M -m tw.weekly.c130.t1 N - # ... or ... - $ bb run task-1 N + $ clojure -M -m tw.weekly.c132.t1 D Run Task #2 with input: - $ clojure -M -m tw.weekly.c130.t2 D S + $ clojure -M -m tw.weekly.c132.t2 H1 H2 I1 I2 # ... or ... - $ bb run task-2 D S + $ bb run task-2 H1 H2 I1 I2 View available tasks Babashka can run: diff --git a/challenge-132/tyler-wardhaugh/clojure/pom.xml b/challenge-132/tyler-wardhaugh/clojure/pom.xml index b1039ce744..b3edb199c9 100644 --- a/challenge-132/tyler-wardhaugh/clojure/pom.xml +++ b/challenge-132/tyler-wardhaugh/clojure/pom.xml @@ -2,11 +2,11 @@ 4.0.0 tw.weekly - tw.weekly.c131 + tw.weekly.c132 0.1.0-SNAPSHOT - tw.weekly.c131 - Challenge #131 - https://github.com/tw.weekly/tw.weekly.c131 + tw.weekly.c132 + Challenge #132 + https://github.com/tw.weekly/tw.weekly.c132 Eclipse Public License diff --git a/challenge-132/tyler-wardhaugh/clojure/src/tw/weekly/c132/core.clj b/challenge-132/tyler-wardhaugh/clojure/src/tw/weekly/c132/core.clj new file mode 100644 index 0000000000..4115f99d9b --- /dev/null +++ b/challenge-132/tyler-wardhaugh/clojure/src/tw/weekly/c132/core.clj @@ -0,0 +1,12 @@ +(ns tw.weekly.c132.core + (:require [tw.weekly.c132.t1 :as t1]) + (:require [tw.weekly.c132.t2 :as t2]) + (:gen-class)) + +(defn -main + "Run all tasks" + [& _] + (println "Task #1:") + (t1/-main) + (println "\nTask #2:") + (t2/-main)) diff --git a/challenge-132/tyler-wardhaugh/clojure/src/tw/weekly/c132/t1.clj b/challenge-132/tyler-wardhaugh/clojure/src/tw/weekly/c132/t1.clj new file mode 100644 index 0000000000..007e4b2067 --- /dev/null +++ b/challenge-132/tyler-wardhaugh/clojure/src/tw/weekly/c132/t1.clj @@ -0,0 +1,14 @@ +(ns tw.weekly.c132.t1 + (:require [clojure.edn :as edn])) + +;;; +; Task description for TASK #1 › Mirror Dates +;;; +(def DEFAULT-INPUT []) + +(defn -main + "Run Task 1 with a given input N, defaulting to the first example from the + task description." + [& args] + (let [[D] (or args DEFAULT-INPUT)] + )) diff --git a/challenge-132/tyler-wardhaugh/clojure/src/tw/weekly/c132/t2.clj b/challenge-132/tyler-wardhaugh/clojure/src/tw/weekly/c132/t2.clj new file mode 100644 index 0000000000..8d237772b6 --- /dev/null +++ b/challenge-132/tyler-wardhaugh/clojure/src/tw/weekly/c132/t2.clj @@ -0,0 +1,14 @@ +(ns tw.weekly.c132.t2 + (:require [clojure.edn :as :edn)) + +;;; +; Task description for TASK #2, Hash Join +;;; +(def DEFAULT-INPUT []) + +(defn -main + "Run Task 1 with a given input D and S, defaulting to the first example from + the task description." + [& args] + (let [[H1 H2] (or (some->> args (map edn/read-string)) DEFAULT-INPUT)] + )) diff --git a/challenge-132/tyler-wardhaugh/clojure/test/tw/weekly/c132_test.clj b/challenge-132/tyler-wardhaugh/clojure/test/tw/weekly/c132_test.clj new file mode 100644 index 0000000000..e4ff9454a9 --- /dev/null +++ b/challenge-132/tyler-wardhaugh/clojure/test/tw/weekly/c132_test.clj @@ -0,0 +1,12 @@ +(ns tw.weekly.c132-test + (:require [clojure.test :refer [deftest is testing]] + #_[tw.weekly.c132.t1 :refer []] + #_[tw.weekly.c132.t2 :refer []])) + +(deftest task-1 + (testing "Task 1, Mirror Dates" + )) + +(deftest task-2 + (testing "Task 2, Hash Join" + )) -- cgit From 85dc157cc2972c8ca43e467cc825f818afa10326 Mon Sep 17 00:00:00 2001 From: Tyler Wardhaugh Date: Wed, 29 Sep 2021 09:41:07 -0700 Subject: Ch131 (Clojure): Task 1 --- challenge-132/tyler-wardhaugh/clojure/bb.edn | 4 ++- challenge-132/tyler-wardhaugh/clojure/deps.edn | 3 ++- challenge-132/tyler-wardhaugh/clojure/pom.xml | 5 ++++ .../clojure/src/tw/weekly/c132/t1.clj | 29 +++++++++++++++++++--- .../clojure/test/tw/weekly/c132_test.clj | 12 +++++++-- 5 files changed, 45 insertions(+), 8 deletions(-) diff --git a/challenge-132/tyler-wardhaugh/clojure/bb.edn b/challenge-132/tyler-wardhaugh/clojure/bb.edn index 4cd11817b8..a0e8b96a48 100644 --- a/challenge-132/tyler-wardhaugh/clojure/bb.edn +++ b/challenge-132/tyler-wardhaugh/clojure/bb.edn @@ -63,7 +63,9 @@ :task (run-task :t1 *command-line-args*)} task-1-bb {:doc "Run Task 1 (via Babashka)" - :task (run-task-bb :t1 *command-line-args*)} + :task (binding [*out* *err*] + (println "error: can't run Task 1 via Babashka because it depends on some incompatible libraries.") + (System/exit 1))} task-2 {:doc "Run Task 2 (via clojure)" :task (run-task :t2 *command-line-args*)} diff --git a/challenge-132/tyler-wardhaugh/clojure/deps.edn b/challenge-132/tyler-wardhaugh/clojure/deps.edn index 5b1400b27e..e821835450 100644 --- a/challenge-132/tyler-wardhaugh/clojure/deps.edn +++ b/challenge-132/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"} + clojure.java-time/clojure.java-time {:mvn/version "0.3.3"}} :aliases {:test {:extra-paths ["test"] :extra-deps {org.clojure/test.check {:mvn/version "1.1.0"} diff --git a/challenge-132/tyler-wardhaugh/clojure/pom.xml b/challenge-132/tyler-wardhaugh/clojure/pom.xml index b3edb199c9..ca7a3f1f2a 100644 --- a/challenge-132/tyler-wardhaugh/clojure/pom.xml +++ b/challenge-132/tyler-wardhaugh/clojure/pom.xml @@ -24,6 +24,11 @@ clojure 1.10.3 + + clojure.java-time + clojure.java-time + 0.3.3 + src diff --git a/challenge-132/tyler-wardhaugh/clojure/src/tw/weekly/c132/t1.clj b/challenge-132/tyler-wardhaugh/clojure/src/tw/weekly/c132/t1.clj index 007e4b2067..b24255c143 100644 --- a/challenge-132/tyler-wardhaugh/clojure/src/tw/weekly/c132/t1.clj +++ b/challenge-132/tyler-wardhaugh/clojure/src/tw/weekly/c132/t1.clj @@ -1,14 +1,35 @@ (ns tw.weekly.c132.t1 - (:require [clojure.edn :as edn])) + (:require [java-time :as j] + [clojure.pprint :refer [cl-format]])) ;;; ; Task description for TASK #1 › Mirror Dates ;;; -(def DEFAULT-INPUT []) +(def DEFAULT-TODAY "2021/09/22") +(def DEFAULT-INPUT ["2021/09/18" DEFAULT-TODAY]) +(def DATE-FORMAT "yyyy/MM/dd") + +(defn parse-date + [s] + (j/local-date DATE-FORMAT s)) + +(defn format-date + [d] + (-> (j/formatter DATE-FORMAT) + (j/format d))) + +(defn mirror-date + [origin today] + (let [delta (j/time-between :days origin today) + before (j/minus origin (j/days delta)) + after (j/plus today (j/days delta))] + (list before after))) (defn -main "Run Task 1 with a given input N, defaulting to the first example from the task description." [& args] - (let [[D] (or args DEFAULT-INPUT)] - )) + (let [[origin today] (map parse-date (or args DEFAULT-INPUT))] + (->> (mirror-date origin today) + (map format-date) + (cl-format true "~{~a~^, ~}~%")))) diff --git a/challenge-132/tyler-wardhaugh/clojure/test/tw/weekly/c132_test.clj b/challenge-132/tyler-wardhaugh/clojure/test/tw/weekly/c132_test.clj index e4ff9454a9..6d2c5f2894 100644 --- a/challenge-132/tyler-wardhaugh/clojure/test/tw/weekly/c132_test.clj +++ b/challenge-132/tyler-wardhaugh/clojure/test/tw/weekly/c132_test.clj @@ -1,11 +1,19 @@ (ns tw.weekly.c132-test (:require [clojure.test :refer [deftest is testing]] - #_[tw.weekly.c132.t1 :refer []] + [tw.weekly.c132.t1 :as t1] #_[tw.weekly.c132.t2 :refer []])) +(def today (t1/parse-date t1/DEFAULT-TODAY)) + (deftest task-1 (testing "Task 1, Mirror Dates" - )) + (let [today (t1/parse-date t1/DEFAULT-TODAY)] + (is (= (map t1/parse-date ["2021/09/14" "2021/09/26"]) + (t1/mirror-date (t1/parse-date "2021/09/18") today))) + (is (= (map t1/parse-date ["1929/10/27" "2067/09/05"]) + (t1/mirror-date (t1/parse-date "1975/10/10") today))) + (is (= (map t1/parse-date ["1912/07/08" "2076/04/30"]) + (t1/mirror-date (t1/parse-date "1967/02/14") today)))))) (deftest task-2 (testing "Task 2, Hash Join" -- cgit From ea1fffc2c7a7762111128528607a2a8ffd9b42f3 Mon Sep 17 00:00:00 2001 From: Tyler Wardhaugh Date: Wed, 29 Sep 2021 09:41:07 -0700 Subject: Ch131 (Clojure): Task 2 --- .../clojure/src/tw/weekly/c132/t2.clj | 60 +++++++++++++++++++--- .../clojure/test/tw/weekly/c132_test.clj | 12 ++++- 2 files changed, 64 insertions(+), 8 deletions(-) diff --git a/challenge-132/tyler-wardhaugh/clojure/src/tw/weekly/c132/t2.clj b/challenge-132/tyler-wardhaugh/clojure/src/tw/weekly/c132/t2.clj index 8d237772b6..0f0930b838 100644 --- a/challenge-132/tyler-wardhaugh/clojure/src/tw/weekly/c132/t2.clj +++ b/challenge-132/tyler-wardhaugh/clojure/src/tw/weekly/c132/t2.clj @@ -1,14 +1,62 @@ (ns tw.weekly.c132.t2 - (:require [clojure.edn :as :edn)) + (:require [clojure.edn :as edn] + [clojure.pprint :refer [cl-format]])) ;;; ; Task description for TASK #2, Hash Join ;;; -(def DEFAULT-INPUT []) +(def MAXSIZE "The maximum number of build relations to process at one time." 3) +(def DEFAULT-INPUT + [[[20, "Alex" ] + [28, "Joe" ] + [38, "Mike" ] + [18, "Alex" ] + [25, "David" ] + [18, "Simon" ]] + [["Alex", "Stewart"] + ["Joe", "Root" ] + ["Mike", "Gatting"] + ["Joe", "Blog" ] + ["Alex", "Jones" ] + ["Simon","Duane" ]] + 1 + 0]) + +(defn butnth + "Returns all values except the one at index." + [coll index] + (keep-indexed (fn [i v] (when (not= i index) v)) coll)) + +;;; Classic Hash Join +;; Algorithm description: +; https://en.wikipedia.org/wiki/Hash_join#Classic_hash_join +;; Notes: +; - We proactively batch the smaller relation (build) into MAXSIZE chunks to +; ensure it can fit into memory. +; - Order of output relation is not guaranteed. +;;; +(defn hash-join + [a b a-index b-index] + (let [[build build-index probe probe-index] + (if (<= (count a) (count b)) + [a a-index b b-index] + [b b-index a a-index])] + (-> (comp + (partition-all MAXSIZE) + (map (fn [batch] (group-by #(nth % build-index) batch))) + (mapcat + (fn [build-map] + (keep (fn [row] + (when-let [ks (build-map (nth row probe-index))] + (map #(concat % (butnth row probe-index)) ks))) + probe))) + cat) + (sequence build)))) (defn -main - "Run Task 1 with a given input D and S, defaulting to the first example from - the task description." + "Run Task 1 with a given input H1, H2, I1, and I2, defaulting to the first + example from the task description." [& args] - (let [[H1 H2] (or (some->> args (map edn/read-string)) DEFAULT-INPUT)] - )) + (let [[H1 H2 I1 I2] (or (some->> args (map edn/read-string)) DEFAULT-INPUT)] + (->> (hash-join H1 H2 I1 I2) + (cl-format true "~:{~a, ~s, ~s~%~}")))) diff --git a/challenge-132/tyler-wardhaugh/clojure/test/tw/weekly/c132_test.clj b/challenge-132/tyler-wardhaugh/clojure/test/tw/weekly/c132_test.clj index 6d2c5f2894..00edee2c66 100644 --- a/challenge-132/tyler-wardhaugh/clojure/test/tw/weekly/c132_test.clj +++ b/challenge-132/tyler-wardhaugh/clojure/test/tw/weekly/c132_test.clj @@ -1,7 +1,7 @@ (ns tw.weekly.c132-test (:require [clojure.test :refer [deftest is testing]] [tw.weekly.c132.t1 :as t1] - #_[tw.weekly.c132.t2 :refer []])) + [tw.weekly.c132.t2 :as t2])) (def today (t1/parse-date t1/DEFAULT-TODAY)) @@ -17,4 +17,12 @@ (deftest task-2 (testing "Task 2, Hash Join" - )) + (is (= (set '((20 "Alex" "Stewart") + (18 "Alex" "Stewart") + (28 "Joe" "Root") + (38 "Mike" "Gatting") + (28 "Joe" "Blog") + (20 "Alex" "Jones") + (18 "Alex" "Jones") + (18 "Simon" "Duane"))) + (set (apply t2/hash-join t2/DEFAULT-INPUT)))))) -- cgit