Initial commit

This commit is contained in:
Vegard Berg 2023-12-02 20:13:42 +01:00
commit 86929d2dfc
7 changed files with 199 additions and 0 deletions

23
.gitignore vendored Normal file
View File

@ -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.*

13
day-one/.gitignore vendored Normal file
View File

@ -0,0 +1,13 @@
/target
/classes
/checkouts
profiles.clj
pom.xml
pom.xml.asc
*.jar
*.class
/.lein-*
/.nrepl-port
/.prepl-port
.hgignore
.hg/

9
day-one/project.clj Normal file
View File

@ -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"]])

View File

@ -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)))

13
day-two/.gitignore vendored Normal file
View File

@ -0,0 +1,13 @@
/target
/classes
/checkouts
profiles.clj
pom.xml
pom.xml.asc
*.jar
*.class
/.lein-*
/.nrepl-port
/.prepl-port
.hgignore
.hg/

9
day-two/project.clj Normal file
View File

@ -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"]])

View File

@ -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))))