Updated solution for "Day 5: If You Give A Seed A Fertilizer", part 1, to process the data just in time instead of preloading all of it

This commit is contained in:
Stefan Müller 2023-12-05 18:14:14 +01:00 committed by Stefan Müller
parent e68701333b
commit 474cfa6cc3
1 changed files with 62 additions and 63 deletions

View File

@ -32,29 +32,19 @@ type
private
FDestinationStart, FSourceStart, FSourceEnd, FDifference1, FDifference2: Cardinal;
public
constructor Create(const ALine: string);
constructor Create(const ADestinationStart, ASourceStart, ALength: Cardinal);
function TryConvert(const AInput: Cardinal; out OOutput: Cardinal): Boolean;
end;
{ TAlmanacMap }
TAlmanacMap = class
private
FRanges: specialize TFPGObjectList<TAlmanacMapRange>;
public
constructor Create;
destructor Destroy; override;
procedure AddMapRange(const ALine: string);
function Convert(const AInput: Cardinal): Cardinal;
end;
{ TGiveSeedFertilizer }
TGiveSeedFertilizer = class(TSolver)
private
FSeeds: specialize TFPGList<Cardinal>;
FMaps: specialize TFPGObjectList<TAlmanacMap>;
FNew, FConverted, FProcessedIndices: specialize TFPGList<Cardinal>;
procedure ProcessSeeds(const ALine: string);
procedure ProcessMapRange(const ALine: string);
procedure FinishMap;
public
constructor Create;
destructor Destroy; override;
@ -68,6 +58,14 @@ implementation
{ TAlmanacMapRange }
constructor TAlmanacMapRange.Create(const ALine: string);
var
split: TStringArray;
begin
split := ALine.Split(' ');
Create(StrToDWord(split[0]), StrToDWord(split[1]), StrToDWord(split[2]));
end;
constructor TAlmanacMapRange.Create(const ADestinationStart, ASourceStart, ALength: Cardinal);
begin
FDestinationStart := ADestinationStart;
@ -106,40 +104,6 @@ begin
end;
end;
{ TAlmanacMap }
constructor TAlmanacMap.Create;
begin
FRanges := specialize TFPGObjectList<TAlmanacMapRange>.Create;
end;
destructor TAlmanacMap.Destroy;
begin
FRanges.Free;
inherited Destroy;
end;
procedure TAlmanacMap.AddMapRange(const ALine: string);
var
split: TStringArray;
begin
split := ALine.Split(' ');
FRanges.Add(TAlmanacMapRange.Create(StrToDWord(split[0]), StrToDWord(split[1]), StrToDWord(split[2])));
end;
function TAlmanacMap.Convert(const AInput: Cardinal): Cardinal;
var
range: TAlmanacMapRange;
begin
for range in FRanges do
begin
if range.TryConvert(AInput, Result) then
Exit;
end;
Result := AInput;
end;
{ TGiveSeedFertilizer }
procedure TGiveSeedFertilizer.ProcessSeeds(const ALine: string);
@ -150,20 +114,60 @@ begin
split := Aline.Split(' ');
for i := 1 to Length(split) - 1 do
begin
FSeeds.Add(StrToDWord(split[i]));
FNew.Add(StrToDWord(split[i]));
end;
end;
procedure TGiveSeedFertilizer.ProcessMapRange(const ALine: string);
var
range: TAlmanacMapRange;
i: Integer;
converted: Cardinal;
begin
// Converts all "new" values that fall into this mapping range.
range := TAlmanacMapRange.Create(ALine);
for i := 0 to FNew.Count - 1 do
begin
if range.TryConvert(FNew[i], converted) then
begin
FConverted.Add(converted);
FProcessedIndices.Add(i);
end;
end;
range.Free;
// Forgets the converted values.
for i := FProcessedIndices.Count - 1 downto 0 do
begin
FNew.Delete(FProcessedIndices[i]);
end;
FProcessedIndices.Clear;
end;
procedure TGiveSeedFertilizer.FinishMap;
var
value: Cardinal;
begin
// Resets the lists for the next map, remaining values stay unconverted.
for value in FConverted do
begin
FNew.Add(value);
end;
FConverted.Clear;
end;
constructor TGiveSeedFertilizer.Create;
begin
FSeeds := specialize TFPGList<Cardinal>.Create;
FMaps := specialize TFPGObjectList<TAlmanacMap>.Create;
FNew := specialize TFPGList<Cardinal>.Create;
FConverted := specialize TFPGList<Cardinal>.Create;
FProcessedIndices := specialize TFPGList<Cardinal>.Create;
end;
destructor TGiveSeedFertilizer.Destroy;
begin
FSeeds.Free;
FMaps.Free;
FNew.Free;
FConverted.Free;
FProcessedIndices.Free;
inherited Destroy;
end;
@ -172,23 +176,18 @@ begin
if LeftStr(ALine, 6) = 'seeds:' then
ProcessSeeds(ALine)
else if RightStr(ALine, 4) = 'map:' then
FMaps.Add(TAlmanacMap.Create)
FinishMap
else if Aline <> '' then
FMaps.Last.AddMapRange(ALine);
ProcessMapRange(ALine);
end;
procedure TGiveSeedFertilizer.Finish;
var
seed, value: Cardinal;
map: TAlmanacMap;
value: Cardinal;
begin
for seed in FSeeds do
FinishMap;
for value in FNew do
begin
value := seed;
for map in FMaps do
begin
value := map.Convert(value);
end;
if (FPart1 = 0) or (value < FPart1) then
FPart1 := value;
end;