Skip to content

Commit 6b6e72a

Browse files
refactor: Optimize after user group discussion
1 parent cec597e commit 6b6e72a

5 files changed

Lines changed: 79 additions & 66 deletions

File tree

entries/dcornelius/src/uChallengeCommon.pas

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,18 @@ interface
1313
TWeatherCity = class
1414
public
1515
CityName: string;
16-
MinTemp: Single;
17-
MaxTemp: Single;
16+
MinTemp: Integer;
17+
MaxTemp: Integer;
1818
DataCount: Int64;
19-
TotalTemp: Double;
20-
constructor Create(const NewCityName: string; const NewTemp: single);
21-
procedure AddNewTemp(const NewTemp: Single);
19+
TotalTemp: Int64;
20+
constructor Create(const NewCityName: string; const NewTemp: Integer);
21+
procedure AddNewTemp(const NewTemp: Integer);
2222
function Mean: Double;
23+
function OutputSumLine: string;
2324
end;
2425

2526
// anonymous method type
26-
TWeatherCityProc = reference to procedure(const City: string; const Temp: Double);
27+
TWeatherCityProc = reference to procedure(const City: string; const Temp: Integer);
2728

2829
// a global class to provide standard open/close and other functions
2930
TChallengeCommon = class
@@ -36,7 +37,7 @@ TChallengeCommon = class
3637
procedure CloseWeatherData;
3738
procedure ReadAndParseAllData(WeatherCityProcessor: TWeatherCityProc);
3839
function PascalRound(x: Double): Double;
39-
function SplitCityTemp(const StationLine: string; var CityName: string; var CityTemp: Double): Boolean;
40+
function SplitCityTemp(const StationLine: string; var CityName: string; var CityTemp: Integer): Boolean;
4041
property InputFilename: string read FInputFilename write FInputFilename;
4142
property WeatherDataFile: TextFile read FWeatherDataFile;
4243
end;
@@ -47,7 +48,11 @@ TChallengeCommon = class
4748
implementation
4849

4950
uses
50-
System.Classes, System.SysUtils, System.Math;
51+
System.Classes, System.SysUtils,
52+
{$IFDEF DEBUG}
53+
System.Diagnostics,
54+
{$ENDIF }
55+
System.Math;
5156

5257
{ TChallengeCommon }
5358

@@ -88,14 +93,23 @@ procedure TChallengeCommon.ReadAndParseAllData(WeatherCityProcessor: TWeatherCit
8893
var
8994
WeatherLine: string;
9095
WeatherCity: string;
91-
CityTemp: Double;
96+
CityTemp: Integer;
97+
LineCount: Int64;
9298
begin
99+
{$IFDEF DEBUG}
100+
var StopWatch := TStopwatch.StartNew;
101+
LineCount := 0;
102+
{$ENDIF}
103+
93104
OpenWeatherData;
94105
try
95106
// read all rows
96107
while not Eof(WeatherDataFile) do begin
97108
// read a row into a temp string
98109
Readln(WeatherDataFile, WeatherLine);
110+
{$IFDEF DEBUG}
111+
Inc(LineCount);
112+
{$ENDIF}
99113

100114
// parse the data and call a procedure to process it
101115
if SplitCityTemp(WeatherLine, WeatherCity, CityTemp) then
@@ -104,14 +118,20 @@ procedure TChallengeCommon.ReadAndParseAllData(WeatherCityProcessor: TWeatherCit
104118
finally
105119
ChallengeCommon.CloseWeatherData;
106120
end;
121+
122+
{$IFDEF DEBUG}
123+
StopWatch.Stop;
124+
Writeln(Format('Loaded %d lines from %s in %d milliseconds', [LineCount, FInputFilename,
125+
StopWatch.ElapsedMilliseconds]));
126+
{$ENDIF}
107127
end;
108128

109129
procedure TChallengeCommon.CloseWeatherData;
110130
begin
111131
CloseFile(FWeatherDataFile);
112132
end;
113133

114-
function TChallengeCommon.SplitCityTemp(const StationLine: string; var CityName: string; var CityTemp: Double): Boolean;
134+
function TChallengeCommon.SplitCityTemp(const StationLine: string; var CityName: string; var CityTemp: Integer): Boolean;
115135
var
116136
SemiPos: Integer;
117137
TempStr: string;
@@ -126,14 +146,16 @@ function TChallengeCommon.SplitCityTemp(const StationLine: string; var CityName:
126146
Exit;
127147

128148
CityName := Copy(StationLine, 1, SemiPos - 1);
129-
TempStr := Copy(StationLine, SemiPos + 1, 50);
149+
TempStr := Trim(Copy(StationLine, SemiPos + 1, 50));
150+
// remove the decimal point to make this an integer
151+
CityTemp := StrToInt(Copy(TempStr, 1, Length(TempStr) - 2) + Copy(TempStr, Length(TempStr), 1));
130152

131-
Result := TryStrToFloat(TempStr, CityTemp);
153+
Result := True;
132154
end;
133155

134156
{ TWeatherCity }
135157

136-
procedure TWeatherCity.AddNewTemp(const NewTemp: Single);
158+
procedure TWeatherCity.AddNewTemp(const NewTemp: Integer);
137159
begin
138160
Inc(DataCount);
139161

@@ -147,7 +169,7 @@ procedure TWeatherCity.AddNewTemp(const NewTemp: Single);
147169
TotalTemp := TotalTemp + NewTemp;
148170
end;
149171

150-
constructor TWeatherCity.Create(const NewCityName: string; const NewTemp: single);
172+
constructor TWeatherCity.Create(const NewCityName: string; const NewTemp: Integer);
151173
begin
152174
CityName := NewCityName;
153175
DataCount := 1;
@@ -161,4 +183,13 @@ function TWeatherCity.Mean: Double;
161183
Result := ChallengeCommon.PascalRound(TotalTemp / DataCount);
162184
end;
163185

186+
function TWeatherCity.OutputSumLine: string;
187+
begin
188+
Result := Format(' %s=%0.1f/%0.1f/%0.1f', [CityName,
189+
MinTemp / 10,
190+
Mean,
191+
MaxTemp / 10]);
192+
193+
end;
194+
164195
end.

entries/dcornelius/src/uChallengeWithDictionary.pas

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
* NOTE: This is a single-threaded process.
1010
*
11-
* Processing time when reading in a 1-billion row file: 9 minutes (22½ minutes on WSL-Windows Subsystem for Linux)
11+
* Processing time when reading in a 1-billion row file: 9 minutes
1212
*)
1313

1414
interface
@@ -31,32 +31,22 @@ procedure ChallengeWithDictionary;
3131
var
3232
SortedList: TStringList;
3333
CurrWeatherCity: TWeatherCity;
34-
TempLine: string;
3534
begin
3635
WeatherCityList := TDictionary<string, TWeatherCity>.Create;
3736
try
38-
ChallengeCommon.ReadAndParseAllData(procedure (const CityName: string; const CityTemp: Double)
37+
ChallengeCommon.ReadAndParseAllData(procedure (const CityName: string; const CityTemp: Integer)
3938
begin
4039
if WeatherCityList.TryGetValue(CityName, CurrWeatherCity) then
4140
CurrWeatherCity.AddNewTemp(CityTemp)
4241
else
4342
WeatherCityList.Add(CityName, TWeatherCity.Create(CityName, CityTemp));
4443
end);
4544

46-
{$IFDEF DEBUG}
47-
Writeln(Format('Loaded %d lines from %s', [WeatherCityList.Count, ChallengeCommon.InputFilename]));
48-
{$ENDIF}
49-
5045
// create the output list
51-
SortedList := TStringList.Create;
46+
SortedList := TStringList.Create(TDuplicates.dupAccept, False, True);
5247
try
53-
for var WeatherSum in WeatherCityList do begin
54-
TempLine := Format(' %s=%0.1f/%0.1f/%0.1f', [WeatherSum.Value.CityName,
55-
WeatherSum.Value.MinTemp,
56-
WeatherSum.Value.Mean,
57-
WeatherSum.Value.MaxTemp]);
58-
SortedList.Add(TempLine);
59-
end;
48+
for var WeatherSum in WeatherCityList do
49+
SortedList.Append(WeatherSum.Value.OutputSumLine);
6050

6151
// sort and write out the data
6252
SortedList.Sort;

entries/dcornelius/src/uChallengeWithStringList.pas

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,17 @@ implementation
1717

1818
uses
1919
System.SysUtils, System.Classes, System.StrUtils,
20+
{$IFDEF DEBUG}
21+
System.Diagnostics,
22+
{$ENDIF }
2023
uChallengeCommon;
2124

2225
procedure ChallengeWithStringList;
2326
var
2427
WeatherLines: TStringList;
2528
SortedList: TStringList;
2629
WeatherCity: string;
27-
CityTemp: Double;
30+
CityTemp: Integer;
2831
ListCity: Integer;
2932
CurrLine: Int64;
3033
begin
@@ -33,13 +36,18 @@ procedure ChallengeWithStringList;
3336
WeatherLines.Delimiter := ';';
3437
{$IFDEF DEBUG}
3538
Writeln('Reading from ' + ChallengeCommon.InputFilename);
39+
40+
var StopWatch := TStopwatch.StartNew;
3641
{$ENDIF}
42+
3743
WeatherLines.LoadFromFile(ChallengeCommon.InputFilename);
44+
3845
{$IFDEF DEBUG}
39-
Writeln(Format('Loaded %d lines from %s', [WeatherLines.Count, ChallengeCommon.InputFilename]));
46+
StopWatch.Stop;
47+
Writeln(Format('Loaded %d lines from %s in %d milliseconds', [WeatherLines.Count, ChallengeCommon.InputFilename,
48+
StopWatch.ElapsedMilliseconds]));
4049
{$ENDIF}
4150

42-
4351
SortedList := TStringList.Create;
4452
try
4553
SortedList.Sorted := True;
@@ -56,22 +64,9 @@ procedure ChallengeWithStringList;
5664
end;
5765

5866
Write('{');
59-
for var i := 0 to SortedList.Count - 1 do begin
60-
{$IFDEF DEBUG}
61-
Write(Format('%s=%0.1f/%0.1f/%0.1f (%d stores)%s', [TWeatherCity(SortedList.Objects[i]).CityName,
62-
TWeatherCity(SortedList.Objects[i]).MinTemp,
63-
TWeatherCity(SortedList.Objects[i]).Mean,
64-
TWeatherCity(SortedList.Objects[i]).MaxTemp,
65-
TWeatherCity(SortedList.Objects[i]).DataCount,
66-
IfThen(i = SortedList.Count - 1, '', ', ')]));
67-
{$ELSE}
68-
Write(Format('%s=%0.1f/%0.1f/%0.1f%s', [TWeatherCity(SortedList.Objects[i]).CityName,
69-
TWeatherCity(SortedList.Objects[i]).MinTemp,
70-
TWeatherCity(SortedList.Objects[i]).Mean,
71-
TWeatherCity(SortedList.Objects[i]).MaxTemp,
72-
IfThen(i = SortedList.Count - 1, '', ',')]));
73-
{$ENDIF}
74-
end;
67+
Write(Trim(TWeatherCity(SortedList.Objects[0]).OutputSumLine));
68+
for var i := 1 to SortedList.Count - 1 do
69+
Write(TWeatherCity(SortedList.Objects[i]).OutputSumLine);
7570
Writeln('}');
7671
{$IFDEF DEBUG}
7772
Writeln('Unique Stations: ', SortedList.Count);

entries/dcornelius/src/udmChallengeWithFireDAC.dfm

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
object dmChallengeWithFireDAC: TdmChallengeWithFireDAC
2-
Height = 293
3-
Width = 348
2+
Height = 366
3+
Width = 435
4+
PixelsPerInch = 120
45
object tblWeatherData: TFDMemTable
56
ActiveStoredUsage = [auDesignTime]
67
Active = True
@@ -24,8 +25,8 @@ object dmChallengeWithFireDAC: TdmChallengeWithFireDAC
2425
UpdateOptions.AutoCommitUpdates = True
2526
LocalSQL = FDLocalSQL
2627
StoreDefs = True
27-
Left = 208
28-
Top = 80
28+
Left = 260
29+
Top = 100
2930
object tblWeatherDataCityName: TStringField
3031
FieldName = 'CityName'
3132
Size = 50
@@ -35,24 +36,24 @@ object dmChallengeWithFireDAC: TdmChallengeWithFireDAC
3536
end
3637
end
3738
object FDPhysSQLiteDriverLink: TFDPhysSQLiteDriverLink
38-
Left = 72
39-
Top = 32
39+
Left = 90
40+
Top = 40
4041
end
4142
object FDConnection: TFDConnection
4243
Params.Strings = (
4344
'DriverID=SQLite')
4445
Connected = True
4546
LoginPrompt = False
46-
Left = 80
47-
Top = 96
47+
Left = 100
48+
Top = 120
4849
end
4950
object FDLocalSQL: TFDLocalSQL
5051
SchemaName = 'measurements'
5152
Connection = FDConnection
5253
Active = True
5354
DataSets = <>
54-
Left = 80
55-
Top = 168
55+
Left = 100
56+
Top = 210
5657
end
5758
object qryCityTemps: TFDQuery
5859
ActiveStoredUsage = [auDesignTime]
@@ -70,8 +71,8 @@ object dmChallengeWithFireDAC: TdmChallengeWithFireDAC
7071
'from measurements.tblWeatherData'
7172
'group by CityName'
7273
'order by CityName')
73-
Left = 200
74-
Top = 144
74+
Left = 250
75+
Top = 180
7576
object qryCityTempsCityName: TStringField
7677
FieldName = 'CityName'
7778
Origin = 'CityName'

entries/dcornelius/src/udmChallengeWithFireDAC.pas

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
* NOTE: This is a single-threaded process.
1010
*
11-
* Processing time when reading in a 1-billion row file:
11+
* Processing time when reading in a 1-billion row file: ___
1212
*)
1313

1414
interface
@@ -71,15 +71,11 @@ procedure ChallengeWithFireDAC;
7171
dmChallengeWithFireDAC.tblWeatherData.Open;
7272
dmChallengeWithFireDAC.tblWeatherData.EmptyDataSet;
7373

74-
ChallengeCommon.ReadAndParseAllData(procedure (const CityName: string; const CityTemp: Double)
74+
ChallengeCommon.ReadAndParseAllData(procedure (const CityName: string; const CityTemp: Integer)
7575
begin
7676
dmChallengeWithFireDAC.tblWeatherData.InsertRecord([CityName, CityTemp]);
7777
end);
7878

79-
{$IFDEF DEBUG}
80-
Writeln(Format('Loaded %d lines from %s', [dmChallengeWithFireDAC.tblWeatherData.RecordCount, ChallengeCommon.InputFilename]));
81-
{$ENDIF}
82-
8379
dmChallengeWithFireDAC.qryCityTemps.Close;
8480
dmChallengeWithFireDAC.qryCityTemps.Open;
8581

0 commit comments

Comments
 (0)