{ 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 UCubeConundrum; {$mode ObjFPC}{$H+} interface uses Classes, SysUtils; const CMaxRed = 12; CMaxGreen = 13; CMaxBlue = 14; type { TCubeConundrum } TCubeConundrum = class(TObject) private FValue1, FValue2, FGameMaxRed, FGameMaxGreen, FGameMaxBlue: Integer; procedure ProcessDataLine(const ALine: string); procedure ProcessGame(const id: Integer; const draws: TStringArray); function ProcessDraw(const cubes: TStringArray): Boolean; public procedure Solve; property Part1: Integer read FValue1; property Part2: Integer read FValue2; class procedure Run; static; end; implementation { TCubeConundrum } procedure TCubeConundrum.ProcessDataLine(const ALine: string); var gameSplit, subSplit: TStringArray; id: Integer; begin gameSplit := ALine.Split(':'); subSplit := gameSplit[0].Split(' '); id := StrToInt(subSplit[1]); subSplit := gameSplit[1].Split(';'); ProcessGame(id, subSplit); end; procedure TCubeConundrum.ProcessGame(const id: Integer; const draws: TStringArray); var draw: string; drawSplit: TStringArray; isWithinMaxima: Boolean; begin FGameMaxRed := 0; FGameMaxGreen := 0; FGameMaxBlue := 0; isWithinMaxima := True; for draw in draws do begin drawSplit := draw.Split(','); if not ProcessDraw(drawSplit) then isWithinMaxima := False; end; if isWithinMaxima then begin // All draws fulfill maxima. Inc(FValue1, id); end; Inc(FValue2, FGameMaxRed * FGameMaxGreen * FGameMaxBlue); end; function TCubeConundrum.ProcessDraw(const cubes: TStringArray): Boolean; var cubeColor: string; colorSplit: TStringArray; cubeCount, max: Integer; begin Result := True; for cubeColor in cubes do begin colorSplit := cubeColor.Trim.Split(' '); cubeCount := StrToInt(colorSplit[0]); if colorSplit[1] = 'red' then begin if FGameMaxRed < cubeCount then FGameMaxRed := cubeCount; max := CMaxRed end else if colorSplit[1] = 'green' then begin if FGameMaxGreen < cubeCount then FGameMaxGreen := cubeCount; max := CMaxGreen; end else if colorSplit[1] = 'blue' then begin if FGameMaxBlue < cubeCount then FGameMaxBlue := cubeCount; max := CMaxBlue; end; if max < cubeCount then Result := False; end; end; procedure TCubeConundrum.Solve; var data: TextFile; s: string; begin FValue1 := 0; FValue2 := 0; AssignFile(data, ConcatPaths(['data', 'cube_conundrum.txt'])); try reset(data); while (not EOF(data)) do begin readln(data, s); ProcessDataLine(s); end; finally CloseFile(data) end; end; class procedure TCubeConundrum.Run; var cubeConundrum: TCubeConundrum; begin WriteLn; WriteLn('--- Day 2: Cube Conundrum ---'); cubeConundrum := TCubeConundrum.Create; cubeConundrum.Solve; WriteLn('Part 1: ', cubeConundrum.Part1); WriteLn('Part 2: ', cubeConundrum.Part2); cubeConundrum.Free; end; end.