Skip to content

Commit c4243dd

Browse files
committed
Merge remote-tracking branch 'refs/remotes/origin/main'
2 parents 7ce393f + fbb6b17 commit c4243dd

45 files changed

Lines changed: 4129 additions & 855 deletions

Some content is hidden

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

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
/results
66
/entries/entries.json
77
*.sh
8+
*.cmd
89

910
# Compiled l10n files: .mo should be ignored
1011
*.mo

README.md

Lines changed: 21 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ Conakry;31.2
3333
Istanbul;23.0
3434
```
3535

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 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.):
3737

3838
```
3939
{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, ...}
@@ -70,45 +70,11 @@ Submit your implementation and become part of the leader board!
7070

7171
## Rounding
7272

73-
In a discussion with [Mr. Packman](https://pack.ac/) themselves, we came up with a simpler solution. They even added some _Unit Testing_ :D.
74-
75-
This will be the official way to round the output values, so pick your poison:
76-
```pas
77-
function RoundEx(x: Currency): Double; inline;
78-
begin
79-
Result := Ceil(x * 10) / 10;
80-
end;
81-
82-
function RoundExInteger(x: Currency): Integer; inline;
83-
begin
84-
Result := Ceil(x * 10);
85-
end;
86-
87-
{ Neater version by @bytebites from Lazarus forum }
88-
function RoundExString(x: Currency): String; inline;
89-
var
90-
V, Q, R: Integer;
91-
begin
92-
V := RoundExInteger(x);
93-
divmod(V, 10, Q, R);
94-
Result := IntToStr(Q) + '.' + chr(48 + Abs(R))
95-
end;
96-
97-
procedure Test;
98-
var
99-
F: Double;
100-
begin
101-
for F in [10.01, 10.04, -10.01, -10.0, 0, -0, -0.01] do
102-
WriteLn(RoundExInteger(F), ' ', RoundExString(F), ' ', RoundEx(F));
103-
//101 10.1 1.0100000000000000E+001
104-
//101 10.1 1.0100000000000000E+001
105-
//-100 -10.0 -1.0000000000000000E+001
106-
//-100 -10.0 -1.0000000000000000E+001
107-
//0 0.0 0.0000000000000000E+000
108-
//0 0.0 0.0000000000000000E+000
109-
//0 0.0 0.0000000000000000E+000
110-
end;
111-
```
73+
With the help of this magnificent community, we were able to finally get to a rounding solution that works.
74+
75+
This means that I'm encouraging everyone to use the code that is now in the [Baseline.Common](baseline/Common) unit.\
76+
I do have to make crystal clear that using that code is an **option**, one that you can always opt out of.\
77+
But if you do opt in, just include that unit in your entry and job's a done.
11278

11379
## Generating the measurements.txt
11480
> **NOTE**
@@ -156,12 +122,12 @@ Expected `SHA256` hash:
156122
`ebad17b266ee9f5cb3d118531f197e6f68c9ab988abc5cb9506e6257e1a52ce6`
157123

158124
## Verify Output File
159-
> **NOTE**
160-
>
161-
> We are still waiting for the Delphi version to be completed in order for us to have an official `SHA256` hash for the output.
162-
>
163-
> Until then, this is the current one: `683bb3d247f53bab96e98983771d66bc9d7dbfb38aa3fecac4c04b8ab29e3032`
164-
> There's also an archived version of the [baseline output](./data/baseline.output.gz)
125+
126+
There is now a Delphi version of the baseline. This means that we now have an official way of generating a valid output on both sides of the fence.
127+
128+
With this, we now have the official hash: `4256d19d3e134d79cc6f160d428a1d859ce961167bd01ca528daca8705163910`
129+
130+
There's also an archived version of the [baseline output](./data/baseline.output.gz)
165131

166132
## Differences From Original
167133
I've decided that I would want this challenge to be turned way up to 11!
@@ -188,11 +154,13 @@ These are the results from running all entries into the challenge on my personal
188154

189155
| # | Result (m:s.ms) | Compiler | Submitter | Notes | Certificates |
190156
|--:|----------------:|---------:|:----------|:------|:-------------|
191-
| 1 | 0:1.7599 | lazarus-3.0, fpc-3.2.2 | Arnaud Bouchez | Using `mORMot2`, 32 threads | |
192-
| 2 | 0:16.874 | lazarus-3.0, fpc-3.2.2 | Székely Balázs | Using 32 threads | |
193-
| 3 | 0:20.0693 | lazarus-3.0, fpc-3.2.2 | Lurendrejer Aksen | Using 32 threads | |
194-
| 4 | 1:16.059 | lazarus-3.0, fpc-3.2.2 | Richard Lawson | Using 1 thread | |
195-
| 5 | 12:37.7864 | lazarus-3.0, fpc-3.2.2 | Iwan Kelaiah | Using 1 thread | |
157+
| 1 | 0:1.971 | lazarus-3.0, fpc-3.2.2 | Arnaud Bouchez | Using `mORMot2`, 32 threads | |
158+
| 2 | 0:20.960 | lazarus-3.0, fpc-3.2.2 | Székely Balázs | Using 32 threads | |
159+
| 3 | 0:23.158 | lazarus-3.0, fpc-3.2.2 | Lurendrejer Aksen | Using 32 threads **(failed hash)** | |
160+
| 4 | 1:23.684 | lazarus-3.0, fpc-3.2.2 | Richard Lawson | Using a single thread | |
161+
| 5 | 5:2.512 | lazarus-3.0, fpc-3.2.2 | Iwan Kelaiah | Using a single thread | |
162+
| 6 | 7:54.606 | delphi 12.1 | David Cornelius | Using 1 threads **(failed hash)** | |
163+
| 7 | 10:55.724 | delphi 12.1 | Brian Fire | Using 1 threads | |
196164

197165
> **NOTE**
198166
>
@@ -224,7 +192,8 @@ I'd like to thank [@mobius](https://github.com/mobius1qwe) for taking the time t
224192
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.\
225193
I'd like to thank Székely Balázs for providing many patches to make everything compliant with the original challenge.\
226194
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.\
227-
I'd like to thank Mr. **Pack**man, aka O, for clearing the fog around the rounding issues.
195+
I'd like to thank Mr. **Pack**man, aka O, for clearing the fog around the rounding issues.\
196+
I'd like to thank [Georges](https://github.com/georges-hatem) for providing us with the Delphi version of baseline.
228197

229198
## Links
230199
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: Currency): 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: Currency): 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)