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:
parent
e68701333b
commit
474cfa6cc3
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue