Skip to content

Commit

Permalink
day 19
Browse files Browse the repository at this point in the history
  • Loading branch information
narimiran committed Dec 19, 2024
1 parent 342aa09 commit 4883d14
Show file tree
Hide file tree
Showing 5 changed files with 549 additions and 1 deletion.
134 changes: 134 additions & 0 deletions clojure/day19.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
^{:nextjournal.clerk/visibility {:code :hide :result :hide}}
(ns day19
{:nextjournal.clerk/auto-expand-results? true
:nextjournal.clerk/toc :collapsed}
(:require
aoc
[clojure.string :as str]))


;; # Day 19: Linen Layout
;;
;; Today we're at the hot sprins on Gear Island.
;; We are given a list of towel patterns (first line of the input) and
;; a list of desired designs.
;; It looks like this:
;;
(def example "r, wr, b, g, bwu, rb, gb, br
brwrr
bggr
gbbr
rrbgbr
ubwu
bwurrg
brgr
bbrgwb")


;; ## Input parsing
;;
;; From the first line we need to extract the patterns, which are separated
;; by `, ` (comma, space).
;; The designs are each on their own line, nothing to do there:
;;
(defn parse-data [input]
(let [[[patterns] designs] (aoc/parse-paragraphs input)]
[(str/split patterns #", ")
designs]))

(def example-data (parse-data example))
(def data (parse-data (aoc/read-input 19)))







;; ## Solution
;;
;; Both parts share 99% of the same logic, so we'll write a solution that
;; works on both parts.
;;
;; For each design we need to check if it can be created from the provided
;; patterns (Part 1) and how many different ways there are to create
;; it (Part 2).
;;
;; The idea is to check each design recursively.
;; We start with a complete design (e.g. `abcdef`), then we `filter` the
;; list of patterns to keep only those that the design `starts-with?`.
;;
(defn valid-patterns [patterns design]
(filter #(str/starts-with? design %) patterns))

(valid-patterns ["a" "ab" "b" "bc"] "abcdef")



;; We check the remaining part of the design
;; (e.g. if a pattern was `ab`, we now check `cdef`) recursively.\
;; If we have come to the end of a design (i.e. the design is `empty?`), it
;; means that we found a successful way to create a design.
;;
;; We will encounter the same part of a design multiple times (we can reach
;; it with different pattern combinations, e.g. we reach `cdef` either
;; by matching either the `ab` pattern or by matching
;; "first `a` then `b`" patterns).
;; There's no need to repeatedly check if it'll be successful: we've already
;; calculated it before.
;;
;; To keep a cache of already seen situations, we will use the
;; [`memoize` function](https://clojuredocs.org/clojure.core/memoize).
;;
(def count-ways
(memoize
(fn [patterns design]
(if (empty? design)
1
(->> design
(valid-patterns patterns)
(aoc/sum-map (fn [valid-patt]
(count-ways patterns
(subs design (count valid-patt))))))))))



;; Once we get all the ways each design can be created, for Part 1 we
;; need to count only those which have at least one (`pos?`) way to be created,
;; and for Part 2 we're interested in the total number of all possible ways
;; to create the designs.
;;
(defn solve [[patterns designs]]
(let [possible-designs (mapv #(count-ways patterns %) designs)]
[(aoc/count-if pos? possible-designs)
(reduce + possible-designs)]))


(solve example-data)
(solve data)





;; ## Conclusion
;;
;; Another suspiciously easy task, less than a week until the end.
;; That's now two easy ones in a row.
;; I'm afraid of what will this weekend bring.
;;
;; Today's highlight:
;; - `memoize`: cache results of a function
;; - `subs`: create a substring







^{:nextjournal.clerk/visibility {:code :hide :result :hide}}
(defn -main [input]
(let [data (parse-data input)]
(solve data)))
3 changes: 2 additions & 1 deletion clojure/tests/solutions_tests.clj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
day01 day02 day03 day04 day05
day06 day07 day08 day09 day10
day11 day12 day13 day14 day15
day16 day17 day18 ;day19 day20
day16 day17 day18 day19 ;day20
;; day21 day22 day23 day24 day25
[clojure.test :refer [deftest is run-tests successful?]]))

Expand Down Expand Up @@ -41,6 +41,7 @@
(check-day 16 [7036 45] [79404 451])
(check-day 17 nil ["7,4,2,0,5,0,5,3,7" 202991746427434])
(check-day 18 nil [384 "36,10"])
(check-day 19 [6 16] [240 848076019766013])


(let [summary (run-tests)]
Expand Down
1 change: 1 addition & 0 deletions index.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,5 @@ Task | Notebo
[Day 16: Reindeer Maze](https://adventofcode.com/2024/day/16) | [day16.clj](clojure/day16) | viz | Dijkstra.
[Day 17: Chronospatial Computer](https://adventofcode.com/2024/day/17) | [day17.clj](clojure/day17) | bench | Intcode meets Assembunny.
[Day 18: RAM Run](https://adventofcode.com/2024/day/18) | [day18.clj](clojure/day18) | viz | [aMaze](https://narimiran.github.io/amaze/) :)
[Day 19: Linen Layout](https://adventofcode.com/2024/day/19) | [day19.clj](clojure/day19) | | Another easy one.

Loading

0 comments on commit 4883d14

Please sign in to comment.