From 2439761d36a8757be8c89a3420707ba68b9c8252 Mon Sep 17 00:00:00 2001 From: Daniel Flanagan Date: Thu, 3 Dec 2020 09:54:58 -0600 Subject: [PATCH] Day 2 implementation --- 2020/src/aoc2020.nim | 2 +- 2020/src/day1.nim | 13 ++++++------- 2020/src/day2.nim | 35 ++++++++++++++++++++++++++++++----- 2020/src/day3.nim | 7 +++++++ 2020/src/day_loader.nim | 12 +++++++----- 2020/src/input_helpers.nim | 9 +++++++++ 6 files changed, 60 insertions(+), 18 deletions(-) create mode 100644 2020/src/day3.nim create mode 100644 2020/src/input_helpers.nim diff --git a/2020/src/aoc2020.nim b/2020/src/aoc2020.nim index 814cd49..55a6b07 100644 --- a/2020/src/aoc2020.nim +++ b/2020/src/aoc2020.nim @@ -8,4 +8,4 @@ proc solve_for_day(n: int) {.used.} = echo solvers[n]() when isMainModule: - solve_for_day(2) + solve_all() diff --git a/2020/src/day1.nim b/2020/src/day1.nim index df28e2e..cfef733 100644 --- a/2020/src/day1.nim +++ b/2020/src/day1.nim @@ -1,19 +1,18 @@ -import sets, streams, strutils, options +import sets, streams, strutils, options, input_helpers # Day 1 let day1TargetSum = 2020 -proc part1*(strm: Stream): Option[int] = +proc part1*(s: Stream): int = var targets = initHashSet[int]() - for line in strm.lines(): - let n = parseInt line + for n in asInts(s): if targets.contains(day1TargetSum - n): - return some((day1TargetSum - n) * n) + return (day1TargetSum - n) * n else: targets.incl n -proc part2*(strm: Stream): Option[int] = +proc part2*(strm: Stream): int = # this works exactly the same as the previous algorithm, except we simply # permute once more # TODO: if I was really cool, I could split the shared functionality into @@ -26,5 +25,5 @@ proc part2*(strm: Stream): Option[int] = let nTargetSum = day1TargetSum - n for n2 in nums: if iset.contains(nTargetSum - n2): - return some(n * n2 * (nTargetSum - n2)) + return n * n2 * (nTargetSum - n2) iset.incl n2 diff --git a/2020/src/day2.nim b/2020/src/day2.nim index e003789..080c3ec 100644 --- a/2020/src/day2.nim +++ b/2020/src/day2.nim @@ -1,7 +1,32 @@ -import streams +import streams, strutils, sequtils, re, options -proc part1*(strm: Stream): string = - "ayy" +type PasswordPolicy = tuple[min: int, max: int, keyChar: char] -proc part2*(strm: Stream): string = - "ayy" +proc isValidPassword(str: string, pp: PasswordPolicy): bool = + let count = str.count pp.keyChar + (pp.min <= count) and (count <= pp.max) + +proc isValidPasswordPart2(str: string, pp: PasswordPolicy): bool = + (str[pp.min - 1] == pp.keyChar) xor (pp.keyChar == str[pp.max - 1]) + +let parsePasswordPolicyRe = re"^(\d+)-(\d+) (.): (.*)$" +proc parsePasswordPolicy(str: string): (PasswordPolicy, string) = + var matches: array[4, string] + if match(str, parsePasswordPolicyRe, matches): + return ((min: parseInt(matches[0]), max: parseInt(matches[1]), keyChar: matches[2][0]), matches[3]) + +iterator asPasswordPolicies(s: Stream): (PasswordPolicy, string) = + for line in s.lines(): + yield parsePasswordPolicy line + +proc part1*(s: Stream): int = + result = 0 + for (pp, pw) in asPasswordPolicies(s): + if isValidPassword(pw, pp): + result += 1 + +proc part2*(s: Stream): int = + result = 0 + for (pp, pw) in asPasswordPolicies(s): + if isValidPasswordPart2(pw, pp): + result += 1 diff --git a/2020/src/day3.nim b/2020/src/day3.nim new file mode 100644 index 0000000..7a4ee8f --- /dev/null +++ b/2020/src/day3.nim @@ -0,0 +1,7 @@ +import streams + +proc part1*(s: Stream): int = + 0 + +proc part2*(s: Stream): int = + 0 diff --git a/2020/src/day_loader.nim b/2020/src/day_loader.nim index 6414b48..93c0b20 100644 --- a/2020/src/day_loader.nim +++ b/2020/src/day_loader.nim @@ -3,15 +3,17 @@ import input_requestor, os, macros, strformat, tables macro loadDays(): untyped = var solver_str = "var solvers = {\n" result = newStmtList() - for day in 1..2: + for day in 1..3: let module = fmt"day{day}" if fileExists joinPath("src/", &"{module}.nim"): result.add parseStmt fmt"from {module} import nil" solver_str = solver_str & &""" - {day}: proc(): (string, string) = ( - $(day{day}.part1(getInputFileStreamForDay({day}))), - $(day{day}.part2(getInputFileStreamForDay({day}))) - ), + {day}: proc(): tuple[part1: int, part2: int] = + echo "Day {day}" + ( + {module}.part1(getInputFileStreamForDay({day})), + {module}.part2(getInputFileStreamForDay({day})) + ), """ result.add parseStmt (solver_str & "\n}.newTable()\nexport solvers") diff --git a/2020/src/input_helpers.nim b/2020/src/input_helpers.nim new file mode 100644 index 0000000..41d6511 --- /dev/null +++ b/2020/src/input_helpers.nim @@ -0,0 +1,9 @@ +import streams, strutils, sugar + +iterator mapStream*[T](s: Stream, cb: (string) -> T): T = + for line in s.lines(): + yield cb line + +iterator asInts*(s: Stream): int = + for i in mapStream[int](s, parseInt): + yield i