advent/2020/day04.nim

121 lines
2.9 KiB
Nim

import std/[options, strutils]
import lib/loader
type Passport = object
byr, iyr, eyr, hgt, hcl, ecl, pid, cid: Option[string]
proc addField(p: var Passport, field: string) =
let kv = field.split(':')
case kv[0]
of "byr": p.byr = some(kv[1])
of "iyr": p.iyr = some(kv[1])
of "eyr": p.eyr = some(kv[1])
of "hgt": p.hgt = some(kv[1])
of "hcl": p.hcl = some(kv[1])
of "ecl": p.ecl = some(kv[1])
of "pid": p.pid = some(kv[1])
of "cid": p.cid = some(kv[1])
else: discard
var data = @[Passport()] # start with one empty passport
for line in loadStrings(4):
let pairs = line.splitWhitespace()
if pairs.len == 0:
data.add(Passport())
else:
for pair in pairs:
data[^1].addField(pair)
proc partOne(data: seq[Passport]): int =
for p in data:
if (
p.byr.isSome() and
p.iyr.isSome() and
p.eyr.isSome() and
p.hgt.isSome() and
p.hcl.isSome() and
p.ecl.isSome() and
p.pid.isSome()
):
inc result
func validateYr(year: string; min, max: int): bool =
if year.len != 4:
return false
try:
let n = parseInt(year)
result = (n >= min and n <= max)
except ValueError:
result = false
func validateHgt(hgt: string): bool =
if hgt.len < 3: # need both value and unit
return false
let value = try:
parseInt(hgt[0 .. ^3])
except ValueError:
return false
let unit = hgt[^2 .. ^1]
if unit == "in":
return value >= 59 and value <= 76
elif unit == "cm":
return value >= 150 and value <= 193
else:
return false
func validateHcl(hcl: string): bool =
if hcl.len != 7 or hcl[0] != '#':
return false
for c in hcl[2 .. ^1]:
if c notin {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
}:
return false
return true
func validateEcl(ecl: string): bool =
case ecl:
of "amb", "blu", "brn", "gry", "grn", "hzl", "oth":
return true
else:
return false
func validatePid(pid: string): bool =
if pid.len != 9:
return false
for c in pid:
if c notin {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}:
return false
return true
proc partTwo(data: seq[Passport]): int =
for p in data:
if (
validateYr(p.byr.get(""), 1920, 2002) and
validateYr(p.iyr.get(""), 2010, 2020) and
validateYr(p.eyr.get(""), 2020, 2030) and
validateHgt(p.hgt.get("")) and
validateHcl(p.hcl.get("")) and
validateEcl(p.ecl.get("")) and
validatePid(p.pid.get(""))
):
inc result
when isMainModule:
echo "One: ", partOne(data)
echo "Two: ", partTwo(data)