Added solution for "Day 21: Step Counter", part 1
This commit is contained in:
		
							parent
							
								
									8d5757fae0
								
							
						
					
					
						commit
						bc2568756b
					
				@ -121,6 +121,10 @@
 | 
				
			|||||||
        <Filename Value="solvers\UPulsePropagation.pas"/>
 | 
					        <Filename Value="solvers\UPulsePropagation.pas"/>
 | 
				
			||||||
        <IsPartOfProject Value="True"/>
 | 
					        <IsPartOfProject Value="True"/>
 | 
				
			||||||
      </Unit>
 | 
					      </Unit>
 | 
				
			||||||
 | 
					      <Unit>
 | 
				
			||||||
 | 
					        <Filename Value="solvers\UStepCounter.pas"/>
 | 
				
			||||||
 | 
					        <IsPartOfProject Value="True"/>
 | 
				
			||||||
 | 
					      </Unit>
 | 
				
			||||||
    </Units>
 | 
					    </Units>
 | 
				
			||||||
  </ProjectOptions>
 | 
					  </ProjectOptions>
 | 
				
			||||||
  <CompilerOptions>
 | 
					  <CompilerOptions>
 | 
				
			||||||
 | 
				
			|||||||
@ -27,7 +27,7 @@ uses
 | 
				
			|||||||
  UTrebuchet, UCubeConundrum, UGearRatios, UScratchcards, UGiveSeedFertilizer, UWaitForIt, UCamelCards,
 | 
					  UTrebuchet, UCubeConundrum, UGearRatios, UScratchcards, UGiveSeedFertilizer, UWaitForIt, UCamelCards,
 | 
				
			||||||
  UHauntedWasteland, UNumberTheory, UMirageMaintenance, UPipeMaze, UCosmicExpansion, UHotSprings, UPointOfIncidence,
 | 
					  UHauntedWasteland, UNumberTheory, UMirageMaintenance, UPipeMaze, UCosmicExpansion, UHotSprings, UPointOfIncidence,
 | 
				
			||||||
  UParabolicReflectorDish, ULensLibrary, UFloorWillBeLava, UClumsyCrucible, ULavaductLagoon, UAplenty,
 | 
					  UParabolicReflectorDish, ULensLibrary, UFloorWillBeLava, UClumsyCrucible, ULavaductLagoon, UAplenty,
 | 
				
			||||||
  UPulsePropagation;
 | 
					  UPulsePropagation, UStepCounter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type
 | 
					type
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -89,6 +89,7 @@ begin
 | 
				
			|||||||
      18: engine.RunAndFree(TLavaductLagoon.Create);
 | 
					      18: engine.RunAndFree(TLavaductLagoon.Create);
 | 
				
			||||||
      19: engine.RunAndFree(TAplenty.Create);
 | 
					      19: engine.RunAndFree(TAplenty.Create);
 | 
				
			||||||
      20: engine.RunAndFree(TPulsePropagation.Create);
 | 
					      20: engine.RunAndFree(TPulsePropagation.Create);
 | 
				
			||||||
 | 
					      21: engine.RunAndFree(TStepCounter.Create);
 | 
				
			||||||
    end;
 | 
					    end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  engine.Free;
 | 
					  engine.Free;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										173
									
								
								solvers/UStepCounter.pas
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								solvers/UStepCounter.pas
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,173 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  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 UStepCounter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{$mode ObjFPC}{$H+}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uses
 | 
				
			||||||
 | 
					  Classes, SysUtils, Generics.Collections, USolver;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type
 | 
				
			||||||
 | 
					  TPoints = specialize TList<TPoint>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  { TStepCounter }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  TStepCounter = class(TSolver)
 | 
				
			||||||
 | 
					  private
 | 
				
			||||||
 | 
					    FLines: TStringList;
 | 
				
			||||||
 | 
					    FWidth, FHeight, FMaxSteps: Integer;
 | 
				
			||||||
 | 
					    function FindStart: TPoint;
 | 
				
			||||||
 | 
					    function IsInBounds(constref APoint: TPoint): Boolean;
 | 
				
			||||||
 | 
					    function GetPosition(constref APoint: TPoint): Char;
 | 
				
			||||||
 | 
					    procedure SetPosition(constref APoint: TPoint; const AValue: Char);
 | 
				
			||||||
 | 
					  public
 | 
				
			||||||
 | 
					    property MaxSteps: Integer read FMaxSteps write FMaxSteps;
 | 
				
			||||||
 | 
					    constructor Create;
 | 
				
			||||||
 | 
					    destructor Destroy; override;
 | 
				
			||||||
 | 
					    procedure ProcessDataLine(const ALine: string); override;
 | 
				
			||||||
 | 
					    procedure Finish; override;
 | 
				
			||||||
 | 
					    function GetDataFileName: string; override;
 | 
				
			||||||
 | 
					    function GetPuzzleName: string; override;
 | 
				
			||||||
 | 
					  end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{ TStepCounter }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function TStepCounter.FindStart: TPoint;
 | 
				
			||||||
 | 
					var
 | 
				
			||||||
 | 
					  i, j: Integer;
 | 
				
			||||||
 | 
					begin
 | 
				
			||||||
 | 
					  for i := 1 to FWidth do
 | 
				
			||||||
 | 
					    for j := 0 to FHeight - 1 do
 | 
				
			||||||
 | 
					      if FLines[j][i] = CStartChar then
 | 
				
			||||||
 | 
					      begin
 | 
				
			||||||
 | 
					        Result.X := i;
 | 
				
			||||||
 | 
					        Result.Y := j;
 | 
				
			||||||
 | 
					        Exit;
 | 
				
			||||||
 | 
					      end;
 | 
				
			||||||
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function TStepCounter.IsInBounds(constref APoint: TPoint): Boolean;
 | 
				
			||||||
 | 
					begin
 | 
				
			||||||
 | 
					  Result := (0 < APoint.X) and (APoint.X <= FWidth) and (0 <= APoint.Y) and (APoint.Y < FHeight);
 | 
				
			||||||
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function TStepCounter.GetPosition(constref APoint: TPoint): Char;
 | 
				
			||||||
 | 
					begin
 | 
				
			||||||
 | 
					  Result := FLines[APoint.Y][APoint.X];
 | 
				
			||||||
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					procedure TStepCounter.SetPosition(constref APoint: TPoint; const AValue: Char);
 | 
				
			||||||
 | 
					var
 | 
				
			||||||
 | 
					  s: string;
 | 
				
			||||||
 | 
					begin
 | 
				
			||||||
 | 
					  s := FLines[APoint.Y];
 | 
				
			||||||
 | 
					  s[APoint.X] := AValue;
 | 
				
			||||||
 | 
					  FLines[APoint.Y] := s;
 | 
				
			||||||
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					constructor TStepCounter.Create;
 | 
				
			||||||
 | 
					begin
 | 
				
			||||||
 | 
					  FMaxSteps := 64;
 | 
				
			||||||
 | 
					  FLines := TStringList.Create;
 | 
				
			||||||
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					destructor TStepCounter.Destroy;
 | 
				
			||||||
 | 
					begin
 | 
				
			||||||
 | 
					  FLines.Free;
 | 
				
			||||||
 | 
					  inherited Destroy;
 | 
				
			||||||
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					procedure TStepCounter.ProcessDataLine(const ALine: string);
 | 
				
			||||||
 | 
					begin
 | 
				
			||||||
 | 
					  FLines.Add(ALine);
 | 
				
			||||||
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					procedure TStepCounter.Finish;
 | 
				
			||||||
 | 
					var
 | 
				
			||||||
 | 
					  currentStep: Integer;
 | 
				
			||||||
 | 
					  currentPlots, nextPlots, temp: TPoints;
 | 
				
			||||||
 | 
					  plot, direction, next: TPoint;
 | 
				
			||||||
 | 
					  //s: string;
 | 
				
			||||||
 | 
					begin
 | 
				
			||||||
 | 
					  FWidth := Length(FLines[0]);
 | 
				
			||||||
 | 
					  FHeight := FLines.Count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  currentStep := 0;
 | 
				
			||||||
 | 
					  currentPlots := TPoints.Create;
 | 
				
			||||||
 | 
					  currentPlots.Add(FindStart);
 | 
				
			||||||
 | 
					  Inc(FPart1);
 | 
				
			||||||
 | 
					  nextPlots := TPoints.Create;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  while currentStep < FMaxSteps do
 | 
				
			||||||
 | 
					  begin
 | 
				
			||||||
 | 
					    for plot in currentPlots do
 | 
				
			||||||
 | 
					      for direction in CDirections do
 | 
				
			||||||
 | 
					      begin
 | 
				
			||||||
 | 
					        next := plot + direction;
 | 
				
			||||||
 | 
					        if IsInBounds(next) and (GetPosition(next) = CPlotChar) then
 | 
				
			||||||
 | 
					        begin
 | 
				
			||||||
 | 
					          SetPosition(next, CTraversedChar);
 | 
				
			||||||
 | 
					          nextPlots.Add(next);
 | 
				
			||||||
 | 
					        end;
 | 
				
			||||||
 | 
					      end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    currentPlots.Clear;
 | 
				
			||||||
 | 
					    temp := currentPlots;
 | 
				
			||||||
 | 
					    currentPlots := nextPlots;
 | 
				
			||||||
 | 
					    nextPlots := temp;
 | 
				
			||||||
 | 
					    Inc(currentStep);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Positions where the number of steps are even can be reached with trivial backtracking, so they count.
 | 
				
			||||||
 | 
					    if currentStep mod 2 = 0 then
 | 
				
			||||||
 | 
					    //begin
 | 
				
			||||||
 | 
					      Inc(FPart1, currentPlots.Count);
 | 
				
			||||||
 | 
					    //  for plot in currentPlots do
 | 
				
			||||||
 | 
					    //    SetPosition(plot, 'O');
 | 
				
			||||||
 | 
					    //end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //for s in FLines do
 | 
				
			||||||
 | 
					    //  WriteLn(s);
 | 
				
			||||||
 | 
					    //WriteLn;
 | 
				
			||||||
 | 
					  end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  currentPlots.Free;
 | 
				
			||||||
 | 
					  nextPlots.Free;
 | 
				
			||||||
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function TStepCounter.GetDataFileName: string;
 | 
				
			||||||
 | 
					begin
 | 
				
			||||||
 | 
					  Result := 'step_counter.txt';
 | 
				
			||||||
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function TStepCounter.GetPuzzleName: string;
 | 
				
			||||||
 | 
					begin
 | 
				
			||||||
 | 
					  Result := 'Day 21: Step Counter';
 | 
				
			||||||
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					end.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -124,6 +124,10 @@
 | 
				
			|||||||
        <Filename Value="UPulsePropagationTestCases.pas"/>
 | 
					        <Filename Value="UPulsePropagationTestCases.pas"/>
 | 
				
			||||||
        <IsPartOfProject Value="True"/>
 | 
					        <IsPartOfProject Value="True"/>
 | 
				
			||||||
      </Unit>
 | 
					      </Unit>
 | 
				
			||||||
 | 
					      <Unit>
 | 
				
			||||||
 | 
					        <Filename Value="UStepCounterTestCases.pas"/>
 | 
				
			||||||
 | 
					        <IsPartOfProject Value="True"/>
 | 
				
			||||||
 | 
					      </Unit>
 | 
				
			||||||
    </Units>
 | 
					    </Units>
 | 
				
			||||||
  </ProjectOptions>
 | 
					  </ProjectOptions>
 | 
				
			||||||
  <CompilerOptions>
 | 
					  <CompilerOptions>
 | 
				
			||||||
 | 
				
			|||||||
@ -8,7 +8,7 @@ uses
 | 
				
			|||||||
  UHauntedWastelandTestCases, UMirageMaintenanceTestCases, UPipeMazeTestCases, UCosmicExpansionTestCases,
 | 
					  UHauntedWastelandTestCases, UMirageMaintenanceTestCases, UPipeMazeTestCases, UCosmicExpansionTestCases,
 | 
				
			||||||
  UHotSpringsTestCases, UPointOfIncidenceTestCases, UParabolicReflectorDishTestCases, ULensLibraryTestCases,
 | 
					  UHotSpringsTestCases, UPointOfIncidenceTestCases, UParabolicReflectorDishTestCases, ULensLibraryTestCases,
 | 
				
			||||||
  UFloorWillBeLavaTestCases, UClumsyCrucibleTestCases, ULavaductLagoonTestCases, UAplentyTestCases,
 | 
					  UFloorWillBeLavaTestCases, UClumsyCrucibleTestCases, ULavaductLagoonTestCases, UAplentyTestCases,
 | 
				
			||||||
UPulsePropagationTestCases;
 | 
					  UPulsePropagationTestCases, UStepCounterTestCases;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{$R *.res}
 | 
					{$R *.res}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										82
									
								
								tests/UStepCounterTestCases.pas
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								tests/UStepCounterTestCases.pas
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,82 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  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 UStepCounterTestCases;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{$mode ObjFPC}{$H+}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uses
 | 
				
			||||||
 | 
					  Classes, SysUtils, fpcunit, testregistry, USolver, UBaseTestCases, UStepCounter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  { TStepCounterFullDataTestCase }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  TStepCounterFullDataTestCase = class(TEngineBaseTest)
 | 
				
			||||||
 | 
					  protected
 | 
				
			||||||
 | 
					    function CreateSolver: ISolver; override;
 | 
				
			||||||
 | 
					  published
 | 
				
			||||||
 | 
					    procedure TestPart1;
 | 
				
			||||||
 | 
					  end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  { TStepCounterMax6ExampleTestCase }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  TStepCounterMax6ExampleTestCase = class(TExampleEngineBaseTest)
 | 
				
			||||||
 | 
					  protected
 | 
				
			||||||
 | 
					    function CreateSolver: ISolver; override;
 | 
				
			||||||
 | 
					  published
 | 
				
			||||||
 | 
					    procedure TestPart1;
 | 
				
			||||||
 | 
					  end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					implementation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{ TStepCounterFullDataTestCase }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function TStepCounterFullDataTestCase.CreateSolver: ISolver;
 | 
				
			||||||
 | 
					begin
 | 
				
			||||||
 | 
					  Result := TStepCounter.Create;
 | 
				
			||||||
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					procedure TStepCounterFullDataTestCase.TestPart1;
 | 
				
			||||||
 | 
					begin
 | 
				
			||||||
 | 
					  AssertEquals(3809, FSolver.GetResultPart1);
 | 
				
			||||||
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{ TStepCounterMax6ExampleTestCase }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function TStepCounterMax6ExampleTestCase.CreateSolver: ISolver;
 | 
				
			||||||
 | 
					var
 | 
				
			||||||
 | 
					  solver: TStepCounter;
 | 
				
			||||||
 | 
					begin
 | 
				
			||||||
 | 
					  solver := TStepCounter.Create;
 | 
				
			||||||
 | 
					  solver.MaxSteps := 6;
 | 
				
			||||||
 | 
					  Result := solver;
 | 
				
			||||||
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					procedure TStepCounterMax6ExampleTestCase.TestPart1;
 | 
				
			||||||
 | 
					begin
 | 
				
			||||||
 | 
					  AssertEquals(16, FSolver.GetResultPart1);
 | 
				
			||||||
 | 
					end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					initialization
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  RegisterTest(TStepCounterFullDataTestCase);
 | 
				
			||||||
 | 
					  RegisterTest(TStepCounterMax6ExampleTestCase);
 | 
				
			||||||
 | 
					end.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user