2024 day 13 in nix
This commit is contained in:
parent
71e6dcd7dc
commit
69fdd2bdaa
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: 147 KiB |
82
2024/13/solution.nix
Normal file
82
2024/13/solution.nix
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
{lib, ...}: input: let
|
||||||
|
inherit (builtins) elemAt match filter foldl';
|
||||||
|
inherit (lib.strings) toIntBase10;
|
||||||
|
inherit (lib) mod;
|
||||||
|
|
||||||
|
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": {
|
"aoc-inputs": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1733919427,
|
"lastModified": 1734085033,
|
||||||
"narHash": "sha256-9QvGJVeFT1BfuoGcFUWSr6iq4VHiaEd9SKUrl6k2tzw=",
|
"narHash": "sha256-UlLhIP9NbAywjOGRkrULOa0e+AtY2Eb7Vgem/o/pN7Y=",
|
||||||
"path": "/tmp/aoc-inputs",
|
"path": "/tmp/aoc-inputs",
|
||||||
"type": "path"
|
"type": "path"
|
||||||
},
|
},
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
inherit (pkgs) lib;
|
inherit (pkgs) lib;
|
||||||
|
|
||||||
|
|
||||||
in (lib.range 1 11
|
in (lib.range 1 13
|
||||||
|> map (i: let id = lib.fixedWidthNumber 2 i; in {
|
|> map (i: let id = lib.fixedWidthNumber 2 i; in {
|
||||||
name = "day-${id}";
|
name = "day-${id}";
|
||||||
value = let
|
value = let
|
||||||
|
|
Loading…
Reference in a new issue