More cleanup, stick precompiled regexes in a table

This commit is contained in:
Daniel Flanagan 2020-12-04 11:02:05 -06:00
parent 541279fa25
commit e6683932e8
Signed by: lytedev
GPG key ID: 5B2020A0F9921EF4
3 changed files with 20 additions and 20 deletions

View file

@ -8,5 +8,5 @@ proc solve_for_day(n: int) {.used.} =
echo solvers[n]()
when isMainModule:
# solve_all()
solve_for_day(4)
solve_all()
# solve_for_day(4)

View file

@ -1,4 +1,4 @@
import streams, strutils, re
import streams, strutils, re, sequtils
type PasswordPolicy = tuple[min: int, max: int, keyChar: char]
@ -8,20 +8,12 @@ proc parsePasswordLine(str: string): (PasswordPolicy, 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)
proc isValidPasswordPart2(str: string, pp: PasswordPolicy): bool =
(str[pp.min - 1] == pp.keyChar) xor (pp.keyChar == str[pp.max - 1])
proc asPasswordPolicies(s: Stream): seq[(PasswordPolicy, string)] =
toSeq(s.lines()).mapIt(it.parsePasswordLine)
proc part1*(s: Stream): int =
for (pp, pw) in s.asPasswordPolicies:
if isValidPassword(pw, pp): inc result
s.asPasswordPolicies.countIt(it[1].count(it[0].keyChar) in it[0].min..it[0].max)
proc part2*(s: Stream): int =
for (pp, pw) in s.asPasswordPolicies:
if isValidPasswordPart2(pw, pp): inc result
s.asPasswordPolicies.countIt(
(it[1][it[0].min - 1] == it[0].keyChar) xor (it[0].keyChar == it[1][it[0].max - 1]))

View file

@ -1,15 +1,23 @@
import streams, strutils, sets, sequtils, sugar, re, tables
let regexes = toTable({
"hcl": re"^#[0-9a-f]{6}$",
"ecl": re"^(amb|blu|brn|gry|grn|hzl|oth)$",
"pid": re"^\d{9}$",
"hgt": re"^\d+(cm|in)$",
"nondec": re"[^0-9]",
})
let validators = toTable({
"hcl": (v: string) => v.match re"^#[0-9a-f]{6}$",
"ecl": (v: string) => v.match re"^(amb|blu|brn|gry|grn|hzl|oth)$",
"pid": (v: string) => v.match re"^\d{9}$",
"hcl": (v: string) => v.match regexes["hcl"],
"ecl": (v: string) => v.match regexes["ecl"],
"pid": (v: string) => v.match regexes["pid"],
"byr": (v: string) => parseInt(v) in 1920..2002,
"iyr": (v: string) => parseInt(v) in 2010..2020,
"eyr": (v: string) => parseInt(v) in 2020..2030,
"hgt": proc (v: string): bool =
let (mn, mx) = if v.endsWith("cm"): (150, 193) else: (59, 76)
v.match(re"^\d+(cm|in)$") and v.replace(re"[^0-9]").parseInt in mn..mx,
v.match(regexes["hgt"]) and v.replace(regexes["nondec"]).parseInt in mn..mx,
"cid": (v: string) => true,
})