AoC-2022-Nix/days/5/solution.nix
2022-12-06 21:33:10 -07:00

50 lines
1.8 KiB
Nix

with import ../../util.nix;
let
# read input
input = splitString "\n\n" (readFile ./input);
stacks =
let
# each layer of stacks as a raw input string
layers = dropLast (splitString "\n" (head input));
# each layer of stacks as a list
parsedLayers = map (s: map (l: elemAt l 1) (chunksOf 4 (stringToCharacters s))) layers;
in
# flip from layers to stacks and remove empty slots
map (filter (s: s != " ")) (transpose parsedLayers);
# list of moves "move 1 from 7 to 9" => [1 7 9]
moves = map
(line: map toInt (subtractLists ["move" "from" "to"] (splitString " " line)))
(splitString "\n" (last input));
# funcs for how many boxes to be moved
moveTopOnly = cnt: 1; # crane can only move one box at a time
moveAll = cnt: cnt; # crane can move any number of boxes at a time
moveThree = min 3; # crane can only move 3 boxes at a time
# performs a single move
performMove = moveCntFunc: stacks: mv:
if head mv == 0 then stacks # base case; no more boxes to move
else
let
cnt = elemAt mv 0; # boxes that need to be moved
cnt' = moveCntFunc cnt; # boxes that can be moved
src = elemAt mv 1;
dest = elemAt mv 2;
boxes = take cnt' (elemAt stacks (src -1)); # box(es) being moved
stacks' = imap1 (i: s:
if i == src then drop cnt' s
else if i == dest then boxes ++ s
else s) stacks;
in
performMove moveCntFunc stacks' [(cnt - cnt') src dest];
# performs all moves in sequence
performMoves = moveCntFunc: foldl (performMove moveCntFunc) stacks moves;
in {
part1 = concatStrings (map head (performMoves moveTopOnly));
part2 = concatStrings (map head (performMoves moveAll));
# moveThree = concatStrings (map head (performMoves moveThree));
}