46 lines
1.5 KiB
Nix
46 lines
1.5 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 can be moved
|
|
moveTopOnly = cnt: 1; # crane can only move one bpx at a time
|
|
moveAll = cnt: cnt; # crane can move any number of 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;
|
|
cnt' = moveCntFunc cnt;
|
|
src = elemAt mv 1;
|
|
dest = elemAt mv 2;
|
|
boxes = take cnt' (elemAt stacks (src -1));
|
|
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));
|
|
} |