Skip to content

Commit ec7dd02

Browse files
authored
Merge branch 'main' into ikelaiah-rev05
2 parents 9b3f72a + e4f066c commit ec7dd02

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+4055
-606
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
/profiling
55
/results
66
/entries/entries.json
7-
*_all.*
7+
*.sh
88

99
# Compiled l10n files: .mo should be ignored
1010
*.mo

README.md

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
# 1️⃣🐝🏎️ The One Billion Row Challenge in Object Pascal
22
<p>
3-
<a href="https://discord.gg/c382VBk"><img src="https://img.shields.io/discord/623794270255579146?label=Delphi Community Discord" alt="Delphi Community" /></a>
4-
<a href="https://discord.gg/3VdxbSFyJP"><img src="https://img.shields.io/discord/570025060312547359?label=Unofficial Free Pacal Discord" alt="Unofficial Free Pacal" /></a>
3+
<a href="https://discord.gg/c382VBk"><img src="https://img.shields.io/discord/623794270255579146?label=Delphi Community&logo=discord" alt="Delphi Community" /></a>
4+
<a href="https://discord.gg/3VdxbSFyJP"><img src="https://img.shields.io/discord/570025060312547359?label=Unofficial Free Pascal&logo=discord" alt="Unofficial Free Pacal" /></a>
5+
<a href="https://t.me/delphidevelopers"><img src="https://img.shields.io/badge/Telegram-Delphi_Developers-blue?logo=telegram" /></a>
6+
<a href="https://t.me/freepascal_en"><img src="https://img.shields.io/badge/Telegram-Free_Pascal_&_Lazarus-blue?logo=telegram" /></a>
57
<a href="https://forum.lazarus.freepascal.org/index.php/topic,66571.0.html"><img src="https://img.shields.io/badge/Lazarus_Forum-1BRC_Thread-blue" /></a>
68
<a href="https://en.delphipraxis.net/topic/11209-offical-launch-of-the-1-billion-row-challenge-in-object-pascal/"><img src="https://img.shields.io/badge/Delphi_Praxis_Forum-1BRC_Thread-blue" /></a>
79
</p>
@@ -31,7 +33,7 @@ Conakry;31.2
3133
Istanbul;23.0
3234
```
3335

34-
The task is to write an Object Pascal program which reads the file, calculates the min, mean, and max temperature value per weather station, and emits the results on `STDOUT` like this (i.e., sorted alphabetically by station name, and the result values per station in the format `<min>/<mean>/<max>`, rounded to one fractional digit towards positive infinity with both `17.01` and `17.05` being rounded to `17.1`, with the decimal separator being a period `.`):
36+
The task is to write an Object Pascal program which reads the file, calculates the min, mean, and max temperature value per weather station, and emits the results on `STDOUT` like this (i.e., sorted alphabetically by station name, and the result values per station in the format `<min>/<mean>/<max>`, rounded to one fractional digit, with the decimal separator being a period `.`, and for that you can chose one of the options presented in the [Rounding Section](#rounding) or implement your own that is consistent with the options provided.):
3537

3638
```
3739
{Abha=-23.0/18.0/59.2, Abidjan=-16.2/26.0/67.3, Abéché=-10.0/29.4/69.0, Accra=-10.1/26.4/66.4, Addis Ababa=-23.7/16.0/67.0, Adelaide=-27.8/17.3/58.5, ...}
@@ -72,31 +74,24 @@ In a discussion with [Mr. Packman](https://pack.ac/) themselves, we came up with
7274

7375
This will be the official way to round the output values, so pick your poison:
7476
```pas
75-
function RoundEx(x: Double): Double; inline;
77+
function RoundEx(x: Currency): Double; inline;
7678
begin
7779
Result := Ceil(x * 10) / 10;
7880
end;
7981
80-
function RoundExInteger(x: Double): Integer; inline;
82+
function RoundExInteger(x: Currency): Integer; inline;
8183
begin
8284
Result := Ceil(x * 10);
8385
end;
8486
85-
function RoundExString(x: Double): String; inline;
87+
{ Neater version by @bytebites from Lazarus forum }
88+
function RoundExString(x: Currency): String; inline;
8689
var
8790
V, Q, R: Integer;
8891
begin
8992
V := RoundExInteger(x);
90-
if V < 0 then
91-
begin
92-
Result := '-';
93-
V := -V;
94-
end
95-
else
96-
Result := '';
97-
Q := V div 10;
98-
R := V - (Q * 10);
99-
Result := Result + IntToStr(Q) + '.' + IntToStr(R);
93+
divmod(V, 10, Q, R);
94+
Result := IntToStr(Q) + '.' + chr(48 + Abs(R))
10095
end;
10196
10297
procedure Test;
@@ -165,7 +160,7 @@ Expected `SHA256` hash:
165160
>
166161
> We are still waiting for the Delphi version to be completed in order for us to have an official `SHA256` hash for the output.
167162
>
168-
> Until then, this is the current one: `4256d19d3e134d79cc6f160d428a1d859ce961167bd01ca528daca8705163910`
163+
> Until then, this is the current one: `683bb3d247f53bab96e98983771d66bc9d7dbfb38aa3fecac4c04b8ab29e3032`
169164
> There's also an archived version of the [baseline output](./data/baseline.output.gz)
170165
171166
## Differences From Original
@@ -229,7 +224,8 @@ I'd like to thank [@mobius](https://github.com/mobius1qwe) for taking the time t
229224
I'd like to thank [@dtpfl](https://github.com/dtpfl) for his invaluable work on maintaining the `README.md` file up to date with everything.\
230225
I'd like to thank Székely Balázs for providing many patches to make everything compliant with the original challenge.\
231226
I'd like to thank [@corneliusdavid](https://github.com/corneliusdavid) for giving some of the information files a once over and making things more legible and clear.\
232-
I'd like to thank Mr. **Pack**man, aka O, for clearing the fog around the rounding issues.
227+
I'd like to thank Mr. **Pack**man, aka O, for clearing the fog around the rounding issues.\
228+
I'd like to thank [Georges](https://github.com/georges-hatem) for providing us with the Delphi version of baseline.
233229

234230
## Links
235231
The original repository: https://github.com/gunnarmorling/1brc \

baseline/Common/baseline.common.pas

Lines changed: 17 additions & 199 deletions
Original file line numberDiff line numberDiff line change
@@ -7,219 +7,37 @@
77
interface
88

99
uses
10-
Classes
11-
, SysUtils
12-
{$IFDEF FPC}
13-
, Contnrs
14-
{$ELSE}
15-
{$ENDIF}
16-
10+
{$IFDEF FPC}
11+
SysUtils
12+
{$ELSE}
13+
System.SysUtils
14+
{$ENDIF}
1715
;
1816

19-
type
20-
{ TWeatherStation }
21-
PWeatherStation = ^TWeatherStation;
22-
TWeatherStation = record
23-
FStation: String[100];
24-
FMin: Int64;
25-
FMax: Int64;
26-
FTot: Int64;
27-
FCnt: Integer;
28-
29-
end;
30-
{ TBaseline }
31-
TBaseline = class(TObject)
32-
private
33-
FInputFile: String;
34-
FStationNames: TStringList;
35-
FHashStationList: TFPHashList;
36-
procedure AddToHashList(AStation: String; ATemp: Int64);
37-
procedure BuildHashList;
38-
function RoundEx(x: Double): Double;
39-
protected
40-
public
41-
constructor Create(AInputFile: String);
42-
destructor Destroy; override;
43-
44-
procedure Generate;
45-
published
46-
end;
47-
48-
{$IFNDEF FPC}
49-
TStringArray = array of Utf8String;
50-
TWriteBufStream = TFileStream;
51-
{$ENDIF}
17+
function RoundExDouble(const ATemp: Double): Double;
18+
function RoundExInteger(const ATemp: Double): Integer;
5219

5320
implementation
5421

55-
uses
56-
Math
57-
{$IFDEF FPC}
58-
, streamex
59-
{$ELSE}
60-
, System.Diagnostics
61-
{$IF defined(MSWINDOWS)}, Winapi.Windows{$ENDIF}
62-
{$ENDIF}
63-
;
64-
65-
const
66-
//lineEnding = #13#10;
67-
stationsCapacity = 50000;
68-
69-
70-
function Compare(AList: TStringList; AIndex1, AIndex2: Integer): Integer;
71-
var
72-
Pos1, Pos2: Integer;
73-
Str1, Str2: String;
74-
begin
75-
Result := 0;
76-
Str1 := AList.Strings[AIndex1];
77-
Str2 := AList.Strings[AIndex2];
78-
Pos1 := Pos('=', Str1);
79-
Pos2 := Pos('=', Str2);
80-
if (Pos1 > 0) and (Pos2 > 0) then
81-
begin
82-
Str1 := Copy(Str1, 1, Pos1 - 1);
83-
Str2 := Copy(Str2, 1, Pos2 - 1);
84-
Result := CompareStr(Str1, Str2);
85-
end;
86-
end;
87-
88-
{ TBaseline }
89-
90-
constructor TBaseline.Create(AInputFile: String);
91-
begin
92-
FInputFile := AInputFile;
93-
94-
FHashStationList:= TFPHashList.Create;
95-
FHashStationList.Capacity:= stationsCapacity;
96-
97-
FStationNames := TStringList.Create;
98-
FStationNames.Capacity := stationsCapacity;
99-
FStationNames.UseLocale := False;
100-
end;
101-
102-
destructor TBaseline.Destroy;
103-
var
104-
index: Integer;
105-
begin
106-
FStationNames.Free;
107-
for index:= 0 to FHashStationList.Count - 1 do
108-
begin
109-
Dispose(PWeatherStation(FHashStationList.Items[index]));
110-
end;
111-
FHashStationList.Free;
112-
inherited Destroy;
113-
end;
114-
115-
procedure TBaseline.AddToHashList(AStation: String; ATemp: Int64);
116-
var
117-
weatherStation: PWeatherStation;
118-
Index: Integer;
22+
function Ceiling(const ANumber: Double): integer; inline;
11923
begin
120-
Index := FHashStationList.FindIndexOf(AStation);
121-
if Index = -1 then
122-
begin
123-
New(weatherStation);
124-
weatherStation^.FStation := AStation;
125-
weatherStation^.FMin := ATemp;
126-
weatherStation^.FMax := ATemp;
127-
weatherStation^.FTot := ATemp;
128-
weatherStation^.FCnt := 1;
129-
FHashStationList.Add(AStation, weatherStation);
130-
end
131-
else
132-
begin
133-
weatherStation := FHashStationList.Items[Index];
134-
weatherStation^.FMin := Min(weatherStation^.FMin, ATemp);
135-
weatherStation^.FMax := Max(weatherStation^.FMax, ATemp);
136-
weatherStation^.FTot := weatherStation^.FTot + ATemp;
137-
weatherStation^.FCnt := weatherStation^.FCnt + 1;
138-
end;
24+
Result := Trunc(ANumber) + Ord(Frac(ANumber) > 0);
13925
end;
14026

141-
procedure TBaseline.BuildHashList;
27+
function RoundExDouble(const ATemp: Double): Double; inline;
14228
var
143-
inputFileStream: TFileStream;
144-
streamReader: TStreamReader;
145-
position, Code: Integer;
146-
strLine: String;
147-
strStation: String;
148-
strTemp: String;
149-
temparature: Int64;
150-
begin
151-
if FileExists(FInputFile) then
152-
begin
153-
inputFileStream:= TFileStream.Create(FInputFile, fmOpenRead);
154-
try
155-
streamReader:= TStreamReader.Create(inputFileStream);
156-
try
157-
while not streamReader.Eof do
158-
begin
159-
strLine:= streamReader.ReadLine;
160-
position := Pos(';', strLine);
161-
if position > 0 then
162-
begin
163-
strStation := Copy(strLine, 1, position - 1);
164-
strTemp := Copy(strLine, position + 1, Length(strLine));
165-
strTemp := StringReplace(strTemp, '.', '', [rfReplaceAll]);
166-
Val(strTemp, temparature, Code);
167-
if Code <> 0 then
168-
Continue;
169-
AddToHashList(strStation, temparature);
170-
end;
171-
end;
172-
finally
173-
streamReader.Free;
174-
end;
175-
finally
176-
inputFileStream.Free;
177-
end;
178-
end
179-
else
180-
begin
181-
raise Exception.Create(Format('File "%s" not found.', [FInputFile]));
182-
end;
183-
end;
184-
185-
function TBaseline.RoundEx(x: Double): Double;
29+
tmp: Double;
18630
begin
187-
Result := Ceil(x * 10) / 10;
31+
tmp:= ATemp * 10;
32+
Result := Ceiling(tmp) / 10;
18833
end;
18934

190-
procedure TBaseline.Generate;
35+
function RoundExInteger(const ATemp: Double): Integer; inline;
19136
var
192-
index: Integer;
193-
strTemp: String;
194-
min: Double;
195-
max: Double;
196-
mean: Double;
197-
weatherStation: PWeatherStation;
37+
tmp: Double;
19838
begin
199-
200-
BuildHashList;
201-
202-
FStationNames.BeginUpdate;
203-
for index := 0 to FHashStationList.Count - 1 do
204-
begin
205-
weatherStation := FHashStationList.Items[index];
206-
Min := RoundEx(weatherStation^.FMin/10);
207-
Max := RoundEx(weatherStation^.FMax/10);
208-
Mean := RoundEx(weatherStation^.FTot/weatherStation^.FCnt/10);
209-
strTemp := weatherStation^.FStation + '=' + FormatFloat('0.0', Min) + '/' + FormatFloat('0.0', Mean) + '/' + FormatFloat('0.0', Max) + ',';
210-
FStationNames.Add(strTemp);
211-
end;
212-
FStationNames.EndUpdate;
213-
FStationNames.CustomSort(@Compare);
214-
215-
strTemp:= '';
216-
for index:= 0 to FStationNames.Count - 1 do
217-
begin
218-
strTemp:= strTemp + FStationNames[index] + ' ';
219-
end;
220-
SetLength(strTemp, Length(strTemp) - 2);
221-
WriteLn('{', strTemp, '}');
222-
39+
tmp:= ATemp * 10;
40+
Result := Ceiling(tmp);
22341
end;
22442

22543
end.

0 commit comments

Comments
 (0)