Skip to content

Commit

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


;; # Day 13: Claw Contraption
;;
;; Today we're on a tropical island, and in the lobby of a resort there are
;; lots of claw machines.\
;; They have two buttons, `A` and `B`, which move the claw different amount
;; in the x- and y- directions.
;; We win a prize if, after N amount of presses, we are at the exact
;; x-y location of the prize.
;;
;; For example:
;;
(def example "Button A: X+94, Y+34
Button B: X+22, Y+67
Prize: X=8400, Y=5400
Button A: X+26, Y+66
Button B: X+67, Y+21
Prize: X=12748, Y=12176
Button A: X+17, Y+86
Button B: X+84, Y+37
Prize: X=7870, Y=6450
Button A: X+69, Y+23
Button B: X+27, Y+71
Prize: X=18641, Y=10279")


;; Here we have four different machines.\
;; To press button `A` we need 3 tokens, to press button `B` we need 1 token.
;; Our task is to find the minimum amount of tokens needed to win all
;; possible prizes (on some machines it is impossible to win a prize).





;; ## Input parsing
;;
;; Each machine is in its own paragraph, so the `aoc/parse-paragraphs`
;; function will come handy.
;; The description format is always the same, and we're only interested
;; in the numbers for each machine:
;;
(defn parse-data [input]
(aoc/parse-paragraphs input :ints))

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




;; ## Math
;;
;; The task for Part 1 says:
;; > You estimate that each button would need to be pressed no more
;; > than **100 times** to win a prize.
;;
;; Which, if you're familiar with AoC, looks like a bait.
;; You should immediately get a hint that for Part 2 the numbers will be
;; much higher and we won't be able to check every single combination
;; until we find a solution.
;;
;; For each machine, we need to solve a system of two equations with
;; two unknowns:
;; ```
;; ax*a + bx*b = px
;; ay*a + by*b = py
;; ```
;; where `a` and `b` are unknown amounts of button presses for button `A`
;; and button `B`, respectively.\
;; For each machine, `ax` and `ay` are the movements for each press of
;; button `A`, and `bx` and `by` are the movements for button `B`.
;; The prize is at `[px py]`.
;;
;; At first, I solved these equations on paper, manually doing the
;; subtitutions.
;;
;; There is another way (well, it is the same stuff, just written/calculated
;; a bit differently).
;; This system can also been written as:
;;
^{:nextjournal.clerk/visibility {:code :hide}}
(clerk/tex "
\\begin{bmatrix}
a_x & b_x \\\\
a_y & b_y
\\end{bmatrix}
\\begin{bmatrix}
a \\\\
b
\\end{bmatrix}
=
\\begin{bmatrix}
p_x \\\\
p_y
\\end{bmatrix}
")


;; We can solve this system using
;; [Cramer's rule](https://en.wikipedia.org/wiki/Cramer's_rule#Applications).
;; (Last time I've used it, I was in highschool, 20+ years ago!)
;;
;; We need to find three determinants:
;; - `det-M`, determinant of the original matrix
;; - `det-a`, we substitute `ax` and `ay` in the original matrix with
;; `px` and `py` and find a determinant
;; - `det-b`, we substitute `bx` and `by` in the original matrix with
;; `px` and `py` and find a determinant
;;
^{:nextjournal.clerk/visibility {:code :hide}}
(clerk/tex "
{\\det}_M
=
\\begin{vmatrix}
a_x & b_x \\\\
a_y & b_y
\\end{vmatrix}
\\hspace{1 cm}
{\\det}_a
=
\\begin{vmatrix}
p_x & b_x \\\\
p_y & b_y
\\end{vmatrix}
\\hspace{1 cm}
{\\det}_b
=
\\begin{vmatrix}
a_x & p_x \\\\
a_y & p_y
\\end{vmatrix}
")

;; To get the solution for `a` and `b`, we need to divide the determinants:
;; `det-a / det-M` and `det-b / det-M`, respectively.






;; ## Solution
;;
;; We have all we need to solve the equations.
;;
;; For our task, valid solutions are only those for which `a` and `b` are integers.
;; (We cannot press a button 0.1 times :P).\
;; If a solution is valid, we multiply the presses of button `A` by their
;; price of 3 tokens, and add presses of `B` (costing 1 token):
;;
(defn det [a1 a2 b1 b2]
(- (* a1 b2) (* b1 a2)))

(defn solve-eq [pos-incr [[ax ay] [bx by] [px py]]]
(let [px (+ pos-incr px)
py (+ pos-incr py)
det-M (det ax ay bx by)
det-a (det px py bx by)
det-b (det ax ay px py)
a (/ det-a det-M)
b (/ det-b det-M)]
(if (or (ratio? a) (ratio? b))
0
(+ (* 3 a) b))))


;; The only difference between Part 1 and Part 2 is that for the second part
;; we need to increase the coordinates of a prize by `10000000000000` in
;; each direction:
;;
(defn solve [data]
(vec
(for [pos-incr [0 10000000000000]]
(aoc/sum-map (partial solve-eq pos-incr) data))))


(solve example-data)
(solve data)





;; ## Conclusion
;;
;; Today was mainly a math task.
;;
;; If you know how to solve a system of two linear equations with two unknowns,
;; the hardest thing to code (if you don't have some helpers ready ;))
;; is to separate the input into different groups and parse integers in each.




^{: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 @@ -2,7 +2,7 @@
(:require
day01 day02 day03 day04 day05
day06 day07 day08 day09 day10
day11 day12 ;day13 day14 day15
day11 day12 day13 ;day14 day15
;; day16 day17 day18 day19 day20
;; day21 day22 day23 day24 day25
[clojure.test :refer [deftest is run-tests successful?]]))
Expand Down Expand Up @@ -35,6 +35,7 @@
(check-day 10 [36 81] [820 1786])
(check-day 11 [55312 65601038650482] [183435 218279375708592])
(check-day 12 [1930 1206] [1464678 877492])
(check-day 13 [480 875318608908] [27105 101726882250942])


(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 @@ -65,4 +65,5 @@ Task | Notebook | Comment
[Day 10: Hoof It](https://adventofcode.com/2024/day/10) | [day10.clj](clojure/day10) | Finally some pathfinding!
[Day 11: Plutonian Pebbles](https://adventofcode.com/2024/day/11) | [day11.clj](clojure/day11) | Episode VI: Return of the Lanternfish
[Day 12: Garden Groups](https://adventofcode.com/2024/day/12) | [day12.clj](clojure/day12) | Turns = sides.
[Day 13: Claw Contraption](https://adventofcode.com/2024/day/13) | [day13.clj](clojure/day13) | Kosmo Cramer!

Loading

0 comments on commit a814f5f

Please sign in to comment.