From 474cfa6cc37b398675613764d3318cfa38620bc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20M=C3=BCller?= Date: Tue, 5 Dec 2023 18:14:14 +0100 Subject: [PATCH] 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 --- UGiveSeedFertilizer.pas | 125 ++++++++++++++++++++-------------------- 1 file changed, 62 insertions(+), 63 deletions(-) diff --git a/UGiveSeedFertilizer.pas b/UGiveSeedFertilizer.pas index dc44a6b..cc4b76a 100644 --- a/UGiveSeedFertilizer.pas +++ b/UGiveSeedFertilizer.pas @@ -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; - 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; - FMaps: specialize TFPGObjectList; + FNew, FConverted, FProcessedIndices: specialize TFPGList; 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.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.Create; - FMaps := specialize TFPGObjectList.Create; + FNew := specialize TFPGList.Create; + FConverted := specialize TFPGList.Create; + FProcessedIndices := specialize TFPGList.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;