Added solution for "Day 14: Parabolic Reflector Dish", part 1

This commit is contained in:
Stefan Müller 2023-12-14 17:51:12 +01:00 committed by Stefan Müller
parent 01267c8f79
commit f9583e684d
6 changed files with 252 additions and 5 deletions

View File

@ -89,6 +89,10 @@
<Filename Value="solvers\UPointOfIncidence.pas"/> <Filename Value="solvers\UPointOfIncidence.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
</Unit> </Unit>
<Unit>
<Filename Value="solvers\UParabolicReflectorDish.pas"/>
<IsPartOfProject Value="True"/>
</Unit>
</Units> </Units>
</ProjectOptions> </ProjectOptions>
<CompilerOptions> <CompilerOptions>

View File

@ -23,10 +23,9 @@ uses
{$IFDEF UNIX} {$IFDEF UNIX}
cthreads, cthreads,
{$ENDIF} {$ENDIF}
Classes, SysUtils, CustApp, Classes, SysUtils, CustApp, USolver, UTrebuchet, UCubeConundrum, UGearRatios, UScratchcards, UGiveSeedFertilizer,
USolver, UWaitForIt, UCamelCards, UHauntedWasteland, UNumberTheory, UMirageMaintenance, UPipeMaze, UCosmicExpansion,
UTrebuchet, UCubeConundrum, UGearRatios, UScratchcards, UGiveSeedFertilizer, UWaitForIt, UCamelCards, UHotSprings, UPointOfIncidence, UParabolicReflectorDish;
UHauntedWasteland, UNumberTheory, UMirageMaintenance, UPipeMaze, UCosmicExpansion, UHotSprings, UPointOfIncidence;
type type
@ -64,6 +63,7 @@ begin
engine.RunAndFree(TCosmicExpansion.Create); engine.RunAndFree(TCosmicExpansion.Create);
engine.RunAndFree(THotSprings.Create); engine.RunAndFree(THotSprings.Create);
engine.RunAndFree(TPointOfIncidence.Create); engine.RunAndFree(TPointOfIncidence.Create);
engine.RunAndFree(TParabolicReflectorDish.Create);
engine.Free; engine.Free;
end; end;

View File

@ -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 <http://www.gnu.org/licenses/>.
}
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<TRockPile>;
{ 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.

View File

@ -96,6 +96,10 @@
<Filename Value="UPointOfIncidenceTestCases.pas"/> <Filename Value="UPointOfIncidenceTestCases.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
</Unit> </Unit>
<Unit>
<Filename Value="UParabolicReflectorDishTestCases.pas"/>
<IsPartOfProject Value="True"/>
</Unit>
</Units> </Units>
</ProjectOptions> </ProjectOptions>
<CompilerOptions> <CompilerOptions>

View File

@ -6,7 +6,7 @@ uses
Interfaces, Forms, GuiTestRunner, USolver, UBaseTestCases, UTrebuchetTestCases, UCubeConundrumTestCases, Interfaces, Forms, GuiTestRunner, USolver, UBaseTestCases, UTrebuchetTestCases, UCubeConundrumTestCases,
UGearRatiosTestCases, UScratchcardsTestCases, UGiveSeedFertilizerTestCases, UWaitForItTestCases, UCamelCardsTestCases, UGearRatiosTestCases, UScratchcardsTestCases, UGiveSeedFertilizerTestCases, UWaitForItTestCases, UCamelCardsTestCases,
UHauntedWastelandTestCases, UMirageMaintenanceTestCases, UPipeMazeTestCases, UCosmicExpansionTestCases, UHauntedWastelandTestCases, UMirageMaintenanceTestCases, UPipeMazeTestCases, UCosmicExpansionTestCases,
UHotSpringsTestCases, UPointOfIncidenceTestCases; UHotSpringsTestCases, UPointOfIncidenceTestCases, UParabolicReflectorDishTestCases;
{$R *.res} {$R *.res}

View File

@ -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 <http://www.gnu.org/licenses/>.
}
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.