Update: Tried benchmarking an older version of advent of code script, which
parses the input in one go, then loops through the parsed sequences once for
the first solution, then again for the second solution
import strutils,std/strformat,tables
type ball = tuple[number: int, color: string]
type set = seq[ball]
type game = seq[set]
var allgames = newSeq[game]()
proc processInputs(inputLines: seq[string]) =
var gameId,ballnum: int
var sets,balls,thisball: seq[string]
var games,ballcolor: string
for lineI,lineV in inputLines:
# echo inputLines
gameId = lineI + 1
games = lineV.split(": ")[1]
sets = games.split("; ")
var thisgame = newSeq[set]()
for setI,setV in sets.pairs:
# echo "set " & setI.string
var thisset = newSeq[ball]()
balls = setV.split(", ")
for ball in balls:
thisball = ball.split(" ")
ballnum = parseInt(thisball[0])
ballcolor = thisball[1]
thisset.add((ballnum,ballcolor))
thisgame.add(thisset)
allgames.add(thisgame)
# echo allgames
proc Level1(): int=
var sum,gameId: int
const colorLimits = {"red":12,"green":13,"blue":14}.toTable
for gameI,gameV in allgames.pairs:
# echo inputLines
var impossible = false
gameId = gameI + 1
for set in gameV:
for ball in set:
if ball.number > colorLimits[ball.color]:
impossible = true
if impossible == false:
sum += gameId
return sum
proc Level2(): int=
var gameId,sum: int
for gameI,gameV in allgames.pairs:
var minBalls = {"red":0,"green":0,"blue":0}.toTable
gameId = gameI + 1
for set in gameV:
# echo "set " & setI.string
for ball in set:
if ball.number > minBalls[ball.color]:
minBalls[ball.color] = ball.number
var product = 1
for color,value in minBalls:
product *= value
# echo product
sum += product
return sum
proc main() =
let input = readFile("input.txt")
let inputLines = input.splitLines
processInputs(inputLines)
echo fmt"Level1: {Level1()}"
echo fmt"Level2: {Level2()}"
main()
Run
orc is now faster
nim\aoc23\day02> hyperfine day2orc.exe day2markandsweep.exe --warmup 10
Benchmark 1: day2orc.exe
Time (mean ± σ): 245.4 ms ± 3.7 ms [User: 233.1 ms, System: 17.0
ms]
Range (min … max): 240.8 ms … 254.9 ms 11 runs
Benchmark 2: day2markandsweep.exe
Time (mean ± σ): 354.9 ms ± 6.6 ms [User: 333.1 ms, System: 22.3
ms]
Range (min … max): 348.3 ms … 365.5 ms 10 runs
Summary
'day2orc.exe' ran
1.45 ± 0.03 times faster than 'day2markandsweep.exe'
Run
My understanding is that the older version has more unnecessary loops and
unnecessary sequences, so it is the less efficient script. Is the garbage
collection working more now, and therefore orc is better? Is markandsweep
better if less garbage collection is needed?