advent-of-code/2022/day09/default.nix

93 lines
2.4 KiB
Nix
Raw Permalink Normal View History

2022-12-12 13:57:34 +01:00
{ pkgs, lib, AoCLib, ... }:
2022-12-12 12:57:59 +01:00
with lib;
let
2022-12-12 13:57:34 +01:00
inherit (AoCLib) scanl abs repeat cmp;
2022-12-12 12:57:59 +01:00
mapDirectionStepsToHorizontalVertical = { direction, steps }: {
horizontal = if direction == "L" then steps else
if direction == "R" then -steps else 0;
vertical = if direction == "D" then steps else
if direction == "U" then -steps else 0;
};
foldHeadPosition =
{ x ? 0, y ? 0 }:
{ horizontal, vertical }: {
x = x + horizontal;
y = y + vertical;
};
movements = pipe ./input.txt [
fileContents
(splitString "\n")
(map (splitString " "))
(map (x: { direction = head x; steps = toInt (elemAt x 1); }))
(map mapDirectionStepsToHorizontalVertical)
(scanl foldHeadPosition {})
];
ropePieceLength = headPiece: tailPiece: let
deltaX = abs (headPiece.x - tailPiece.x);
deltaY = abs (headPiece.y - tailPiece.y);
in max deltaX deltaY;
moveRopePiece = headPiece: tailPiece: {
2022-12-12 13:57:34 +01:00
x = tailPiece.x + (cmp headPiece.x tailPiece.x);
y = tailPiece.y + (cmp headPiece.y tailPiece.y);
2022-12-12 12:57:59 +01:00
};
moveRope = headToOverlap: rope: let
newHead = moveRopePiece headToOverlap (head rope);
moveIfNextPieceMoved = x: y:
if ropePieceLength x y > 1
then moveRopePiece x y
else y;
newTail = scanl moveIfNextPieceMoved newHead (tail rope);
in [newHead] ++ newTail;
moveRopeUntilHeadOverlapsAndReportLastPositions = headToOverlap: rope: let
newRope = moveRope headToOverlap rope;
nextIteration = moveRopeUntilHeadOverlapsAndReportLastPositions headToOverlap newRope;
in if head rope == headToOverlap
then {
inherit rope;
tailPositions = [];
}
else {
inherit (nextIteration) rope;
tailPositions = [(last newRope)] ++ nextIteration.tailPositions;
};
f = n: { rope ? (repeat { x = 0; y = 0; } n), tailPositions ? [{ x = 0; y = 0; }] }: newHeadPosition: let
newRope = moveRopeUntilHeadOverlapsAndReportLastPositions newHeadPosition rope;
in {
rope = newRope.rope;
tailPositions = tailPositions ++ newRope.tailPositions;
};
answer1 = pipe movements [
(foldl (f 2) {})
(x: x.tailPositions)
unique
length
toString
];
answer2 = pipe movements [
(foldl (f 10) {})
(x: x.tailPositions)
unique
length
toString
];
in pkgs.writeText "answers" ''
Task1:
${answer1}
Task2:
${answer2}
''