Be concise for no reason

This commit is contained in:
Daniel Flanagan 2020-12-03 11:42:18 -06:00
parent f1f5b2f57c
commit 7419eccd05
Signed by: lytedev
GPG key ID: 5B2020A0F9921EF4
5 changed files with 33 additions and 51 deletions

View file

@ -1,29 +1,19 @@
import sets, streams, strutils, input_helpers
import sets, streams, input_helpers, sequtils, options
# Day 1
let targetSum = 2020
let day1TargetSum = 2020
proc findComplement(nums: seq[int], complement = targetSum): Option[(int, int)] =
var targets = initHashSet[int]()
for n in nums:
if targets.contains(complement - n): return some(((complement - n), n))
else: targets.incl n
proc part1*(s: Stream): int =
var targets = initHashSet[int]()
for n in asInts(s):
if targets.contains(day1TargetSum - n):
return (day1TargetSum - n) * n
else:
targets.incl n
let (n1, n2) = findComplement(toSeq(asInts(s))).get; n1 * n2
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
# a shared proc
var nums: seq[int]
for line in strm.lines():
nums.add parseInt line
proc part2*(s: Stream): int =
let nums = toSeq(asInts(s))
for n in nums:
var iset = initHashSet[int]()
let nTargetSum = day1TargetSum - n
for n2 in nums:
if iset.contains(nTargetSum - n2):
return n * n2 * (nTargetSum - n2)
iset.incl n2
let comp = findComplement(nums, targetSum - n)
if comp.isSome:
let (n1, n2) = comp.get; return n * n1 * n2

View file

@ -2,6 +2,15 @@ import streams, strutils, re
type PasswordPolicy = tuple[min: int, max: int, keyChar: char]
let parsePasswordLineRe = re"^(\d+)-(\d+) (.): (.*)$"
proc parsePasswordLine(str: string): (PasswordPolicy, string) =
var matches: array[4, string]
if match(str, parsePasswordLineRe, 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 parsePasswordLine line
proc isValidPassword(str: string, pp: PasswordPolicy): bool =
let count = str.count pp.keyChar
(pp.min <= count) and (count <= pp.max)
@ -9,22 +18,10 @@ proc isValidPassword(str: string, pp: PasswordPolicy): bool =
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 =
for (pp, pw) in asPasswordPolicies(s):
if isValidPassword(pw, pp):
result += 1
for (pp, pw) in s.asPasswordPolicies:
if isValidPassword(pw, pp): inc result
proc part2*(s: Stream): int =
for (pp, pw) in asPasswordPolicies(s):
if isValidPasswordPart2(pw, pp):
result += 1
for (pp, pw) in s.asPasswordPolicies:
if isValidPasswordPart2(pw, pp): inc result

View file

@ -3,15 +3,12 @@ import streams
proc sled(s: Stream, velx: int, vely: int): int =
var xpos, ypos: int
for line in s.lines():
ypos += 1
if (ypos - 1) mod vely > 0:
continue
if line[xpos mod line.len()] == '#':
result += 1
inc ypos
if (ypos - 1) mod vely > 0: continue
if line[xpos mod line.len()] == '#': inc result
xpos += velx
proc part1*(s: Stream): int =
sled(s, 3, 1)
proc part1*(s: Stream): int = sled(s, 3, 1)
proc part2*(s: Stream): int =
result = part1(s)

View file

@ -10,7 +10,7 @@ macro loadDays(): untyped =
# TODO: do I "need" to close these streams?
solver_str = solver_str & &"""
{day}: proc(): tuple[part1: int, part2: int] =
echo "Day {day}"
stdout.write "Day {day}: "
(
{module}.part1(getInputFileStreamForDay({day})),
{module}.part2(getInputFileStreamForDay({day}))

View file

@ -1,9 +1,7 @@
import streams, strutils, sugar
iterator mapStream*[T](s: Stream, cb: (string) -> T): T =
for line in s.lines():
yield cb line
for line in s.lines(): yield cb line
iterator asInts*(s: Stream): int =
for i in mapStream[int](s, parseInt):
yield i
for i in mapStream[int](s, parseInt): yield i