diff --git a/AdventOfCode.lpi b/AdventOfCode.lpi
index f3c814a..606b61b 100644
--- a/AdventOfCode.lpi
+++ b/AdventOfCode.lpi
@@ -89,6 +89,10 @@
+
+
+
+
diff --git a/AdventOfCode.lpr b/AdventOfCode.lpr
index b355b57..338ddf6 100644
--- a/AdventOfCode.lpr
+++ b/AdventOfCode.lpr
@@ -23,10 +23,9 @@ uses
{$IFDEF UNIX}
cthreads,
{$ENDIF}
- Classes, SysUtils, CustApp,
- USolver,
- UTrebuchet, UCubeConundrum, UGearRatios, UScratchcards, UGiveSeedFertilizer, UWaitForIt, UCamelCards,
- UHauntedWasteland, UNumberTheory, UMirageMaintenance, UPipeMaze, UCosmicExpansion, UHotSprings, UPointOfIncidence;
+ Classes, SysUtils, CustApp, USolver, UTrebuchet, UCubeConundrum, UGearRatios, UScratchcards, UGiveSeedFertilizer,
+ UWaitForIt, UCamelCards, UHauntedWasteland, UNumberTheory, UMirageMaintenance, UPipeMaze, UCosmicExpansion,
+ UHotSprings, UPointOfIncidence, UParabolicReflectorDish;
type
@@ -64,6 +63,7 @@ begin
engine.RunAndFree(TCosmicExpansion.Create);
engine.RunAndFree(THotSprings.Create);
engine.RunAndFree(TPointOfIncidence.Create);
+ engine.RunAndFree(TParabolicReflectorDish.Create);
engine.Free;
end;
diff --git a/solvers/UParabolicReflectorDish.pas b/solvers/UParabolicReflectorDish.pas
new file mode 100644
index 0000000..c2d7732
--- /dev/null
+++ b/solvers/UParabolicReflectorDish.pas
@@ -0,0 +1,161 @@
+{
+ Solutions to the Advent Of Code.
+ Copyright (C) 2023 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 UParabolicReflectorDish;
+
+{$mode ObjFPC}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, Generics.Collections, USolver;
+
+const
+ CRoundRockChar = 'O';
+ CCubeRockChar = '#';
+
+type
+
+ { TRockPile }
+
+ TRockPile = class
+ private
+ FStart, FLength: Integer;
+ public
+ constructor Create(const AStart: Integer);
+ procedure AddRock;
+ function Any: Boolean;
+ procedure SetStart(const AStart: Integer);
+ function CalcWeight(const ALineCount: Integer): Integer;
+ end;
+
+ TRockPiles = specialize TObjectList;
+
+ { TParabolicReflectorDish }
+
+ TParabolicReflectorDish = class(TSolver)
+ private
+ FLineIndex: Integer;
+ FActivePiles, FFinishedPiles: TRockPiles;
+ public
+ constructor Create;
+ destructor Destroy; override;
+ procedure ProcessDataLine(const ALine: string); override;
+ procedure Finish; override;
+ function GetDataFileName: string; override;
+ function GetPuzzleName: string; override;
+ end;
+
+implementation
+
+{ TRockPile }
+
+constructor TRockPile.Create(const AStart: Integer);
+begin
+ FStart := AStart;
+ FLength := 0;
+end;
+
+procedure TRockPile.AddRock;
+begin
+ Inc(FLength);
+end;
+
+function TRockPile.Any: Boolean;
+begin
+ Result := (FLength > 0);
+end;
+
+procedure TRockPile.SetStart(const AStart: Integer);
+begin
+ FStart := AStart;
+end;
+
+function TRockPile.CalcWeight(const ALineCount: Integer): Integer;
+begin
+ Result := (2 * (ALineCount - FStart) - FLength + 1) * FLength div 2;
+end;
+
+{ TParabolicReflectorDish }
+
+constructor TParabolicReflectorDish.Create;
+begin
+ FLineIndex := 0;
+ FActivePiles := TRockPiles.Create;
+ FFinishedPiles := TRockPiles.Create;
+end;
+
+destructor TParabolicReflectorDish.Destroy;
+begin
+ FActivePiles.Free;
+ FFinishedPiles.Free;
+ inherited Destroy;
+end;
+
+procedure TParabolicReflectorDish.ProcessDataLine(const ALine: string);
+var
+ i: Integer;
+begin
+ Inc(FLineIndex);
+
+ // Initializes the list of active piles, one per column.
+ if FActivePiles.Count = 0 then
+ begin
+ FActivePiles.Count := Length(ALine);
+ for i:= 0 to FActivePiles.Count - 1 do
+ FActivePiles[i] := TRockPile.Create(0);
+ end;
+
+ // Updates the active piles from the current line.
+ for i := 1 to Length(ALine) do
+ begin
+ case ALine[i] of
+ CRoundRockChar: FActivePiles[i - 1].AddRock;
+ CCubeRockChar:
+ if FActivePiles[i - 1].Any then
+ begin
+ FFinishedPiles.Add(FActivePiles.ExtractIndex(i - 1));
+ FActivePiles.Insert(i - 1, TRockPile.Create(FLineIndex));
+ end
+ else
+ FActivePiles[i - 1].SetStart(FLineIndex);
+ end;
+ end;
+end;
+
+procedure TParabolicReflectorDish.Finish;
+var
+ i: Integer;
+begin
+ for i := 0 to FFinishedPiles.Count - 1 do
+ Inc(FPart1, FFinishedPiles[i].CalcWeight(FLineIndex));
+ for i := 0 to FActivePiles.Count - 1 do
+ Inc(FPart1, FActivePiles[i].CalcWeight(FLineIndex));
+end;
+
+function TParabolicReflectorDish.GetDataFileName: string;
+begin
+ Result := 'parabolic_reflector_dish.txt';
+end;
+
+function TParabolicReflectorDish.GetPuzzleName: string;
+begin
+ Result := 'Day 14: Parabolic Reflector Dish';
+end;
+
+end.
+
diff --git a/tests/AdventOfCodeFPCUnit.lpi b/tests/AdventOfCodeFPCUnit.lpi
index 9282724..bc6bfbd 100644
--- a/tests/AdventOfCodeFPCUnit.lpi
+++ b/tests/AdventOfCodeFPCUnit.lpi
@@ -96,6 +96,10 @@
+
+
+
+
diff --git a/tests/AdventOfCodeFPCUnit.lpr b/tests/AdventOfCodeFPCUnit.lpr
index ecd15fb..08a515b 100644
--- a/tests/AdventOfCodeFPCUnit.lpr
+++ b/tests/AdventOfCodeFPCUnit.lpr
@@ -6,7 +6,7 @@ uses
Interfaces, Forms, GuiTestRunner, USolver, UBaseTestCases, UTrebuchetTestCases, UCubeConundrumTestCases,
UGearRatiosTestCases, UScratchcardsTestCases, UGiveSeedFertilizerTestCases, UWaitForItTestCases, UCamelCardsTestCases,
UHauntedWastelandTestCases, UMirageMaintenanceTestCases, UPipeMazeTestCases, UCosmicExpansionTestCases,
- UHotSpringsTestCases, UPointOfIncidenceTestCases;
+ UHotSpringsTestCases, UPointOfIncidenceTestCases, UParabolicReflectorDishTestCases;
{$R *.res}
diff --git a/tests/UParabolicReflectorDishTestCases.pas b/tests/UParabolicReflectorDishTestCases.pas
new file mode 100644
index 0000000..2d011ac
--- /dev/null
+++ b/tests/UParabolicReflectorDishTestCases.pas
@@ -0,0 +1,78 @@
+{
+ Solutions to the Advent Of Code.
+ Copyright (C) 2023 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 UParabolicReflectorDishTestCases;
+
+{$mode ObjFPC}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, fpcunit, testregistry, USolver, UBaseTestCases, UParabolicReflectorDish;
+
+type
+
+ { TParabolicReflectorDishFullDataTestCase }
+
+ TParabolicReflectorDishFullDataTestCase = class(TEngineBaseTest)
+ protected
+ function CreateSolver: ISolver; override;
+ published
+ procedure TestPart1;
+ end;
+
+ { TParabolicReflectorDishExampleTestCase }
+
+ TParabolicReflectorDishExampleTestCase = class(TExampleEngineBaseTest)
+ protected
+ function CreateSolver: ISolver; override;
+ published
+ procedure TestPart1;
+ end;
+
+implementation
+
+{ TParabolicReflectorDishFullDataTestCase }
+
+function TParabolicReflectorDishFullDataTestCase.CreateSolver: ISolver;
+begin
+ Result := TParabolicReflectorDish.Create;
+end;
+
+procedure TParabolicReflectorDishFullDataTestCase.TestPart1;
+begin
+ AssertEquals(-1, FSolver.GetResultPart1);
+end;
+
+{ TParabolicReflectorDishExampleTestCase }
+
+function TParabolicReflectorDishExampleTestCase.CreateSolver: ISolver;
+begin
+ Result := TParabolicReflectorDish.Create;
+end;
+
+procedure TParabolicReflectorDishExampleTestCase.TestPart1;
+begin
+ AssertEquals(136, FSolver.GetResultPart1);
+end;
+
+initialization
+
+ RegisterTest(TParabolicReflectorDishFullDataTestCase);
+ RegisterTest(TParabolicReflectorDishExampleTestCase);
+end.
+