@@ -22,11 +22,11 @@ function RoundExDouble(const ATemp: Double): Double; inline;
2222 Max: SmallInt;
2323 Count: UInt32;
2424 Sum: Integer;
25- Name : AnsiString;
2625 end ;
2726 PStationData = ^TStationData;
2827
2928 TKeys = array [0 ..45006 ] of Cardinal;
29+ TStationNames = array [0 ..45006 ] of AnsiString;
3030 TValues = array [0 ..45006 ] of PStationData;
3131
3232 { TMyDictionary }
@@ -36,13 +36,16 @@ TMyDictionary = class
3636 FHashes: TKeys;
3737 FValues: TValues;
3838 FRecords: array [0 ..45006 ] of TStationData;
39+ // store the station names outside of the record as they are filled only upon first encounter
40+ FStationNames: TStationNames;
3941 procedure InternalFind (const aKey: Cardinal; out aFound: Boolean; out aIndex: Integer);
4042 public
4143 constructor Create;
4244 property Keys: TKeys read FHashes;
45+ property StationNames: TStationNames read FStationNames;
4346 property Values: TValues read FValues;
4447 function TryGetValue (const aKey: Cardinal; out aValue: PStationData): Boolean; inline;
45- procedure Add (const aKey: Cardinal; const aValue: PStationData); inline;
48+ procedure Add (const aKey: Cardinal; const aValue: PStationData; const aStationName: AnsiString ); inline;
4649 end ;
4750
4851 { TOneBRC }
@@ -139,6 +142,7 @@ procedure TMyDictionary.InternalFind(const aKey: Cardinal; out aFound: Boolean;
139142 end
140143 else begin
141144 vOffset := 1 ;
145+
142146 while True do begin
143147 // quadratic probing, by incrementing vOffset
144148 Inc (vIdx, vOffset);
@@ -181,7 +185,7 @@ function TMyDictionary.TryGetValue(const aKey: Cardinal; out aValue: PStationDat
181185 aValue := FValues[vIdx];
182186end ;
183187
184- procedure TMyDictionary.Add (const aKey: Cardinal; const aValue: PStationData);
188+ procedure TMyDictionary.Add (const aKey: Cardinal; const aValue: PStationData; const aStationName: AnsiString );
185189var
186190 vIdx: Integer;
187191 vFound: Boolean;
@@ -190,6 +194,7 @@ procedure TMyDictionary.Add(const aKey: Cardinal; const aValue: PStationData);
190194 if not vFound then begin
191195 FHashes[vIdx] := aKey;
192196 FValues[vIdx] := aValue;
197+ FStationNames[vIdx] := aStationName;
193198 end
194199 else
195200 raise Exception.Create (' TMyDict: cannot add, duplicate key' );
@@ -350,8 +355,7 @@ procedure TOneBRC.ProcessData (aThreadNb: UInt16; aStartIdx: Int64; aEndIdx: Int
350355 vData^.Max := vTemp;
351356 vData^.Sum := vTemp;
352357 vData^.Count := 1 ;
353- vData^.Name := vStation;
354- FStationsDicts[aThreadNb].Add (vHash, vData);
358+ FStationsDicts[aThreadNb].Add (vHash, vData, vStation);
355359 end ;
356360
357361 // we're at a #10: next line starts at the next index
@@ -376,8 +380,10 @@ procedure TOneBRC.Merge(aLeft: UInt16; aRight: UInt16);
376380var iHash: Cardinal;
377381 vDataR: PStationData;
378382 vDataL: PStationData;
383+ I: Integer;
379384begin
380- for iHash in FStationsDicts[aRight].Keys do begin
385+ for I := 0 to cDictSize - 1 do begin
386+ iHash := FStationsDicts[aRight].Keys[I];
381387 // zero means empty slot: skip
382388 if iHash = 0 then
383389 continue;
@@ -387,13 +393,14 @@ procedure TOneBRC.Merge(aLeft: UInt16; aRight: UInt16);
387393 if FStationsDicts[aLeft].TryGetValue(iHash, vDataL) then begin
388394 vDataL^.Count := vDataL^.Count + vDataR^.Count;
389395 vDataL^.Sum := vDataL^.Sum + vDataR^.Sum;
396+
390397 if vDataR^.Max > vDataL^.Max then
391398 vDataL^.Max := vDataR^.Max;
392399 if vDataR^.Min < vDataL^.Min then
393400 vDataL^.Min := vDataR^.Min;
394401 end
395402 else begin
396- FStationsDicts[aLeft].Add (iHash, vDataR);
403+ FStationsDicts[aLeft].Add (iHash, vDataR, FStationsDicts[aRight].StationNames[I] );
397404 end ;
398405 end ;
399406end ;
@@ -419,14 +426,16 @@ procedure TOneBRC.GenerateOutput;
419426begin
420427 vStream := TStringStream.Create;
421428 vStations := TStringList.Create;
422- vStations.Capacity := 45000 ;
429+ vStations.Capacity := cDictSize ;
423430 vStations.UseLocale := False;
424431 try
425432 vStations.BeginUpdate;
426- for vData in FStationsDicts[0 ].Values do begin
433+ for I := 0 to cDictSize - 1 do begin
434+ vData := FStationsDicts[0 ].Values[I];
427435 // count = 0 means empty slot: skip
428- if vData^.Count <> 0 then
429- vStations.Add(vData^.Name );
436+ if vData^.Count <> 0 then begin
437+ vStations.Add(FStationsDicts[0 ].StationNames[I]);
438+ end ;
430439 end ;
431440 vStations.EndUpdate;
432441
0 commit comments