This commit is contained in:
Daniel Flanagan 2021-12-13 14:47:22 -06:00
parent 63882ceb04
commit a9e5391187
Signed by: lytedev
GPG key ID: 5B2020A0F9921EF4
4 changed files with 72 additions and 42 deletions

View file

@ -43,17 +43,27 @@ proc doDay*[T](
testInput: T, testInput: T,
expectedPart1: int, expectedPart1: int,
expectedPart2: int): void = 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): when not defined(release):
var p1 = testInput.part1() var p1 = testInput.part1()
echo p1 echo "Day ", day, " Part 1: ", p1, " (Expected: ", expectedPart1, ")"
doAssert p1 == expectedPart1 doAssert p1 == expectedPart1
var p2 = testInput.part2() var p2 = testInput.part2()
echo p2 echo "Day ", day, " Part 2: ", p2, " (Expected: ", expectedPart2, ")"
doAssert p2 == 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 = proc reduce*[T, X](s: openArray[T], op: (X, T) -> X, init: X): X =
result = init result = init
for n in s: result = op(result, n) for n in s: result = op(result, n)

View file

@ -1,43 +1,62 @@
import ./common, std/[sequtils, algorithm, sugar, sets, strformat, strutils, tables] 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 if curNode == "end": return 1
let nv = if curNode == curNode.toUpper(): visitedNodes else: visitedNodes + [curNode].toHashSet echo visitedNodes, curNode, " (", hasVisitedSmallCaveTwice, ")"
let toVisit = (graph[curNode] - nv) var isBig = curNode == curNode.toUpper()
if toVisit.len() == 0: return 0 if not isBig and not hasVisitedSmallCaveTwice and curNode != "start":
for node in toVisit: result += visit(node, graph, nv) 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 = proc pathing(input: seq[string]): int =
var graph: Table[string, HashSet[string]] = initTable[string, HashSet[string]]() visit("start", input.toGraph, toHashSet[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]([]))
proc part2(input: seq[string]): int = proc pathing2(input: seq[string]): int =
result = 0 visit("start", input.toGraph, toHashSet[string]([]), false)
doDay 12, n => n.loadInput, pathing, part2, const smallTestInput = @[
@[ "start-A",
"fs-end", "start-b",
"he-DX", "A-c",
"fs-he", "A-b",
"start-DX", "b-d",
"pj-DX", "A-end",
"end-zg", "b-end",
"zg-sl", ]
"zg-pj", const stest = (smallTestInput, 10, 36)
"pj-he",
"RW-he", # const largeTestInput = @[
"fs-DX", # "fs-end",
"pj-RW", # "he-DX",
"zg-RW", # "fs-he",
"start-pj", # "start-DX",
"he-WI", # "pj-DX",
"zg-he", # "end-zg",
"pj-fs", # "zg-sl",
"start-RW", # "zg-pj",
], 226, 0 # "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

View file

@ -59,7 +59,8 @@ time("powerConsumption part 1"): echo input.powerConsumption()
time("lifeSupportRating part 2"): echo input.lifeSupportRating() time("lifeSupportRating part 2"): echo input.lifeSupportRating()
when not defined(release): when not defined(release):
static: let testInput = @[ static:
let testInput = @[
"00100", "00100",
"11110", "11110",
"10110", "10110",

View file

@ -1,7 +1,7 @@
import ./common, std/[strutils, sequtils, sugar] import ./common, std/[strutils, sequtils, sugar]
proc crabFuel(c: seq[int], f = (n: int) => n): int = 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), doDay(7, (n) => n.loadInputText().split(',').map(parseInt),
(n) => n.crabFuel(), (n) => n.crabFuel(),