commit 86929d2dfccc8cc6ba09a3728596b9ce00327c08 Author: Vegard Berg Date: Sat Dec 2 20:13:42 2023 +0100 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..311c415 --- /dev/null +++ b/.gitignore @@ -0,0 +1,23 @@ +pom.xml +pom.xml.asc +*.jar +*.class +/lib/ +/classes/ +/target/ +**/checkouts/ +.lein-deps-sum +.lein-repl-history +.lein-plugins/ +.lein-failures +.nrepl-port +.cpcache/ + + + +**/.clj-kondo/ +**/.calva +**/.lsp/ +input.* +sample.* +output.* diff --git a/day-one/.gitignore b/day-one/.gitignore new file mode 100644 index 0000000..d956ab0 --- /dev/null +++ b/day-one/.gitignore @@ -0,0 +1,13 @@ +/target +/classes +/checkouts +profiles.clj +pom.xml +pom.xml.asc +*.jar +*.class +/.lein-* +/.nrepl-port +/.prepl-port +.hgignore +.hg/ diff --git a/day-one/project.clj b/day-one/project.clj new file mode 100644 index 0000000..a7b352d --- /dev/null +++ b/day-one/project.clj @@ -0,0 +1,9 @@ +(defproject day-one "0.1.0-SNAPSHOT" + :description "FIXME: write description" + :url "http://example.com/FIXME" + :license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0" + :url "https://www.eclipse.org/legal/epl-2.0/"} + :dependencies [[org.clojure/clojure "1.11.1"]] + :repl-options {:init-ns day-one.core} + :main day-one.core/-main + :plugins [[cider/cider-nrepl "0.42.1"]]) diff --git a/day-one/src/day_one/core.clj b/day-one/src/day_one/core.clj new file mode 100644 index 0000000..3c8d109 --- /dev/null +++ b/day-one/src/day_one/core.clj @@ -0,0 +1,50 @@ +(ns day-one.core + (:require + [clojure.string :as str])) + +(defn no-text-digits + "Convert text digits to number digits" + [text] + [text + (-> text + (str/replace "one" "o1e") + (str/replace "two" "t2o") + (str/replace "three" "t3e") + (str/replace "four" "f4r") + (str/replace "five" "f5e") + (str/replace "six" "s6x") + (str/replace "seven" "s7n") + (str/replace "eight" "e8t") + (str/replace "nine" "n9e") + (str/replace "zero" "z0o"))]) + +(defn digits-from-regex + [match first-digit last-digit & {:keys [debug]}] + (let [num (Integer. (str first-digit last-digit))] + (when debug (printf "%-50s\t%d\n" match num)) + num)) + +(defn parse-digits + "Parse the first and last digit of a line and combine them" + [[orig new] & {:keys [debug]}] + (if-some [[match first last] (re-matches #"^\D*?(\d).*(\d)\D*?$" new)] + (do (when debug (printf "%-50s\t" orig)) + (digits-from-regex match first last + :debug debug)) + (if-some [[match only] (re-matches #"^\D*?(\d)\D*$" new)] + (do (when debug (printf "%-50s\t" orig)) + (digits-from-regex match only only + :debug debug)) + 0))) + +(defn -main [] + (as-> "input.txt" data + (slurp data) + (str/split data #"\n") + + (map no-text-digits data) + + (map #(parse-digits % :debug true) data) + (reduce + data) + (printf "----------\n%d\n" data))) + diff --git a/day-two/.gitignore b/day-two/.gitignore new file mode 100644 index 0000000..d956ab0 --- /dev/null +++ b/day-two/.gitignore @@ -0,0 +1,13 @@ +/target +/classes +/checkouts +profiles.clj +pom.xml +pom.xml.asc +*.jar +*.class +/.lein-* +/.nrepl-port +/.prepl-port +.hgignore +.hg/ diff --git a/day-two/project.clj b/day-two/project.clj new file mode 100644 index 0000000..706e74c --- /dev/null +++ b/day-two/project.clj @@ -0,0 +1,9 @@ +(defproject day-two "0.1.0-SNAPSHOT" + :description "FIXME: write description" + :url "http://example.com/FIXME" + :license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0" + :url "https://www.eclipse.org/legal/epl-2.0/"} + :main day-two.core/-main + :dependencies [[org.clojure/clojure "1.11.1"]] + :repl-options {:init-ns day-two.core} + :plugins [[cider/cider-nrepl "0.42.1"]]) diff --git a/day-two/src/day_two/core.clj b/day-two/src/day_two/core.clj new file mode 100644 index 0000000..74db365 --- /dev/null +++ b/day-two/src/day_two/core.clj @@ -0,0 +1,82 @@ +(ns day-two.core + (:require + [clojure.string :as str])) + +(defn parse-subset + [subset] + (let [[_ nums colour] (re-matches #"(\d+)\s*(\w+)" subset)] + (list (Integer. nums) colour))) + +(defn- to-hashmap + [xs] + (let [base (reduce (fn [m [k v]] (assoc m (keyword v) k)) {} xs) + with-red (if (:red base) base (assoc base :red 0)) + with-green (if (:green with-red) with-red (assoc with-red :green 0)) + with-blue (if (:blue with-green) with-green (assoc with-green :blue 0))] + with-blue)) + +(defn parse-sets + [[set & sets]] + (conj (if sets (parse-sets sets) (list)) + (to-hashmap + (map parse-subset + (str/split set #", "))))) + +(defn parse-game + "Parse a game line" + [text] + (let [[_ game-num sets] + (re-matches #"^Game (\d+):\s(.*)" text)] + (list (Integer. game-num) (parse-sets (str/split sets #"; "))))) + +(defn parse-games [lines] (map parse-game (str/split lines #"\n"))) + +;;; PART 1 + +(def max-map {:red 12 :green 13 :blue 14}) + +(defn- valid-set? + "Given a map of keys and their max values, determine if the set is valid" + [maxes set] + (every? true? (list (<= (:red set) (:red maxes)) + (<= (:green set) (:green maxes)) + (<= (:blue set) (:blue maxes))))) + +(defn- valid-game? + "Given a map of keys and their max values, determine if the game is valid" + [m [_ sets]] + (every? true? + (map #(valid-set? m %) sets))) + +(defn- valid-game-id [[id _ :as game]] (if (valid-game? max-map game) id 0)) +(defn- sum-games [games] (reduce + (map valid-game-id games))) + +;;; PART 2 + +(defn- min-cubes + "Determine the minimum number of cubes of each colour for the game to be successful" + [xs] + (reduce (fn [prev cur] + {:red (max (:red prev) (:red cur)) + :green (max (:green prev) (:green cur)) + :blue (max (:blue prev) (:blue cur))}) + {:red 0 :green 0 :blue 0} + xs)) + +(defn- rgb-map-to-list [m] (list (:red m) (:green m) (:blue m))) + +(defn- game-cube-power + "Get the power of the minimum cubes" + [[_ xs]] + (reduce * (->> xs + (min-cubes) + (rgb-map-to-list)))) + +(defn- sum-games-power [games] (reduce + (map game-cube-power games))) + +(defn -main + "Main entry point of the program" + [] + (let [games (parse-games (slurp "input.txt"))] + (printf "Sum of valid game IDs: %s\n" (sum-games games)) + (printf "Sum of cube powers: %s\n" (sum-games-power games))))