2024 day 13 in nix
This commit is contained in:
parent
71e6dcd7dc
commit
77390e08f3
15
2024/13/example.txt
Normal file
15
2024/13/example.txt
Normal 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
BIN
2024/13/graph.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 67 KiB |
81
2024/13/solution.nix
Normal file
81
2024/13/solution.nix
Normal 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
52
2024/13/solution.test.nix
Normal 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;
|
||||
})
|
||||
|
||||
])
|
||||
]
|
|
@ -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"
|
||||
},
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue