diff --git a/README.md b/README.md index cf50625..4a3c012 100644 --- a/README.md +++ b/README.md @@ -7,4 +7,5 @@ |2|Remove sorting float64 slices. Calculate min, max and average by iterating.|4:25.59|-7.21|[830e5df](https://github.com/shraddhaag/1brc/commit/830e5dfacff9fb7a41d12027e21399736bc34701)| |3|Decouple reading and processing of file content. A buffered goroutine is used to communicate between the two processes.|5:22.83|+57.24|[2babf7d](https://github.com/shraddhaag/1brc/commit/2babf7dda72d92c72722b220b8b663e747075bd7)| |4|Instead of sending each line to the channel, now sending 100 lines chunked together. Also, to minimise garbage collection, not freeing up memory when resetting a slice. |3:41.76|-161.07|[b7b1781](https://github.com/shraddhaag/1brc/commit/b7b1781f58fd258a06940bd6c05eb404c8a14af6)| -|5|Read file in chunks of 100 MB instead of reading line by line. |3:32.62|-9.14|| \ No newline at end of file +|5|Read file in chunks of 100 MB instead of reading line by line. |3:32.62|-9.14|[c26fea4](https://github.com/shraddhaag/1brc/commit/c26fea40019552a7e4fc1c864236f433b1b686f0)| +|6|Convert temperature from `string` to `int64`, process in `int64` and convert to `float64` at the end. |2:51.50|-41.14|| \ No newline at end of file diff --git a/main.go b/main.go index 3f6c86d..55ca81d 100644 --- a/main.go +++ b/main.go @@ -91,10 +91,10 @@ func evaluate(input string) string { for city, temps := range mapOfTemp { wg.Add(1) - go func(city string, temps []float64) { + go func(city string, temps []int64) { defer wg.Done() - var min, max, avg float64 - min, max = math.MaxFloat64, math.MinInt64 + var min, max, avg int64 + min, max = math.MaxInt64, math.MinInt64 for _, temp := range temps { if temp < min { @@ -107,10 +107,7 @@ func evaluate(input string) string { avg += temp } - avg = avg / float64(len(temps)) - avg = math.Ceil(avg*10) / 10 - - updateResult(city, fmt.Sprintf("%.1f/%.1f/%.1f", min, avg, max)) + updateResult(city, fmt.Sprintf("%.1f/%.1f/%.1f", round(float64(min)/10.0), round(float64(avg)/10.0/float64(len(temps))), round(float64(max)/10.0))) }(city, temps) } @@ -127,13 +124,13 @@ func evaluate(input string) string { return stringsBuilder.String()[:stringsBuilder.Len()-2] } -func readFileLineByLineIntoAMap(filepath string) (map[string][]float64, error) { +func readFileLineByLineIntoAMap(filepath string) (map[string][]int64, error) { file, err := os.Open(filepath) if err != nil { panic(err) } - mapOfTemp := make(map[string][]float64) + mapOfTemp := make(map[string][]int64) chanOwner := func() <-chan []string { resultStream := make(chan []string, 100) @@ -172,11 +169,11 @@ func readFileLineByLineIntoAMap(filepath string) (map[string][]float64, error) { continue } city := text[:index] - temp := convertStringToFloat(text[index+1:]) + temp := convertStringToInt64(text[index+1:]) if _, ok := mapOfTemp[city]; ok { mapOfTemp[city] = append(mapOfTemp[city], temp) } else { - mapOfTemp[city] = []float64{temp} + mapOfTemp[city] = []int64{temp} } } } @@ -188,8 +185,9 @@ type cityTemp struct { temp float64 } -func convertStringToFloat(input string) float64 { - output, _ := strconv.ParseFloat(input, 64) +func convertStringToInt64(input string) int64 { + input = input[:len(input)-2] + input[len(input)-1:] + output, _ := strconv.ParseInt(input, 10, 64) return output } @@ -215,3 +213,11 @@ func processReadChunk(buf []byte, readTotal, count int, stringsBuilder *strings. return count } + +func round(x float64) float64 { + rounded := math.Round(x * 10) + if rounded == -0.0 { + return 0.0 + } + return rounded / 10 +}