Paste: AOC day 4

Author: chunes
Mode: factor
Date: Fri, 4 Dec 2020 15:09:03
Plain Text |
USING: continuations io.encodings.ascii io.files kernel literals
math.order math.parser multiline peg.ebnf prettyprint qw regexp
sequences sets splitting ;
IN: aoc.2020.04

CONSTANT: input
    $[ "resource:work/aoc/2020/04/input.txt" ascii file-contents ]

CONSTANT: required qw{ byr iyr eyr hgt hcl ecl pid }

! Change that monstrosity of an input file to something like
! { { "byr:2014" "pid:120312" ... } { "cid:79" ... } },
! with a sequence of fields for each passport.
: normalize ( seq -- newseq )
    R/ \n\n/ re-split
    [ "\n" split " " join " " split harvest ] map ;

! Filter for passports with all required fields.
: passports ( seq -- newseq )
    [ [ 3 head ] map required swap subset? ] filter ;

: part1 ( -- ) input normalize passports length . ;


! ======= PART 2, aka parsing is fun =======

EBNF: field [=[

  num = [0-9]+ => [[ string>number ]]
  cm  = num ?[ 150 193 between? ]? "cm"
  in  = num ?[ 59 76 between? ]? "in"

  byr = "byr" ":"~ num ?[ 1920 2002 between? ]?
  iyr = "iyr" ":"~ num ?[ 2010 2020 between? ]?
  eyr = "eyr" ":"~ num ?[ 2020 2030 between? ]?
  hgt = "hgt" ":"~ (cm|in)
  hcl = "hcl" ":"~ "#"~ [0-9a-f]+ ?[ length 6 = ]?
  ecl = "ecl" ":"~ ("amb"|"blu"|"brn"|"gry"|"grn"|"hzl"|"oth")
  pid = "pid" ":"~ [0-9]+ ?[ length 9 = ]?
  cid = "cid" ":"~ num

  field = (byr|iyr|eyr|hgt|hcl|ecl|pid|cid)

]=]

: part2 ( -- )
    input normalize passports
    [ [ [ field ] map drop t ] [ 2drop f ] recover ] count . ;

New Annotation

Summary:
Author:
Mode:
Body: