diff --git a/2021/nim/common.nim b/2021/nim/common.nim index d93439c..3940de3 100644 --- a/2021/nim/common.nim +++ b/2021/nim/common.nim @@ -1,5 +1,8 @@ import std/[streams, sequtils, strutils, sugar, strformat, times, httpclient, os, options] +type + Lines* = seq[string] + const YEAR = getEnv("AOC_YEAR", "2021").parseInt() proc getCookie(): string = "~/.advent-of-code-auth-cookie".expandTilde().readFile() proc getCacheDir(): string = joinPath(expandTilde("~/.cache"), fmt"/aoc{YEAR}") @@ -22,7 +25,7 @@ proc toInts*(s: seq[string]): seq[int] = s.map(parseInt) proc loadInputText*(day: int): string = day.inputFilePath().readFile().strip() -proc loadInput*(day: int): seq[string] = +proc loadInput*(day: int): Lines = result = collect: for l in day.inputStream().lines(): l @@ -48,11 +51,14 @@ proc doDay*[T]( var p1 = testInput.part1() echo "Day ", day, " Part 1: ", p1, " (Expected: ", expectedPart1, ")" doAssert p1 == expectedPart1 + + time(&"Day {day} Part 1"): echo day.inputLoader().part1() + + when not defined(release): var p2 = testInput.part2() echo "Day ", day, " Part 2: ", p2, " (Expected: ", expectedPart2, ")" doAssert p2 == expectedPart2 - time(&"Day {day} Part 1"): echo day.inputLoader().part1() time(&"Day {day} Part 2"): echo day.inputLoader().part2() proc doDay*[T]( diff --git a/2021/nim/day13.nim b/2021/nim/day13.nim new file mode 100644 index 0000000..12b3754 --- /dev/null +++ b/2021/nim/day13.nim @@ -0,0 +1,69 @@ +import ./common, std/[sequtils, algorithm, sugar, sets, strformat, strutils, tables] + +type + Axis = enum X, Y + Points = HashSet[(int, int)] + Fold = (Axis, int) + Folds = seq[Fold] + +proc parse(input: Lines): (Points, Folds) = + var parsingFolds = false + for l in input.mapIt it.strip: + if l == "": parsingFolds = true; continue + if not parsingFolds: + let coords = l.split(',').map parseInt + result[0].incl (coords[0], coords[1]) + else: + result[1].add ((if l.contains 'x': X else: Y), l.split('=')[1].parseInt) + +proc printPoints(points: Points): void = + var w, h = 0 + for (x, y) in points: + w = max(w, x) + h = max(h, y) + var lines: Lines = @[] + for y in 0..h: lines.add(' '.repeat(w+1)) + for (x, y) in points: lines[y][x] = '#' + for l in lines: echo l + +proc doFold(points: Points, f: Fold): Points = + let (axis, n) = f + for (x, y) in points: + if (axis == X and x > n): result.incl((n - (x - n), y)) + elif (axis == Y and y > n): + result.incl((x, n - (y - n))) + else: result.incl((x, y)) + +proc p1(input: Lines): int = + let (points, folds) = input.parse() + points.doFold(folds[0]).len() + +proc p2(input: Lines): int = + let (points, folds) = input.parse() + folds.reduce((points: Points, fold) => points.doFold(fold), points).printPoints() + echo "You'll have to read this one on your own, captain." + +const input = @[ + "6,10", + "0,14", + "9,10", + "0,3", + "10,4", + "4,11", + "6,0", + "6,12", + "4,1", + "0,13", + "10,12", + "3,4", + "3,0", + "8,4", + "1,10", + "2,14", + "8,10", + "9,0", + "", + "fold along y=7", + "fold along x=5", +] +doDay 13, n => n.loadInput, p1, p2, (input, 17, 0)