diff --git a/AdventOfCode.lpi b/AdventOfCode.lpi
index 2af3826..2a9af4b 100644
--- a/AdventOfCode.lpi
+++ b/AdventOfCode.lpi
@@ -153,6 +153,10 @@
+
+
+
+
diff --git a/UCommon.pas b/UCommon.pas
new file mode 100644
index 0000000..0e674d9
--- /dev/null
+++ b/UCommon.pas
@@ -0,0 +1,45 @@
+{
+ Solutions to the Advent Of Code.
+ Copyright (C) 2023-2024 Stefan Müller
+
+ This program is free software: you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free Software
+ Foundation, either version 3 of the License, or (at your option) any later
+ version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program. If not, see .
+}
+
+unit UCommon;
+
+{$mode ObjFPC}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils;
+
+type
+ PPoint = ^TPoint;
+
+const
+ CNoDirection: TPoint = (X: 0; Y: 0);
+ CDirectionRight: TPoint = (X: 1; Y: 0);
+ CDirectionDown: TPoint = (X: 0; Y: 1);
+ CDirectionLeft: TPoint = (X: -1; Y: 0);
+ CDirectionUp: TPoint = (X: 0; Y: -1);
+ CDirectionRightDown: TPoint = (X: 1; Y: 1);
+ CDirectionRightUp: TPoint = (X: 1; Y: -1);
+ CDirectionLeftDown: TPoint = (X: -1; Y: 1);
+ CDirectionLeftUp: TPoint = (X: -1; Y: -1);
+ CPCardinalDirections: array[0..3] of PPoint = (@CDirectionRight, @CDirectionDown, @CDirectionLeft, @CDirectionUp);
+
+implementation
+
+end.
+
diff --git a/solvers/UFloorWillBeLava.pas b/solvers/UFloorWillBeLava.pas
index 467b0a2..2c8033b 100644
--- a/solvers/UFloorWillBeLava.pas
+++ b/solvers/UFloorWillBeLava.pas
@@ -1,6 +1,6 @@
{
Solutions to the Advent Of Code.
- Copyright (C) 2023 Stefan Müller
+ Copyright (C) 2023-2024 Stefan Müller
This program is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -22,7 +22,7 @@ unit UFloorWillBeLava;
interface
uses
- Classes, SysUtils, Generics.Collections, USolver;
+ Classes, SysUtils, Generics.Collections, USolver, UCommon;
type
@@ -37,7 +37,7 @@ type
{ TTransition }
TTransition = record
- IncomingDirection, OutgoingDirection, SplitDirection: TPoint;
+ IncomingDirection, OutgoingDirection, SplitDirection: PPoint;
Tile: Char;
EnergyChange: TEnergyState;
end;
@@ -73,32 +73,31 @@ type
end;
const
- CNoDirection: TPoint = (X: 0; Y: 0);
CEmptyChar = '.';
CTransitions: array of TTransition = (
- (IncomingDirection: (X: 1; Y: 0); OutgoingDirection: (X: 0; Y: -1); SplitDirection: (X: 0; Y: 0); Tile: '/';
+ (IncomingDirection: @CDirectionRight; OutgoingDirection: @CDirectionUp; SplitDirection: @CNoDirection; Tile: '/';
EnergyChange: esWestOrHorizontal),
- (IncomingDirection: (X: 0; Y: 1); OutgoingDirection: (X: -1; Y: 0); SplitDirection: (X: 0; Y: 0); Tile: '/';
+ (IncomingDirection: @CDirectionDown; OutgoingDirection: @CDirectionLeft; SplitDirection: @CNoDirection; Tile: '/';
EnergyChange: esWestOrHorizontal),
- (IncomingDirection: (X: -1; Y: 0); OutgoingDirection: (X: 0; Y: 1); SplitDirection: (X: 0; Y: 0); Tile: '/';
+ (IncomingDirection: @CDirectionLeft; OutgoingDirection: @CDirectionDown; SplitDirection: @CNoDirection; Tile: '/';
EnergyChange: esEastOrVertical),
- (IncomingDirection: (X: 0; Y: -1); OutgoingDirection: (X: 1; Y: 0); SplitDirection: (X: 0; Y: 0); Tile: '/';
+ (IncomingDirection: @CDirectionUp; OutgoingDirection: @CDirectionRight; SplitDirection: @CNoDirection; Tile: '/';
EnergyChange: esEastOrVertical),
- (IncomingDirection: (X: 1; Y: 0); OutgoingDirection: (X: 0; Y: 1); SplitDirection: (X: 0; Y: 0); Tile: '\';
+ (IncomingDirection: @CDirectionRight; OutgoingDirection: @CDirectionDown; SplitDirection: @CNoDirection; Tile: '\';
EnergyChange: esWestOrHorizontal),
- (IncomingDirection: (X: 0; Y: 1); OutgoingDirection: (X: 1; Y: 0); SplitDirection: (X: 0; Y: 0); Tile: '\';
+ (IncomingDirection: @CDirectionDown; OutgoingDirection: @CDirectionRight; SplitDirection: @CNoDirection; Tile: '\';
EnergyChange: esEastOrVertical),
- (IncomingDirection: (X: -1; Y: 0); OutgoingDirection: (X: 0; Y: -1); SplitDirection: (X: 0; Y: 0); Tile: '\';
+ (IncomingDirection: @CDirectionLeft; OutgoingDirection: @CDirectionUp; SplitDirection: @CNoDirection; Tile: '\';
EnergyChange: esEastOrVertical),
- (IncomingDirection: (X: 0; Y: -1); OutgoingDirection: (X: -1; Y: 0); SplitDirection: (X: 0; Y: 0); Tile: '\';
+ (IncomingDirection: @CDirectionUp; OutgoingDirection: @CDirectionLeft; SplitDirection: @CNoDirection; Tile: '\';
EnergyChange: esWestOrHorizontal),
- (IncomingDirection: (X: 1; Y: 0); OutgoingDirection: (X: 0; Y: -1); SplitDirection: (X: 0; Y: 1); Tile: '|';
+ (IncomingDirection: @CDirectionRight; OutgoingDirection: @CDirectionUp; SplitDirection: @CDirectionDown; Tile: '|';
EnergyChange: esBoth),
- (IncomingDirection: (X: -1; Y: 0); OutgoingDirection: (X: 0; Y: -1); SplitDirection: (X: 0; Y: 1); Tile: '|';
+ (IncomingDirection: @CDirectionLeft; OutgoingDirection: @CDirectionUp; SplitDirection: @CDirectionDown; Tile: '|';
EnergyChange: esBoth),
- (IncomingDirection: (X: 0; Y: 1); OutgoingDirection: (X: -1; Y: 0); SplitDirection: (X: 1; Y: 0); Tile: '-';
+ (IncomingDirection: @CDirectionDown; OutgoingDirection: @CDirectionLeft; SplitDirection: @CDirectionRight; Tile: '-';
EnergyChange: esBoth),
- (IncomingDirection: (X: 0; Y: -1); OutgoingDirection: (X: -1; Y: 0); SplitDirection: (X: 1; Y: 0); Tile: '-';
+ (IncomingDirection: @CDirectionUp; OutgoingDirection: @CDirectionLeft; SplitDirection: @CDirectionRight; Tile: '-';
EnergyChange: esBoth)
);
@@ -193,11 +192,11 @@ begin
begin
// Checks the current position for direction changes and splits.
for transition in CTransitions do
- if (transition.IncomingDirection = ABeam.Direction) and (transition.Tile = GetTile(ABeam.Position)) then
+ if (transition.IncomingDirection^ = ABeam.Direction) and (transition.Tile = GetTile(ABeam.Position)) then
begin
- if transition.SplitDirection <> CNoDirection then
- stack.Push(GetNewBeam(ABeam.Position + transition.SplitDirection, transition.SplitDirection));
- ABeam.Direction := transition.OutgoingDirection;
+ if transition.SplitDirection^ <> CNoDirection then
+ stack.Push(GetNewBeam(ABeam.Position + transition.SplitDirection^, transition.SplitDirection^));
+ ABeam.Direction := transition.OutgoingDirection^;
energyChange := transition.EnergyChange;
Break;
end;
diff --git a/solvers/ULongWalk.pas b/solvers/ULongWalk.pas
index a57c2e6..4af7fb5 100644
--- a/solvers/ULongWalk.pas
+++ b/solvers/ULongWalk.pas
@@ -1,6 +1,6 @@
{
Solutions to the Advent Of Code.
- Copyright (C) 2023 Stefan Müller
+ Copyright (C) 2023-2024 Stefan Müller
This program is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -22,7 +22,7 @@ unit ULongWalk;
interface
uses
- Classes, SysUtils, Generics.Collections, USolver;
+ Classes, SysUtils, Generics.Collections, USolver, UCommon;
type
TPoints = specialize TList;
@@ -93,15 +93,11 @@ type
function GetPuzzleName: string; override;
end;
- TDirection = (dirRight, dirDown, dirLeft, dirUp);
-
const
CPathChar = '.';
CForestChar = '#';
CRightSlopeChar = '>';
CDownSlopeChar = 'v';
- CDirections: array[TDirection] of TPoint = ((X: 1; Y: 0), (X: 0; Y: 1), (X: -1; Y: 0), (X: 0; Y: -1));
- CStartReverseDirection: TPoint = (X: 0; Y: -1);
implementation
@@ -148,7 +144,7 @@ begin
stack := TPathStartQueue.Create;
pathStart.Position := FStart.Position;
pathStart.Crossing := FStart;
- pathStart.ReverseDirection := CStartReverseDirection;
+ pathStart.ReverseDirection := CDirectionUp;
stack.Enqueue(pathStart);
while stack.Count > 0 do
StepPath(stack);
@@ -158,7 +154,8 @@ end;
procedure TLongWalk.StepPath(const AStartPositionQueue: TPathStartQueue);
var
start: TPathStart;
- new, direction: TPoint;
+ new: TPoint;
+ pdirection: PPoint;
c: Char;
len: Integer;
oneMore, stop: Boolean;
@@ -172,14 +169,14 @@ begin
oneMore := False;
stop := False;
repeat
- for direction in CDirections do
- if direction <> start.ReverseDirection then
+ for pdirection in CPCardinalDirections do
+ if pdirection^ <> start.ReverseDirection then
begin
- new := start.Position + direction;
+ new := start.Position + pdirection^;
c := GetPosition(new);
if c <> CForestChar then
begin
- start.ReverseDirection := Point(-direction.X, -direction.Y);
+ start.ReverseDirection := Point(-pdirection^.X, -pdirection^.Y);
start.Position := new;
if oneMore or (new.Y = FLines.Count - 1) then
@@ -233,8 +230,8 @@ begin
Result := TCrossing.Create(APosition);
// Checks if the new crossing has multiple entries.
- if (GetPosition(APosition + CDirections[dirLeft]) = CRightSlopeChar)
- and (GetPosition(APosition + CDirections[dirUp]) = CDownSlopeChar) then
+ if (GetPosition(APosition + CDirectionLeft) = CRightSlopeChar)
+ and (GetPosition(APosition + CDirectionUp) = CDownSlopeChar) then
FWaitingForOtherInPath.Add(Result)
else
FCrossings.Add(Result);
@@ -244,17 +241,17 @@ begin
// Adds the exits of this crossing to the stack as starts for new paths.
pathStart.Crossing := Result;
- pathStart.Position := APosition + CDirections[dirRight];
+ pathStart.Position := APosition + CDirectionRight;
if GetPosition(pathStart.Position) = CRightSlopeChar then
begin
- pathStart.ReverseDirection := CDirections[dirLeft];
+ pathStart.ReverseDirection := CDirectionLeft;
AStartPositionQueue.Enqueue(pathStart);
end;
- pathStart.Position := APosition + CDirections[dirDown];
+ pathStart.Position := APosition + CDirectionDown;
if GetPosition(pathStart.Position) = CDownSlopeChar then
begin
- pathStart.ReverseDirection := CDirections[dirUp];
+ pathStart.ReverseDirection := CDirectionUp;
AStartPositionQueue.Enqueue(pathStart);
end;
end
diff --git a/solvers/UPipeMaze.pas b/solvers/UPipeMaze.pas
index 1f59dd6..8c8d2e3 100644
--- a/solvers/UPipeMaze.pas
+++ b/solvers/UPipeMaze.pas
@@ -1,6 +1,6 @@
{
Solutions to the Advent Of Code.
- Copyright (C) 2023 Stefan Müller
+ Copyright (C) 2023-2024 Stefan Müller
This program is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -22,7 +22,7 @@ unit UPipeMaze;
interface
uses
- Classes, SysUtils, Generics.Collections, USolver;
+ Classes, SysUtils, Generics.Collections, USolver, UCommon;
const
CStartChar = 'S';
@@ -115,24 +115,18 @@ procedure TPipeMaze.InitStepMappings;
var
i: Integer;
begin
- FStepMappings.Add(TStepMapping.Create(Point(0, 1), Point(0, 1), '|',
- TPointArray.Create(Point(1, 0)),
- TPointArray.Create(Point(-1, 0))));
- FStepMappings.Add(TStepMapping.Create(Point(1, 0), Point(1, 0), '-',
- TPointArray.Create(Point(0, -1)),
- TPointArray.Create(Point(0, 1))));
- FStepMappings.Add(TStepMapping.Create(Point(-1, 0), Point(0, -1), 'L',
- TPointArray.Create(Point(0, 1), Point(-1, 1), Point(-1, 0)),
- []));
- FStepMappings.Add(TStepMapping.Create(Point(0, 1), Point(-1, 0), 'J',
- TPointArray.Create(Point(1, 0), Point(1, 1), Point(0, 1)),
- []));
- FStepMappings.Add(TStepMapping.Create(Point(1, 0), Point(0, 1), '7',
- TPointArray.Create(Point(0, -1), Point(1, -1), Point(1, 0)),
- []));
- FStepMappings.Add(TStepMapping.Create(Point(0, -1), Point(1, 0), 'F',
- TPointArray.Create(Point(-1, 0), Point(-1, -1), Point(0, -1)),
- []));
+ FStepMappings.Add(TStepMapping.Create(CDirectionDown, CDirectionDown, '|',
+ TPointArray.Create(CDirectionRight), TPointArray.Create(CDirectionLeft)));
+ FStepMappings.Add(TStepMapping.Create(CDirectionRight, CDirectionRight, '-',
+ TPointArray.Create(CDirectionUp), TPointArray.Create(CDirectionDown)));
+ FStepMappings.Add(TStepMapping.Create(CDirectionLeft, CDirectionUp, 'L',
+ TPointArray.Create(CDirectionDown, CDirectionLeftDown, CDirectionLeft), []));
+ FStepMappings.Add(TStepMapping.Create(CDirectionDown, CDirectionLeft, 'J',
+ TPointArray.Create(CDirectionRight, CDirectionRightDown, CDirectionDown), []));
+ FStepMappings.Add(TStepMapping.Create(CDirectionRight, CDirectionDown, '7',
+ TPointArray.Create(CDirectionUp, CDirectionRightUp, CDirectionRight), []));
+ FStepMappings.Add(TStepMapping.Create(CDirectionUp, CDirectionRight, 'F',
+ TPointArray.Create(CDirectionLeft, CDirectionLeftUp, CDirectionUp), []));
// Adds reverse step mappings.
for i := 0 to FStepMappings.Count - 1 do
@@ -231,13 +225,12 @@ end;
function TPipeMaze.TryCountEnclosureSide(const AChar: Char; out OCount: Int64): Boolean;
var
- directions: TPointArray;
stack: specialize TStack;
i, j: Integer;
- position, direction, neighbor: TPoint;
+ position, neighbor: TPoint;
+ pdirection: PPoint;
c: Char;
begin
- directions := TPointArray.Create(Point(0, -1), Point(-1, 0), Point(0, 1), Point(1, 0));
stack := specialize TStack.Create;
OCount := 0;
@@ -259,12 +252,12 @@ begin
begin
position := stack.Pop;
- for direction in directions do
+ for pdirection in CPCardinalDirections do
begin
- if CheckMapBounds(position + direction) then
+ if CheckMapBounds(position + pdirection^) then
begin
// Checks the neighboring position.
- neighbor := position + direction;
+ neighbor := position + pdirection^;
c := GetEnclosureMapChar(neighbor);
if (c <> CFloodFillChar) and (c <> CPathChar) then
begin
diff --git a/solvers/UStepCounter.pas b/solvers/UStepCounter.pas
index 887cdb7..6227d12 100644
--- a/solvers/UStepCounter.pas
+++ b/solvers/UStepCounter.pas
@@ -1,6 +1,6 @@
{
Solutions to the Advent Of Code.
- Copyright (C) 2023 Stefan Müller
+ Copyright (C) 2023-2024 Stefan Müller
This program is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -22,7 +22,7 @@ unit UStepCounter;
interface
uses
- Classes, SysUtils, Generics.Collections, USolver;
+ Classes, SysUtils, Generics.Collections, USolver, UCommon;
type
TPoints = specialize TList;
@@ -50,7 +50,6 @@ const
CStartChar = 'S';
CPlotChar = '.';
CTraversedChar = '+';
- CDirections: array of TPoint = ((X: 1; Y: 0), (X: -1; Y: 0), (X: 0; Y: 1), (X: 0; Y: -1));
implementation
@@ -110,7 +109,8 @@ procedure TStepCounter.Finish;
var
currentStep: Integer;
currentPlots, nextPlots, temp: TPoints;
- plot, direction, next: TPoint;
+ plot, next: TPoint;
+ pdirection: PPoint;
begin
FWidth := Length(FLines[0]);
FHeight := FLines.Count;
@@ -124,9 +124,9 @@ begin
while currentStep < FMaxSteps do
begin
for plot in currentPlots do
- for direction in CDirections do
+ for pdirection in CPCardinalDirections do
begin
- next := plot + direction;
+ next := plot + pdirection^;
if IsInBounds(next) and (GetPosition(next) = CPlotChar) then
begin
SetPosition(next, CTraversedChar);