diff --git a/AdventOfCode.lpi b/AdventOfCode.lpi
index 0870890..e9f222e 100644
--- a/AdventOfCode.lpi
+++ b/AdventOfCode.lpi
@@ -45,6 +45,10 @@
+
+
+
+
diff --git a/AdventOfCode.lpr b/AdventOfCode.lpr
index 3a77065..43c82a3 100644
--- a/AdventOfCode.lpr
+++ b/AdventOfCode.lpr
@@ -25,7 +25,7 @@ uses
{$ENDIF}
Classes, SysUtils, CustApp,
USolver,
- UTrebuchet, UCubeConundrum, UGearRatios;
+ UTrebuchet, UCubeConundrum, UGearRatios, UScratchcards;
type
@@ -53,6 +53,7 @@ begin
TCubeConundrum.Run;
engine := TSolverEngine.Create('data');
engine.RunAndFree(TGearRatios.Create);
+ engine.RunAndFree(TScratchcards.Create);
engine.Free;
end;
diff --git a/solvers/UScratchcards.pas b/solvers/UScratchcards.pas
new file mode 100644
index 0000000..ede0449
--- /dev/null
+++ b/solvers/UScratchcards.pas
@@ -0,0 +1,105 @@
+{
+ 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 UScratchcards;
+
+{$mode ObjFPC}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, USolver;
+
+type
+
+ { TScratchcards }
+
+ TScratchcards = class(TSolver)
+ private
+ function GetNumber(const AString: string; const AIndex: Integer): Integer;
+ public
+ procedure ProcessDataLine(const ALine: string); override;
+ procedure Finish; override;
+ function GetDataFileName: string; override;
+ function GetPuzzleName: string; override;
+ end;
+
+
+implementation
+
+{ TScratchcards }
+
+function TScratchcards.GetNumber(const AString: string; const AIndex: Integer): Integer;
+begin
+ Result := StrToInt(Trim(Copy(AString, AIndex * 3 + 1, 3)))
+end;
+
+procedure TScratchcards.ProcessDataLine(const ALine: string);
+var
+ cardSplit: TStringArray;
+ wins: array of Integer;
+ count, i, have, win, cardPoints: Integer;
+begin
+ cardSplit := ALine.Split([':', '|']);
+
+ // Determines winning numbers.
+ count := cardSplit[1].Length div 3;
+ SetLength(wins, count);
+ for i := 0 to count - 1 do
+ begin
+ wins[i] := GetNumber(cardSplit[1], i);
+ end;
+
+ // Checks have numbers against winning numbers.
+ cardPoints := 0;
+ count := cardSplit[2].Length div 3;
+ for i := 0 to count - 1 do
+ begin
+ have := GetNumber(cardSplit[2], i);
+ for win in wins do
+ begin
+ if win = have then
+ begin
+ if cardPoints = 0 then
+ cardPoints := 1
+ else
+ Inc(cardPoints, cardPoints);
+ Break;
+ end;
+ end;
+ end;
+
+ Inc(FPart1, cardPoints);
+end;
+
+procedure TScratchcards.Finish;
+begin
+
+end;
+
+function TScratchcards.GetDataFileName: string;
+begin
+ Result := 'scratchcards.txt';
+end;
+
+function TScratchcards.GetPuzzleName: string;
+begin
+ Result := 'Day 4: Scratchcards';
+end;
+
+end.
+
diff --git a/tests/AdventOfCodeFPCUnit.lpi b/tests/AdventOfCodeFPCUnit.lpi
index fff5ccd..4f20461 100644
--- a/tests/AdventOfCodeFPCUnit.lpi
+++ b/tests/AdventOfCodeFPCUnit.lpi
@@ -48,6 +48,10 @@
+
+
+
+
diff --git a/tests/AdventOfCodeFPCUnit.lpr b/tests/AdventOfCodeFPCUnit.lpr
index cb55c7b..3aa8ff7 100644
--- a/tests/AdventOfCodeFPCUnit.lpr
+++ b/tests/AdventOfCodeFPCUnit.lpr
@@ -3,7 +3,7 @@ program AdventOfCodeFPCUnit;
{$mode objfpc}{$H+}
uses
- Interfaces, Forms, GuiTestRunner, USolver, UBaseTestCases, UGearRatiosTestCases;
+ Interfaces, Forms, GuiTestRunner, USolver, UBaseTestCases, UGearRatiosTestCases, UScratchcardsTestCases;
{$R *.res}
diff --git a/tests/UScratchcardsTestCases.pas b/tests/UScratchcardsTestCases.pas
new file mode 100644
index 0000000..5f41315
--- /dev/null
+++ b/tests/UScratchcardsTestCases.pas
@@ -0,0 +1,113 @@
+{
+ 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 UScratchcardsTestCases;
+
+{$mode ObjFPC}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, fpcunit, testregistry, USolver, UBaseTestCases, UScratchcards;
+
+type
+
+ { TScratchcardsBaseTestCase }
+
+ TScratchcardsBaseTestCase = class(TBaseTestCase)
+ protected
+ procedure Setup; override;
+ end;
+
+ { TScratchcardsFullDataTestCase }
+
+ TScratchcardsFullDataTestCase = class(TScratchcardsBaseTestCase)
+ protected
+ procedure Setup; override;
+ published
+ procedure TestPart1;
+ procedure TestPart2;
+ end;
+
+ { TScratchcardsExampleTestCase }
+
+ TScratchcardsExampleTestCase = class(TScratchcardsBaseTestCase)
+ protected
+ procedure Setup; override;
+ published
+ procedure TestPart1;
+ procedure TestPart2;
+ end;
+
+implementation
+
+{ TScratchcardsBaseTestCase }
+
+procedure TScratchcardsBaseTestCase.Setup;
+begin
+ inherited Setup;
+ FSolver := TScratchcards.Create;
+end;
+
+{ TScratchcardsFullDataTestCase }
+
+procedure TScratchcardsFullDataTestCase.Setup;
+begin
+ inherited Setup;
+ FEngine.ProcessData(FSolver);
+end;
+
+procedure TScratchcardsFullDataTestCase.TestPart1;
+begin
+ AssertEquals(21821, FSolver.GetResultPart1);
+end;
+
+procedure TScratchcardsFullDataTestCase.TestPart2;
+begin
+ AssertEquals(-1, FSolver.GetResultPart2);
+end;
+
+{ TScratchcardsExampleTestCase }
+
+procedure TScratchcardsExampleTestCase.Setup;
+begin
+ inherited Setup;
+ FSolver.Init;
+ FSolver.ProcessDataLine('Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53');
+ FSolver.ProcessDataLine('Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19');
+ FSolver.ProcessDataLine('Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1');
+ FSolver.ProcessDataLine('Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83');
+ FSolver.ProcessDataLine('Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36');
+ FSolver.ProcessDataLine('Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11');
+ FSolver.Finish;
+end;
+
+procedure TScratchcardsExampleTestCase.TestPart1;
+begin
+ AssertEquals(13, FSolver.GetResultPart1);
+end;
+
+procedure TScratchcardsExampleTestCase.TestPart2;
+begin
+ AssertEquals(-1, FSolver.GetResultPart2);
+end;
+
+initialization
+
+ RegisterTest(TScratchcardsFullDataTestCase);
+ RegisterTest(TScratchcardsExampleTestCase);
+end.
diff --git a/tests/bin/AdventOfCodeFPCUnit.fpcunit.ini b/tests/bin/AdventOfCodeFPCUnit.fpcunit.ini
index 87cc773..d064076 100644
--- a/tests/bin/AdventOfCodeFPCUnit.fpcunit.ini
+++ b/tests/bin/AdventOfCodeFPCUnit.fpcunit.ini
@@ -23,3 +23,15 @@ TGearRatiosTestCase.Checked=1
TGearRatiosTestCase.Expanded=0
TGearRatiosTestCase.TestEndOfLineNumber.Checked=1
TGearRatiosTestCase.TestEndOfLineNumber.Expanded=0
+TScratchcardsFullDataTestCase.Checked=1
+TScratchcardsFullDataTestCase.Expanded=1
+TScratchcardsFullDataTestCase.TestPart1.Checked=1
+TScratchcardsFullDataTestCase.TestPart1.Expanded=0
+TScratchcardsFullDataTestCase.TestPart2.Checked=1
+TScratchcardsFullDataTestCase.TestPart2.Expanded=1
+TScratchcardsExampleTestCase.Checked=1
+TScratchcardsExampleTestCase.Expanded=1
+TScratchcardsExampleTestCase.TestPart1.Checked=1
+TScratchcardsExampleTestCase.TestPart1.Expanded=0
+TScratchcardsExampleTestCase.TestPart2.Checked=1
+TScratchcardsExampleTestCase.TestPart2.Expanded=1