Be concise for no reason
This commit is contained in:
parent
f1f5b2f57c
commit
7419eccd05
|
@ -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 =
|
proc part1*(s: Stream): int =
|
||||||
var targets = initHashSet[int]()
|
let (n1, n2) = findComplement(toSeq(asInts(s))).get; n1 * n2
|
||||||
for n in asInts(s):
|
|
||||||
if targets.contains(day1TargetSum - n):
|
|
||||||
return (day1TargetSum - n) * n
|
|
||||||
else:
|
|
||||||
targets.incl n
|
|
||||||
|
|
||||||
proc part2*(strm: Stream): int =
|
proc part2*(s: Stream): int =
|
||||||
# this works exactly the same as the previous algorithm, except we simply
|
let nums = toSeq(asInts(s))
|
||||||
# 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
|
|
||||||
for n in nums:
|
for n in nums:
|
||||||
var iset = initHashSet[int]()
|
let comp = findComplement(nums, targetSum - n)
|
||||||
let nTargetSum = day1TargetSum - n
|
if comp.isSome:
|
||||||
for n2 in nums:
|
let (n1, n2) = comp.get; return n * n1 * n2
|
||||||
if iset.contains(nTargetSum - n2):
|
|
||||||
return n * n2 * (nTargetSum - n2)
|
|
||||||
iset.incl n2
|
|
||||||
|
|
|
@ -2,6 +2,15 @@ import streams, strutils, re
|
||||||
|
|
||||||
type PasswordPolicy = tuple[min: int, max: int, keyChar: char]
|
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 =
|
proc isValidPassword(str: string, pp: PasswordPolicy): bool =
|
||||||
let count = str.count pp.keyChar
|
let count = str.count pp.keyChar
|
||||||
(pp.min <= count) and (count <= pp.max)
|
(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 =
|
proc isValidPasswordPart2(str: string, pp: PasswordPolicy): bool =
|
||||||
(str[pp.min - 1] == pp.keyChar) xor (pp.keyChar == str[pp.max - 1])
|
(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 =
|
proc part1*(s: Stream): int =
|
||||||
for (pp, pw) in asPasswordPolicies(s):
|
for (pp, pw) in s.asPasswordPolicies:
|
||||||
if isValidPassword(pw, pp):
|
if isValidPassword(pw, pp): inc result
|
||||||
result += 1
|
|
||||||
|
|
||||||
proc part2*(s: Stream): int =
|
proc part2*(s: Stream): int =
|
||||||
for (pp, pw) in asPasswordPolicies(s):
|
for (pp, pw) in s.asPasswordPolicies:
|
||||||
if isValidPasswordPart2(pw, pp):
|
if isValidPasswordPart2(pw, pp): inc result
|
||||||
result += 1
|
|
||||||
|
|
|
@ -3,15 +3,12 @@ import streams
|
||||||
proc sled(s: Stream, velx: int, vely: int): int =
|
proc sled(s: Stream, velx: int, vely: int): int =
|
||||||
var xpos, ypos: int
|
var xpos, ypos: int
|
||||||
for line in s.lines():
|
for line in s.lines():
|
||||||
ypos += 1
|
inc ypos
|
||||||
if (ypos - 1) mod vely > 0:
|
if (ypos - 1) mod vely > 0: continue
|
||||||
continue
|
if line[xpos mod line.len()] == '#': inc result
|
||||||
if line[xpos mod line.len()] == '#':
|
|
||||||
result += 1
|
|
||||||
xpos += velx
|
xpos += velx
|
||||||
|
|
||||||
proc part1*(s: Stream): int =
|
proc part1*(s: Stream): int = sled(s, 3, 1)
|
||||||
sled(s, 3, 1)
|
|
||||||
|
|
||||||
proc part2*(s: Stream): int =
|
proc part2*(s: Stream): int =
|
||||||
result = part1(s)
|
result = part1(s)
|
||||||
|
|
|
@ -10,7 +10,7 @@ macro loadDays(): untyped =
|
||||||
# TODO: do I "need" to close these streams?
|
# TODO: do I "need" to close these streams?
|
||||||
solver_str = solver_str & &"""
|
solver_str = solver_str & &"""
|
||||||
{day}: proc(): tuple[part1: int, part2: int] =
|
{day}: proc(): tuple[part1: int, part2: int] =
|
||||||
echo "Day {day}"
|
stdout.write "Day {day}: "
|
||||||
(
|
(
|
||||||
{module}.part1(getInputFileStreamForDay({day})),
|
{module}.part1(getInputFileStreamForDay({day})),
|
||||||
{module}.part2(getInputFileStreamForDay({day}))
|
{module}.part2(getInputFileStreamForDay({day}))
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
import streams, strutils, sugar
|
import streams, strutils, sugar
|
||||||
|
|
||||||
iterator mapStream*[T](s: Stream, cb: (string) -> T): T =
|
iterator mapStream*[T](s: Stream, cb: (string) -> T): T =
|
||||||
for line in s.lines():
|
for line in s.lines(): yield cb line
|
||||||
yield cb line
|
|
||||||
|
|
||||||
iterator asInts*(s: Stream): int =
|
iterator asInts*(s: Stream): int =
|
||||||
for i in mapStream[int](s, parseInt):
|
for i in mapStream[int](s, parseInt): yield i
|
||||||
yield i
|
|
||||||
|
|
Loading…
Reference in a new issue