63 lines
1.5 KiB
Nix
63 lines
1.5 KiB
Nix
|
{lib, ...}: input: rec {
|
||
|
|
||
|
content = lib.trim input;
|
||
|
|
||
|
chart = content
|
||
|
|> lib.strings.splitString "\n"
|
||
|
|> map (lib.strings.splitString "")
|
||
|
|> map (line: lib.sublist 1 (builtins.length line - 2) line)
|
||
|
;
|
||
|
|
||
|
startingPos = let
|
||
|
xs = map (lib.lists.findFirstIndex (char: char == "^") null) chart;
|
||
|
y = lib.lists.findFirstIndex (x: !isNull x) null xs;
|
||
|
x = builtins.elemAt xs y;
|
||
|
in
|
||
|
{inherit x y;}
|
||
|
;
|
||
|
|
||
|
posToString = {x, y}: "${toString x},${toString y}";
|
||
|
|
||
|
addVec = a: b: {x = a.x + b.x; y = a.y + b.y;};
|
||
|
|
||
|
index = i: list: builtins.elemAt list i;
|
||
|
|
||
|
getChar = {x, y}: chart
|
||
|
|> index y
|
||
|
|> index x
|
||
|
;
|
||
|
|
||
|
height = builtins.length chart;
|
||
|
width = chart |> index 0 |> builtins.length;
|
||
|
|
||
|
progress = {visited ? {}, pos, dir, ...}: let
|
||
|
nextChar = getChar (addVec pos dir);
|
||
|
newDir = if nextChar == "#" then rotate dir else dir;
|
||
|
newPos = addVec pos newDir;
|
||
|
fwd = addVec pos dir;
|
||
|
in
|
||
|
{
|
||
|
visited = visited // {${posToString pos} = true;};
|
||
|
exited = fwd.y >= height || fwd.x >= width || fwd.y < 0 || fwd.x < 0;
|
||
|
pos = newPos;
|
||
|
dir = newDir;
|
||
|
};
|
||
|
|
||
|
rotate = {x, y}: {x = -y; y = x;};
|
||
|
|
||
|
startingDir = {x = 0; y = -1;};
|
||
|
|
||
|
getVisits = {pos ? startingPos, dir ? startingDir, visited ? {}, ...}:
|
||
|
let
|
||
|
nextStep = progress {inherit pos dir visited;};
|
||
|
in if nextStep.exited then visited else getVisits nextStep;
|
||
|
|
||
|
part1result = getVisits {}
|
||
|
|> builtins.attrNames
|
||
|
|> builtins.length
|
||
|
# the last position
|
||
|
|> (v: v + 1)
|
||
|
;
|
||
|
|
||
|
}
|