61 lines
1.7 KiB
Nix
61 lines
1.7 KiB
Nix
# nix eval -f ./day_1.nix part1
|
|
# nix eval -f ./day_1.nix part1 --arg input 'builtins.readFile ./puzzle_cache/day_1_1'
|
|
# nix eval -f ./day_1.nix part2
|
|
# nix eval -f ./day_1.nix part2 --arg input 'builtins.readFile ./puzzle_cache/day_1_1'
|
|
{
|
|
input ? (builtins.readFile ./puzzle_cache/day_1_0),
|
|
}:
|
|
with builtins;
|
|
with import ./utils.nix;
|
|
let
|
|
# Split into non-empty lines
|
|
lines = split "\n" input;
|
|
|
|
# Parse a line like "L68" or "R14"
|
|
parseLine = line: {
|
|
dir = builtins.substring 0 1 line;
|
|
dist = toIntBase10 (builtins.substring 1 (builtins.stringLength line - 1) line);
|
|
};
|
|
|
|
rotations = map parseLine lines;
|
|
|
|
countZerosDuring =
|
|
position: dir: dist:
|
|
if dir == "R" then
|
|
floor ((position + dist) / 100.0) - floor (position / 100.0)
|
|
else if dir == "L" then
|
|
floor ((position -1) / 100.0) - floor ((position - dist - 1) / 100.0)
|
|
else
|
|
builtins.throw "Invalid direction: ${dir}";
|
|
|
|
# Fold over the list to simulate the dial
|
|
step =
|
|
state: rot:
|
|
let
|
|
position =
|
|
if rot.dir == "L" then
|
|
mod (state.position - rot.dist) 100
|
|
else if rot.dir == "R" then
|
|
mod (state.position + rot.dist) 100
|
|
else
|
|
builtins.trace "Invalid direction: ${rot.dir}" state.position;
|
|
countZeroPassed = state.countZeroPassed + (countZerosDuring state.position rot.dir rot.dist);
|
|
countZero = state.countZero + (if position == 0 then 1 else 0);
|
|
in
|
|
{
|
|
inherit position countZero countZeroPassed;
|
|
};
|
|
|
|
initialState = {
|
|
position = 50;
|
|
countZero = 0;
|
|
countZeroPassed = 0;
|
|
};
|
|
|
|
finalState = builtins.foldl' step initialState rotations;
|
|
in
|
|
{
|
|
part1 = finalState.countZero;
|
|
part2 = finalState.countZeroPassed;
|
|
# 6689 should be part 2
|
|
}
|