diff --git a/2021/nim/common.nim b/2021/nim/common.nim index ee61017..d93439c 100644 --- a/2021/nim/common.nim +++ b/2021/nim/common.nim @@ -43,17 +43,27 @@ proc doDay*[T]( testInput: T, expectedPart1: int, expectedPart2: int): void = - time(&"day {day} part 1"): echo day.inputLoader().part1() - time(&"day {day} part 2"): echo day.inputLoader().part2() when not defined(release): var p1 = testInput.part1() - echo p1 + echo "Day ", day, " Part 1: ", p1, " (Expected: ", expectedPart1, ")" doAssert p1 == expectedPart1 var p2 = testInput.part2() - echo p2 + 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]( + day: int, + inputLoader: int -> T, + part1: T -> int, + part2: T -> int, + testTuple: (T, int, int)): void = + let (tin, expectedPart1, expectedPart2) = testTuple + doDay(day, inputLoader, part1, part2, tin, expectedPart1, expectedPart2) + proc reduce*[T, X](s: openArray[T], op: (X, T) -> X, init: X): X = result = init for n in s: result = op(result, n) diff --git a/2021/nim/day12.nim b/2021/nim/day12.nim index e22b5df..161e02b 100644 --- a/2021/nim/day12.nim +++ b/2021/nim/day12.nim @@ -1,43 +1,62 @@ import ./common, std/[sequtils, algorithm, sugar, sets, strformat, strutils, tables] -proc visit(curNode: string, graph: Table[string, HashSet[string]], visitedNodes: HashSet[string]): int = +proc toGraph(lines: seq[string]): Table[string, HashSet[string]] = + result = initTable[string, HashSet[string]]() + for l in lines: + let nodes = l.split("-") + if result.hasKey(nodes[0]): result[nodes[0]].incl(nodes[1]) + else: result[nodes[0]] = toHashSet([nodes[1]]) + if result.hasKey(nodes[1]): result[nodes[1]].incl(nodes[0]) + else: result[nodes[1]] = toHashSet([nodes[0]]) + +proc visit(curNode: string, graph: Table[string, HashSet[string]], visitedNodes: HashSet[string], hasVisitedSmallCaveTwice = true): int = if curNode == "end": return 1 - let nv = if curNode == curNode.toUpper(): visitedNodes else: visitedNodes + [curNode].toHashSet - let toVisit = (graph[curNode] - nv) - if toVisit.len() == 0: return 0 - for node in toVisit: result += visit(node, graph, nv) + echo visitedNodes, curNode, " (", hasVisitedSmallCaveTwice, ")" + var isBig = curNode == curNode.toUpper() + if not isBig and not hasVisitedSmallCaveTwice and curNode != "start": + for node in (graph[curNode] - visitedNodes): result += visit(node, graph, visitedNodes, true) + var newVisitedNodes = visitedNodes + if not isBig: newVisitedNodes.incl(curNode) + for node in (graph[curNode] - visitedNodes): result += visit(node, graph, newVisitedNodes, hasVisitedSmallCaveTwice) proc pathing(input: seq[string]): int = - var graph: Table[string, HashSet[string]] = initTable[string, HashSet[string]]() - for l in input: - let nodes = l.split("-") - if graph.hasKey(nodes[0]): graph[nodes[0]].incl(nodes[1]) - else: graph[nodes[0]] = toHashSet([nodes[1]]) - if graph.hasKey(nodes[1]): graph[nodes[1]].incl(nodes[0]) - else: graph[nodes[1]] = toHashSet([nodes[0]]) - visit("start", graph, toHashSet[string]([])) + visit("start", input.toGraph, toHashSet[string]([])) -proc part2(input: seq[string]): int = - result = 0 +proc pathing2(input: seq[string]): int = + visit("start", input.toGraph, toHashSet[string]([]), false) -doDay 12, n => n.loadInput, pathing, part2, - @[ - "fs-end", - "he-DX", - "fs-he", - "start-DX", - "pj-DX", - "end-zg", - "zg-sl", - "zg-pj", - "pj-he", - "RW-he", - "fs-DX", - "pj-RW", - "zg-RW", - "start-pj", - "he-WI", - "zg-he", - "pj-fs", - "start-RW", - ], 226, 0 +const smallTestInput = @[ + "start-A", + "start-b", + "A-c", + "A-b", + "b-d", + "A-end", + "b-end", +] +const stest = (smallTestInput, 10, 36) + +# const largeTestInput = @[ +# "fs-end", +# "he-DX", +# "fs-he", +# "start-DX", +# "pj-DX", +# "end-zg", +# "zg-sl", +# "zg-pj", +# "pj-he", +# "RW-he", +# "fs-DX", +# "pj-RW", +# "zg-RW", +# "start-pj", +# "he-WI", +# "zg-he", +# "pj-fs", +# "start-RW", +# ] +# +# const ltest = (largeTestInput, 225, 3509) + +doDay 12, n => n.loadInput, pathing, pathing2, stest diff --git a/2021/nim/day3.nim b/2021/nim/day3.nim index 99b819d..5c77b5c 100644 --- a/2021/nim/day3.nim +++ b/2021/nim/day3.nim @@ -59,7 +59,8 @@ time("powerConsumption part 1"): echo input.powerConsumption() time("lifeSupportRating part 2"): echo input.lifeSupportRating() when not defined(release): - static: let testInput = @[ + static: + let testInput = @[ "00100", "11110", "10110", diff --git a/2021/nim/day7.nim b/2021/nim/day7.nim index 9e37295..f6e8038 100644 --- a/2021/nim/day7.nim +++ b/2021/nim/day7.nim @@ -1,7 +1,7 @@ import ./common, std/[strutils, sequtils, sugar] proc crabFuel(c: seq[int], f = (n: int) => n): int = - toSeq((1..c.foldl(max(a, b)))).reduce((r,t) => min(c.foldl(a + f(abs(b - t)), 0), r), high(int)) + toSeq((1..c.foldl(max(a, b)))).reduce((r: int, t) => min(c.foldl(a + f(abs(b - t)), 0), r), high(int)) doDay(7, (n) => n.loadInputText().split(',').map(parseInt), (n) => n.crabFuel(),