We golfing now
This commit is contained in:
parent
5277507ede
commit
76fe8ffc07
|
@ -1,54 +1,28 @@
|
||||||
import streams, strutils, sets, sequtils, sugar, re, tables
|
import streams, strutils, sets, sequtils, sugar, re, tables
|
||||||
|
|
||||||
proc matchingHeightRange(v: string): (int, int) =
|
let validators = toTable({
|
||||||
if v.endsWith("cm"): return (150, 193)
|
"hcl": (v: string) => v.match re"^#[0-9a-f]{6}$",
|
||||||
elif v.endsWith("in"): return (59, 76)
|
"ecl": (v: string) => v.match re"^(amb|blu|brn|gry|grn|hzl|oth)$",
|
||||||
|
"pid": (v: string) => v.match re"^\d{9}$",
|
||||||
proc isBetween(x: int, r: (int, int)): bool = x >= r[0] and x <= r[1]
|
"byr": (v: string) => parseInt(v) in 1920..2002,
|
||||||
proc validBirthYear(y: int): bool = y >= 1920 and y <= 2002
|
"iyr": (v: string) => parseInt(v) in 2010..2020,
|
||||||
proc validIssuedYear(y: int): bool = y >= 2010 and y <= 2020
|
"eyr": (v: string) => parseInt(v) in 2020..2030,
|
||||||
proc validExpiryYear(y: int): bool = y >= 2020 and y <= 2030
|
"hgt": proc (v: string): bool =
|
||||||
|
let (mn, mx) = if v.endsWith("cm"): (150, 193) else: (59, 76)
|
||||||
let nonDecimal = re"[^0-9]"
|
v.match(re"^\d+(cm|in)$") and v.replace(re"[^0-9]").parseInt in mn..mx,
|
||||||
let hgt = re"\d+(cm|in)"
|
|
||||||
let hcl = re"#[0-9a-f]{6}"
|
|
||||||
let ecl = re"(amb|blu|brn|gry|grn|hzl|oth)"
|
|
||||||
let pid = re"^\d{9}$"
|
|
||||||
|
|
||||||
let validators = {
|
|
||||||
"hgt": (v: string) =>
|
|
||||||
v.match(hgt) and
|
|
||||||
v.replace(nonDecimal).parseInt().isBetween(v.matchingHeightRange),
|
|
||||||
"hcl": (v: string) => v.match hcl,
|
|
||||||
"ecl": (v: string) => v.match ecl,
|
|
||||||
"pid": (v: string) => v.match pid,
|
|
||||||
"byr": (v: string) => validBirthYear parseInt v,
|
|
||||||
"iyr": (v: string) => validIssuedYear parseInt v,
|
|
||||||
"eyr": (v: string) => validExpiryYear parseInt v,
|
|
||||||
"cid": (v: string) => true,
|
"cid": (v: string) => true,
|
||||||
}.toTable
|
})
|
||||||
|
|
||||||
proc passportTable(passport: string): Table[string, string] =
|
proc parsePassports(s: Stream): seq[Table[string, string]] =
|
||||||
passport.split(' ').filterIt(it != "").mapIt(it.split(':', 2)).mapIt((it[0], it[1])).toTable
|
s.readAll().split("\n\n").mapIt(it.replace("\n", " ").split(' ')
|
||||||
|
.filterIt(it != "").mapIt(it.split(':', 2)).mapIt((it[0], it[1])).toTable)
|
||||||
iterator asPassports(s: Stream): Table[string, string] =
|
|
||||||
var p = ""
|
|
||||||
for l in s.lines:
|
|
||||||
p &= l & " "
|
|
||||||
if l == "" or s.atEnd:
|
|
||||||
yield p.passportTable
|
|
||||||
p = ""
|
|
||||||
|
|
||||||
proc hasRequiredFields(p: Table[string, string]): bool =
|
proc hasRequiredFields(p: Table[string, string]): bool =
|
||||||
let optionalFields = ["cid"].toHashSet()
|
toSeq(validators.keys).toHashSet.difference(["cid"].toHashSet) <= toSeq(p.keys).toHashSet
|
||||||
toSeq(p.keys).toHashSet.difference(optionalFields) ==
|
|
||||||
toSeq(validators.keys).toHashSet.difference(optionalFields)
|
|
||||||
|
|
||||||
proc isValid(p: Table[string, string]): bool =
|
|
||||||
toSeq(p.pairs).mapIt(validators[it[0]](it[1])).foldl(a and b)
|
|
||||||
|
|
||||||
proc part1*(s: Stream): int =
|
proc part1*(s: Stream): int =
|
||||||
toSeq(s.asPassports).filterIt(it.hasRequiredFields).len
|
s.parsePassports.filterIt(it.hasRequiredFields).len
|
||||||
|
|
||||||
proc part2*(s: Stream): int =
|
proc part2*(s: Stream): int =
|
||||||
toSeq(s.asPassports).filterIt(it.hasRequiredFields and it.isValid).len
|
s.parsePassports.filterIt(it.hasRequiredFields and
|
||||||
|
toSeq(it.pairs).mapIt(validators[it[0]](it[1])).foldl(a and b)).len
|
||||||
|
|
Loading…
Reference in a new issue