diff --git a/2024/13/example.txt b/2024/13/example.txt new file mode 100644 index 0000000..912f482 --- /dev/null +++ b/2024/13/example.txt @@ -0,0 +1,15 @@ +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 diff --git a/2024/13/graph.png b/2024/13/graph.png new file mode 100644 index 0000000..83e526d Binary files /dev/null and b/2024/13/graph.png differ diff --git a/2024/13/solution.nix b/2024/13/solution.nix new file mode 100644 index 0000000..dfc8157 --- /dev/null +++ b/2024/13/solution.nix @@ -0,0 +1,81 @@ +{lib, ...}: input: let + inherit (builtins) elemAt match filter foldl'; + inherit (lib.strings) toIntBase10; + + acost = 3; + bcost = 1; + part2offset = 10000000000000; + + machines = input + |> lib.trim + |> lib.splitString "\n\n" + |> map (text: let + parts = text |> lib.splitString "\n"; + buttona = elemAt parts 0; + buttonb = elemAt parts 1; + prize = elemAt parts 2; + in { + a = buttonToVec buttona; + b = buttonToVec buttonb; + prize = prizeToVec prize; + } + ) + ; + + buttonToVec = text: text + |> match ''Button .: X\+([0-9]+), Y\+([0-9]+)'' + |> map toIntBase10 + |> (nums: { + x = elemAt nums 0; + y = elemAt nums 1; + }) + ; + prizeToVec = text: text + |> match ''Prize: X=([0-9]+), Y=([0-9]+)'' + |> map toIntBase10 + |> (nums: { + x = elemAt nums 0; + y = elemAt nums 1; + }) + ; + + getPresses = {a, b, prize}: + let + # see https://www.desmos.com/calculator/qfzdjjffso + # ma = 1.0 * a.y / a.x; + # mb = 1.0 * b.y / b.x; + # c = prize.y - prize.x * mb; + # x = c / (ma - mb); + + # rearranged to avoid precision errors + x = (b.x * prize.y - prize.x * b.y) * a.x / (b.x * a.y - a.x * b.y); + + apresses = x / a.x; + bpresses = (prize.x - x) / b.x; + in { + a = apresses; + b = bpresses; + doable = a.x * apresses + b.x * bpresses == prize.x && + a.y * apresses + b.y * bpresses == prize.y; + }; + +in { + inherit machines buttonToVec prizeToVec getPresses; + + part1result = machines + |> map getPresses + |> filter ({doable, ...}: doable) + |> foldl' (cost: {a,b,...}: cost + a * acost + b * bcost) 0 + ; + + part2result = machines + |> map (machine: machine // {prize = { + x = machine.prize.x + part2offset; + y = machine.prize.y + part2offset; + };}) + |> map getPresses + |> filter ({doable, ...}: doable) + |> foldl' (cost: {a,b,...}: cost + a * acost + b * bcost) 0 + ; + +} diff --git a/2024/13/solution.test.nix b/2024/13/solution.test.nix new file mode 100644 index 0000000..bd09665 --- /dev/null +++ b/2024/13/solution.test.nix @@ -0,0 +1,52 @@ +{it, describe}: let + pkgs = import {}; + solution = import ./solution.nix pkgs; + exampleIn = builtins.readFile ./example.txt; +in [ + (describe "part 1" [ + + (it "parses buttons" { + actual = (solution "").buttonToVec "Button A: X+94, Y+34"; + expected = { + x = 94; + y = 34; + }; + }) + + (it "parses prize" { + actual = (solution "").prizeToVec "Prize: X=8400, Y=5400"; + expected = { + x = 8400; + y = 5400; + }; + }) + + (it "gets the machines" { + actual = (solution '' + Button A: X+94, Y+34 + Button B: X+22, Y+67 + Prize: X=8400, Y=5400 + '').machines; + expected = [{ + a = {x = 94; y = 34;}; + b = {x = 22; y = 67;}; + prize = {x = 8400; y = 5400;}; + }]; + }) + + (it "gets the answer for a machine" { + actual = (solution "").getPresses { + a = {x = 94; y = 34;}; + b = {x = 22; y = 67;}; + prize = {x = 8400; y = 5400;}; + }; + expected = {a = 80; b = 40;}; + }) + + (it "gets the cost" { + actual = (solution exampleIn).part1result; + expected = 480; + }) + + ]) +] diff --git a/2024/flake.lock b/2024/flake.lock index fb55822..6a78e02 100644 --- a/2024/flake.lock +++ b/2024/flake.lock @@ -3,8 +3,8 @@ "aoc-inputs": { "flake": false, "locked": { - "lastModified": 1733919427, - "narHash": "sha256-9QvGJVeFT1BfuoGcFUWSr6iq4VHiaEd9SKUrl6k2tzw=", + "lastModified": 1734085033, + "narHash": "sha256-UlLhIP9NbAywjOGRkrULOa0e+AtY2Eb7Vgem/o/pN7Y=", "path": "/tmp/aoc-inputs", "type": "path" }, diff --git a/2024/flake.nix b/2024/flake.nix index e1b9153..0cc8d51 100644 --- a/2024/flake.nix +++ b/2024/flake.nix @@ -25,7 +25,7 @@ inherit (pkgs) lib; - in (lib.range 1 11 + in (lib.range 1 13 |> map (i: let id = lib.fixedWidthNumber 2 i; in { name = "day-${id}"; value = let