Moved common TPoint direction code into new unit
This commit is contained in:
parent
19509c6173
commit
8eb76329c1
|
@ -153,6 +153,10 @@
|
|||
<Filename Value="solvers\USnowverload.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit>
|
||||
<Unit>
|
||||
<Filename Value="UCommon.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
<CompilerOptions>
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
}
|
||||
|
||||
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.
|
||||
|
|
@ -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;
|
||||
|
|
|
@ -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<TPoint>;
|
||||
|
@ -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
|
||||
|
|
|
@ -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<TPoint>;
|
||||
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<TPoint>.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
|
||||
|
|
|
@ -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<TPoint>;
|
||||
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue