2024 day 13 in nix

This commit is contained in:
Tristan 2024-12-13 12:19:42 +00:00
parent 71e6dcd7dc
commit 77390e08f3
6 changed files with 151 additions and 3 deletions

15
2024/13/example.txt Normal file
View file

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

BIN
2024/13/graph.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

81
2024/13/solution.nix Normal file
View file

@ -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
;
}

52
2024/13/solution.test.nix Normal file
View file

@ -0,0 +1,52 @@
{it, describe}: let
pkgs = import <nixpkgs> {};
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;
})
])
]

View file

@ -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"
},

View file

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