diff --git a/2021/common.nim b/2021/common.nim index 510053a..052f581 100644 --- a/2021/common.nim +++ b/2021/common.nim @@ -1,4 +1,4 @@ -import std/[streams, sequtils, strutils, sugar, strformat, times, httpclient, os] +import std/[streams, sequtils, strutils, sugar, strformat, times, httpclient, os, options] const YEAR = getEnv("AOC_YEAR", "2021").parseInt() proc getCookie(): string = "~/.advent-of-code-auth-cookie".expandTilde().readFile() @@ -35,3 +35,19 @@ template time*(i: string, body: untyped): untyped = when not defined(release): echo "NOTE: This is not a real measurement of performance. Compile in release mode with -d:release for best performance." # jkp: {(stop - start) * 1000} ms to calculate solution: {result}" + +proc doDay*[T]( + day: int, + inputLoader: int -> T, + part1: T -> int, + part2: T -> int, + testInput: T, + expectedPart1: int, + expectedPart2: int): void = + let input = day.inputLoader() + time(&"day {day} part 1"): echo input.part1() + time(&"day {day} part 2"): echo input.part2() + + when not defined(release): + doAssert testInput.part1() == expectedPart1 + doAssert testInput.part2() == expectedPart2 diff --git a/2021/seven.nim b/2021/seven.nim index cb11319..1b27b0e 100644 --- a/2021/seven.nim +++ b/2021/seven.nim @@ -1,33 +1,18 @@ -import std/[strutils, sequtils, tables, strformat] +import std/[strutils, sequtils, strformat] import ./common -proc crabsDistance(input: string): int = +proc crabFuel(input: string): int = + let crabs = input.split(',').map(parseInt) result = int.high() - var max_try = 0 - let dists = input.split(',').map(parseInt) - for d in dists: - if d > max_try: max_try = d - for t in 0..max_try: - let fuel = dists.foldl(a + abs(b - t), 0) - if fuel < result: result = fuel + var maxCrab = crabs.foldl(max(a, b), 0) + for t in 0..maxCrab: result = min(crabs.foldl(a + abs(b - t), 0), result) -proc f(n: int): int = toSeq(0..abs(n)).foldl(a + b, 0) +proc triangleNumber(n: int): int = int((n * (n + 1)) / 2) -proc crabsBigDistance(input: string): int = +proc crabMoreFuel(input: string): int = + let crabs = input.split(',').map(parseInt) result = int.high() - var max_try = 0 - let dists = input.split(',').map(parseInt) - for d in dists: - if d > max_try: max_try = d - for t in 0..max_try: - let fuel = dists.foldl(a + f(b - t), 0) - if fuel < result: result = fuel + var maxCrab = crabs.foldl(max(a, b), 0) + for t in 0..maxCrab: result = min(crabs.foldl(a + (b - t).abs().triangleNumber(), 0), result) -let input = 7.loadInputText() -time("day 7 part 1"): echo input.crabsDistance() -time("day 7 part 2"): echo input.crabsBigDistance() - -when not defined(release): - let testInput = "16,1,2,0,4,2,7,1,2,14" - doAssert testInput.crabsDistance() == 37 - doAssert testInput.crabsBigDistance() == 168 +doDay(7, loadInputText, crabFuel, crabMoreFuel, "16,1,2,0,4,2,7,1,2,14", 37, 168)