Done day 4
authorNeil Smith <neil.git@njae.me.uk>
Wed, 9 Dec 2020 15:34:22 +0000 (15:34 +0000)
committerNeil Smith <neil.git@njae.me.uk>
Wed, 9 Dec 2020 15:34:22 +0000 (15:34 +0000)
advent04/package.yaml [new file with mode: 0644]
advent04/src/advent04.hs [new file with mode: 0644]
data/advent04.txt [new file with mode: 0644]
data/advent04a.txt [new file with mode: 0644]
problems/day4.html [new file with mode: 0644]
stack.yaml

diff --git a/advent04/package.yaml b/advent04/package.yaml
new file mode 100644 (file)
index 0000000..60d0bca
--- /dev/null
@@ -0,0 +1,61 @@
+# This YAML file describes your package. Stack will automatically generate a
+# Cabal file when you run `stack build`. See the hpack website for help with
+# this file: <https://github.com/sol/hpack>.
+
+name: advent04
+synopsis: Advent of Code
+version: '0.0.1'
+
+default-extensions:
+- AllowAmbiguousTypes
+- ApplicativeDo
+- BangPatterns
+- BlockArguments
+- DataKinds
+- DeriveFoldable
+- DeriveFunctor
+- DeriveGeneric
+- DeriveTraversable
+- EmptyCase
+- FlexibleContexts
+- FlexibleInstances
+- FunctionalDependencies
+- GADTs
+- GeneralizedNewtypeDeriving
+- ImplicitParams
+- KindSignatures
+- LambdaCase
+- MonadComprehensions
+- MonoLocalBinds
+- MultiParamTypeClasses
+- MultiWayIf
+- NamedFieldPuns
+- NegativeLiterals
+- NumDecimals
+# - OverloadedLists
+- OverloadedStrings
+- PartialTypeSignatures
+- PatternGuards
+- PatternSynonyms
+- PolyKinds
+- RankNTypes
+- RecordWildCards
+- ScopedTypeVariables
+- TemplateHaskell
+- TransformListComp
+- TupleSections
+- TypeApplications
+- TypeFamilies
+- TypeInType
+- TypeOperators
+- ViewPatterns
+
+executables:
+  advent04:
+    main: advent04.hs
+    source-dirs: src
+    dependencies:
+    - base >= 2 && < 6
+    - text
+    - megaparsec
+    - containers
\ No newline at end of file
diff --git a/advent04/src/advent04.hs b/advent04/src/advent04.hs
new file mode 100644 (file)
index 0000000..1960f86
--- /dev/null
@@ -0,0 +1,134 @@
+-- import Debug.Trace
+
+import Data.Text (Text)
+import qualified Data.Text as T
+import qualified Data.Text.IO as TIO
+
+import Data.Void (Void)
+
+import Text.Megaparsec hiding (State)
+import Text.Megaparsec.Char
+import qualified Text.Megaparsec.Char.Lexer as L
+import qualified Control.Applicative as CA
+
+import qualified Data.Map.Strict as M
+import qualified Data.Set as S
+import Data.Char
+import Data.List
+
+-- import Text.Megaparsec.Debug
+
+type Passport = M.Map String String
+
+requiredFields = S.fromList ["byr", "iyr", "eyr", "hgt", "hcl", 
+    "ecl", "pid"]
+expectedFields = S.union requiredFields $ S.singleton "cid"
+
+
+main :: IO ()
+main = 
+  do  text <- TIO.readFile "data/advent04.txt"
+      let passports = successfulParse text
+      -- print $ length passports
+      putStrLn $ runTests
+      print $ part1 passports
+      print $ part2 passports
+
+part1 = length . filter hasRequiredFields 
+part2 = length . filter validPassport
+
+hasRequiredFields passport = S.null $ requiredFields `S.difference` (M.keysSet passport)
+
+validPassport :: Passport -> Bool
+validPassport passport = (hasRequiredFields passport) && (all validField $ M.assocs passport)
+
+validField :: (String, String) -> Bool
+validField (key, value) =
+  case key of
+    "byr" -> validRanged 1920 2002 value
+    "iyr" -> validRanged 2010 2020 value
+    "eyr" -> validRanged 2020 2030 value
+    "hgt" -> validHeight value
+    "hcl" -> validHex value
+    "ecl" -> validEye value
+    "pid" -> validPid value
+    "cid" -> True
+    _ -> False
+
+validRanged lower upper value = 
+  if all isDigit value
+  then v >= lower && v <= upper
+  else False
+  where v = read @Int value 
+
+validHeight value = 
+  if "cm" `isSuffixOf` value
+  then validRanged 150 193 v
+  else if "in" `isSuffixOf` value
+       then validRanged 59 76 v
+       else False
+  where v = reverse $ drop 2 $ reverse value
+
+validHex value = (length value == 7) && (head value == '#') && (all isHexDigit $ tail value)
+
+validEye value = value `S.member` eyeColours
+eyeColours = S.fromList ["amb", "blu", "brn", "gry", "grn", "hzl", "oth"]
+
+validPid value = (length value == 9) && (all isDigit value)
+
+runTests :: String -- [(Text, Bool)]
+runTests = if null failures
+           then "All tests passed"
+           else show failures
+  where failures = filter failedTest testCases
+
+failedTest :: (Text, Bool) -> Bool
+failedTest (passportText, expected) = actual /= expected
+  where passport = parseTestCase passportText
+        actual = validPassport passport
+
+parseTestCase :: Text -> Passport
+parseTestCase input = 
+  case parse passportP "test" input of
+    Left  _err -> M.empty
+    Right p -> p
+
+testCases = 
+  [ ("eyr:1972 cid:100 hcl:#18171d ecl:amb hgt:170 pid:186cm iyr:2018 byr:1926", False)
+  , ("iyr:2019\nhcl:#602927 eyr:1967 hgt:170cm\necl:grn pid:012533040 byr:1946", False)
+  , ("hcl:dab227 iyr:2012\necl:brn hgt:182cm pid:021572410 eyr:2020 byr:1992 cid:277", False)
+  , ("hgt:59cm ecl:zzz\neyr:2038 hcl:74454a iyr:2023\npid:3556412378 byr:2007", False)
+  , ("pid:087499704 hgt:74in ecl:grn iyr:2012 eyr:2030 byr:1980\nhcl:#623a2f", True)
+  , ("eyr:2029 ecl:blu cid:129 byr:1989\niyr:2014 pid:896056539 hcl:#a97842 hgt:165cm", True)
+  , ("hcl:#888785\nhgt:164cm byr:2001 iyr:2015 cid:88\npid:545766238 ecl:hzl\neyr:2022", True)
+  , ("iyr:2010 hgt:158cm hcl:#b6652a ecl:blu byr:1944 eyr:2021 pid:093154719", True)
+  ]
+
+
+-- Parse the input file
+type Parser = Parsec Void Text
+
+sc :: Parser ()
+sc = L.space (skipSome (    char ' ' 
+                       <|> char '\t' 
+                       <|> (try (newline <* notFollowedBy newline))
+                       )
+             ) CA.empty CA.empty
+
+blankLines = skipSome newline
+
+symb = L.symbol sc
+colonP = symb ":"
+hashChar = char '#'
+stringP = some (alphaNumChar <|> hashChar) <* sc
+
+kvP = (,) <$> stringP <* colonP <*> stringP
+
+passportsP = passportP `sepBy` blankLines
+passportP = M.fromList <$> many kvP
+
+successfulParse :: Text -> [Passport]
+successfulParse input = 
+  case parse passportsP "input" input of
+    Left  _err -> [] -- TIO.putStr $ T.pack $ parseErrorPretty err
+    Right passports -> passports
diff --git a/data/advent04.txt b/data/advent04.txt
new file mode 100644 (file)
index 0000000..646dcfe
--- /dev/null
@@ -0,0 +1,1169 @@
+byr:2024 iyr:2016
+eyr:2034 ecl:zzz pid:985592671 hcl:033b48
+hgt:181 cid:166
+
+hgt:66cm
+pid:152cm
+hcl:cfb18a eyr:1947
+byr:2020 ecl:zzz iyr:2029
+
+ecl:gry hcl:#888785 eyr:2023 cid:63
+iyr:2019 hgt:177cm
+pid:656793259
+
+pid:#5e832a
+ecl:dne hcl:#7d3b0c byr:2018 eyr:1928 hgt:61cm iyr:1936 cid:241
+
+hcl:#888785 ecl:oth eyr:2025
+pid:597580472
+iyr:2017 hgt:187cm byr:1957 cid:247
+
+eyr:2029 cid:145 iyr:2026 pid:178cm hgt:162in ecl:gry
+hcl:#a5d09f byr:2002
+
+eyr:2024
+ecl:amb
+pid:349191561 iyr:2018 hgt:156cm byr:1972
+hcl:#341e13
+
+byr:1998 pid:408617933
+hcl:#fffffd hgt:193cm eyr:2021 ecl:brn iyr:2013
+
+eyr:1964 byr:2026
+hcl:#cfa07d hgt:154cm pid:175cm cid:85 iyr:2018 ecl:gmt
+
+hgt:161cm
+pid:021086946
+iyr:2020 ecl:blu eyr:2024
+byr:1921
+
+pid:173cm cid:235 eyr:1935 iyr:1952 ecl:utc byr:2015 hgt:187
+hcl:6239ed
+
+iyr:2015 hcl:#18171d pid:2691566700 ecl:gmt hgt:68cm eyr:2032 byr:2016
+cid:341
+
+hcl:#c0946f
+iyr:2010 pid:941290886 eyr:2023 ecl:brn
+hgt:190cm
+byr:1927
+
+pid:423210256 eyr:2026 iyr:2011 byr:1926 hcl:#efcc98
+ecl:grn
+hgt:185cm cid:135
+
+ecl:blu eyr:2030
+byr:1996 hgt:154cm iyr:2019 pid:809421142
+hcl:#b6652a
+cid:250
+
+hcl:39615c iyr:1934 byr:2009 pid:7752456272 hgt:191cm
+eyr:2024 ecl:#5b7a58
+
+iyr:1938 hgt:160in hcl:#623a2f eyr:2031
+ecl:grn pid:169cm byr:1964
+
+ecl:grt byr:2004 hcl:026249 hgt:176in iyr:1933 eyr:2023
+pid:176cm
+
+hgt:167cm
+pid:023312072 ecl:oth iyr:2018 hcl:#866857 eyr:2024 byr:1994
+
+hcl:#c0946f
+ecl:blu iyr:2016
+eyr:2023 hgt:193cm
+pid:190756361 byr:1943
+cid:306
+
+iyr:2013 hgt:179cm ecl:oth
+cid:290 eyr:2020 pid:953948851
+hcl:#6b5442
+byr:1973
+
+pid:795414848
+cid:51
+ecl:oth iyr:2020 hcl:#ceb3a1 eyr:2026 byr:1995 hgt:186cm
+
+iyr:2020
+byr:1993 hgt:159cm pid:905121332
+ecl:brn eyr:2023
+hcl:#341e13
+
+ecl:hzl iyr:2017 eyr:2020 hcl:z byr:2003 hgt:163
+
+eyr:2038
+cid:342 hgt:116 iyr:2019 hcl:73db63 byr:1973 ecl:gry pid:468207739
+
+pid:022772899 eyr:2040 hgt:181cm
+ecl:dne
+hcl:#866857
+byr:1931 iyr:2012
+
+pid:36127238 eyr:2038 cid:227 iyr:1985 hgt:103 byr:2004
+hcl:z ecl:#45a680
+
+hgt:183cm
+iyr:2013 byr:1933 cid:112
+eyr:2024 pid:795616425
+hcl:#7d3b0c
+ecl:gry
+
+cid:236 byr:1985 hgt:160cm
+hcl:#6b5442 eyr:2028
+ecl:gmt pid:277781460 iyr:2018
+
+ecl:amb
+byr:1948 pid:750948701 eyr:2025 iyr:2013 hgt:62in hcl:#7d3b0c
+
+eyr:2029 iyr:2020 pid:385941629 byr:1998 hgt:153cm cid:321
+hcl:#623a2f
+
+byr:1966 hgt:69in iyr:2012
+pid:423254216
+eyr:2020 hcl:#602927 ecl:blu
+
+byr:2004 pid:14257358 cid:338 iyr:2010
+ecl:gry
+hcl:#602927
+hgt:152cm
+
+ecl:gry eyr:2027 hcl:#341e13
+iyr:2018 pid:298762877 hgt:162cm byr:1968
+
+hcl:#ceb3a1
+iyr:2019 ecl:brn eyr:2020 pid:575413143 byr:2030 hgt:185cm
+cid:159
+
+eyr:2025 pid:628251539 ecl:blu byr:1953 hgt:63in hcl:#18171d iyr:2016
+
+pid:973247326 byr:1925 hcl:#341e13 ecl:grn eyr:2028 hgt:156cm
+iyr:2014
+
+byr:1957 hgt:154cm
+hcl:#7d3b0c
+pid:062760305 eyr:2023 ecl:brn
+iyr:2012
+
+ecl:brn eyr:2029
+cid:250
+pid:477431667 hgt:177cm
+byr:1993 iyr:2020 hcl:#ceb3a1
+
+pid:155471269 iyr:2010 byr:1985 hgt:169cm eyr:2026 hcl:#694b7d cid:337 ecl:gry
+
+ecl:grt hgt:152in byr:2012
+pid:#b9d022 iyr:2030
+eyr:2037 hcl:z cid:201
+
+hcl:9270b3 eyr:2028
+hgt:71cm iyr:2017 pid:#6c7af7 ecl:grn byr:1971
+
+pid:#0ab7e1 hgt:166cm byr:1929
+cid:289
+hcl:#623a2f iyr:2005
+ecl:amb
+
+pid:967754435
+hgt:175cm hcl:#341e13 ecl:utc iyr:2023 eyr:1949 byr:1988
+
+byr:1942 ecl:brn eyr:2023 pid:898126666 hgt:182cm cid:138
+hcl:#866857
+iyr:2010
+
+eyr:2027 iyr:2019 byr:1953 pid:760664328 hcl:#b6652a
+ecl:grn hgt:155cm
+
+iyr:2018
+ecl:brn hcl:#18171d pid:953129359 hgt:167cm eyr:2030 byr:1974
+
+cid:77
+pid:975070417 hcl:#b6652a ecl:amb iyr:2013 byr:1995
+eyr:2025 hgt:184cm
+
+hgt:168cm
+eyr:2026 byr:1938 ecl:gry pid:037135813 hcl:#6b5442
+iyr:2010
+
+iyr:2017 hcl:4cc74b byr:1980 hgt:176in
+pid:460622356 ecl:xry eyr:2030
+
+hcl:z
+ecl:oth pid:872514537 hgt:175in eyr:1984 iyr:2011 cid:145 byr:2024
+
+iyr:2014 ecl:blu
+pid:332729196 hgt:63in
+eyr:2020
+hcl:#602927
+
+hcl:#7d3b0c pid:369981570 byr:1996 ecl:gry
+eyr:2024 iyr:2017
+
+pid:446117373 hgt:158cm
+iyr:2010 ecl:gry eyr:2024 hcl:#e54715
+
+cid:341 pid:842156559
+hgt:167cm hcl:#602927 byr:1939 ecl:amb iyr:2016
+
+byr:2017
+cid:176
+ecl:#9e42ae iyr:2029 pid:8965345 eyr:2038 hcl:z
+hgt:116
+
+eyr:2027 iyr:2014 hcl:#ceb3a1
+cid:280 pid:871521406 ecl:oth byr:1957 hgt:166cm
+
+cid:303 iyr:2019
+eyr:2021 pid:579593282 ecl:gry hcl:011a46 byr:1981
+hgt:184cm
+
+iyr:2015 byr:1936 cid:61 ecl:brn pid:307248029 hgt:172cm hcl:#18171d eyr:2029
+
+pid:708687506 ecl:brn hcl:#602927
+iyr:2014 byr:1987
+hgt:193cm
+eyr:2021
+
+ecl:gry
+iyr:2015 hcl:#efcc98 byr:1950
+cid:150 eyr:2023 pid:569864726
+hgt:161cm
+
+byr:1920 hcl:#602927 iyr:2018
+ecl:gry eyr:2020
+hgt:192cm pid:020336420
+
+hcl:#539335 byr:1949
+hgt:152cm
+cid:95 pid:002018679
+eyr:2030 iyr:2015 ecl:brn
+
+hcl:#b6652a eyr:2023
+pid:515291463 iyr:2013 byr:1990
+ecl:blu hgt:160cm
+
+eyr:2030 iyr:2012
+ecl:grn pid:416049447 hgt:188cm
+hcl:#a97842 byr:1976
+
+iyr:2017 hgt:61in ecl:oth byr:2001 eyr:2028
+hcl:#733820
+pid:078720467
+
+eyr:2021 hgt:151cm iyr:2020
+hcl:#efcc98 ecl:oth
+byr:1985
+pid:876231883
+
+iyr:2019 hcl:#ceb3a1 hgt:156in
+eyr:2004 pid:093465895 ecl:amb byr:2026
+
+pid:103964845 hgt:178cm cid:320 ecl:oth
+hcl:#fffffd byr:2002 eyr:2021 iyr:2019
+
+ecl:brn byr:1920 pid:499363957
+cid:217 hcl:#341e13 hgt:164cm
+iyr:2017 eyr:2028
+
+ecl:brn pid:5837609946 iyr:2011
+byr:1971 eyr:2030 hgt:189cm
+hcl:#866857
+
+byr:1974 iyr:2015 hcl:#cfa07d
+hgt:190cm ecl:grn pid:330115418 eyr:2020 cid:173
+
+iyr:2010
+eyr:2024 byr:1943 pid:227557868
+cid:102 hgt:72in
+hcl:#6b5442
+
+hgt:151cm byr:1994
+pid:050723476
+cid:104 iyr:2010 hcl:#b6652a
+ecl:brn eyr:2030
+
+ecl:gry byr:1942
+hcl:#c5e354 hgt:192cm iyr:2019
+eyr:2027 pid:192177566
+
+ecl:hzl hcl:#c0946f byr:1997 pid:853199076 hgt:166cm
+iyr:2019
+eyr:2020
+cid:329
+
+eyr:2027 iyr:2029 hcl:#602927
+pid:#1b8593 byr:2028 hgt:172in ecl:grn
+
+eyr:2036 iyr:2030 ecl:utc
+pid:22330365 hcl:z byr:2016 hgt:65cm
+
+pid:936740771
+ecl:grn byr:1976
+hcl:#602927
+iyr:2017 hgt:192cm
+cid:257 eyr:2027
+
+eyr:2021 pid:415535681
+hcl:#b6652a hgt:191cm
+ecl:hzl
+iyr:2013 byr:1985
+
+hgt:193cm
+pid:499609129
+iyr:2014 ecl:oth
+eyr:2029 hcl:#cfa07d byr:1973
+
+ecl:gry byr:1996 cid:85 hgt:174cm iyr:2013 pid:444611265 hcl:#6b5442 eyr:2028
+
+pid:170343402
+iyr:2029
+hgt:167cm
+byr:2016 eyr:2034 ecl:hzl hcl:z cid:254
+
+hcl:4893d5 ecl:blu byr:1960
+eyr:2027 pid:573029479 iyr:1952 hgt:74in
+
+eyr:2021 hgt:192cm pid:729836929 iyr:2020 byr:1973
+cid:155 ecl:grn hcl:#602927
+
+hcl:#a97842 byr:1946
+iyr:2018 cid:172 hgt:162cm eyr:2030 ecl:amb pid:028768413
+
+iyr:2020 hcl:#c0946f ecl:grn pid:601040247 cid:237 hgt:177cm eyr:2024
+byr:1941
+
+iyr:2014 byr:1959
+eyr:2028
+hcl:#fffffd
+ecl:#7df42b cid:165 hgt:68cm
+
+byr:1944 hcl:#18171d
+pid:009636175 hgt:155cm ecl:amb eyr:2032 iyr:2015
+
+byr:1987 hgt:150cm
+hcl:#b6652a eyr:2021
+ecl:blu
+pid:723709387 iyr:2017
+
+byr:1937 ecl:oth eyr:2022 hcl:#733820 pid:143694811 cid:175 hgt:150cm
+
+pid:562911401
+cid:80 hgt:61in byr:1922 eyr:2027 ecl:amb iyr:2014
+hcl:#602927
+
+iyr:2013 ecl:amb pid:826291674 hcl:#ceb3a1 eyr:2021 byr:1968 hgt:75in
+
+hcl:#5e0e07
+hgt:164cm pid:572114080 eyr:2028 iyr:2016
+byr:1922 ecl:oth
+
+ecl:blu eyr:2029 hgt:155cm
+byr:1950 hcl:#866857 cid:271 iyr:2015
+pid:216813084
+
+iyr:2018 byr:2009 cid:212 ecl:#71a98c pid:3467231102 hcl:z hgt:173cm
+eyr:2026
+
+eyr:1945 cid:302 iyr:2030
+hcl:z pid:0411732179
+byr:2004 hgt:165in
+ecl:grt
+
+iyr:2010 hgt:169cm
+hcl:#ceb3a1
+eyr:2022 pid:659709686 ecl:hzl
+byr:1931
+
+hcl:z pid:5077677466
+eyr:2021 hgt:184cm
+iyr:1973
+byr:2009 ecl:#35575e
+
+hgt:190cm cid:103 iyr:2018
+byr:1970 ecl:gry
+eyr:2028
+pid:549406360 hcl:#18171d
+
+byr:1964 eyr:2023 iyr:2015 hgt:174cm pid:305268492
+hcl:#b98e00 ecl:blu
+
+hgt:162cm
+ecl:brn iyr:2019 byr:1951
+cid:169 pid:755632568 eyr:2030 hcl:#ceb3a1
+
+iyr:2010 ecl:oth hgt:192cm eyr:2025
+hcl:#efcc98 pid:003868873 byr:1925
+
+hcl:z
+ecl:gmt hgt:62 eyr:1991
+byr:2012
+iyr:2025 pid:1835041269
+
+hgt:162
+iyr:2026 byr:2024
+pid:6463124513 hcl:#602927 ecl:oth eyr:2028
+
+hcl:bfb027 iyr:1945 byr:1989 eyr:1944 pid:826897563 ecl:dne cid:117 hgt:177
+
+hcl:#b6652a iyr:2013
+ecl:blu byr:1952 eyr:2020 pid:737726601 cid:308
+hgt:167cm
+
+eyr:2028 iyr:2012 hcl:#6b5442
+byr:1986 ecl:blu
+pid:365821409 hgt:180cm
+
+hgt:101 eyr:2037 pid:2457985649
+ecl:gmt
+hcl:4c0784 iyr:2029
+
+hcl:#341e13 iyr:1954 ecl:dne byr:2007
+eyr:2028 pid:552497791 hgt:189cm cid:263
+
+ecl:blu
+hgt:71in pid:360012597 eyr:2029 hcl:#18171d byr:1949
+iyr:2014
+
+hgt:164cm cid:237 iyr:2016 byr:1966
+hcl:#623a2f ecl:oth
+pid:129809894 eyr:2027
+
+hcl:a2243b eyr:2031
+ecl:#de9183
+byr:1982 hgt:109 iyr:1968 pid:848311277
+
+eyr:1950
+hcl:45470a byr:1983
+pid:82580746 cid:321
+hgt:191cm ecl:dne iyr:2013
+
+iyr:2018 ecl:blu eyr:2021
+byr:1983 pid:045613120
+
+hgt:164cm byr:1926
+hcl:#cfa07d
+eyr:2030
+iyr:2010
+pid:360787918 cid:61 ecl:amb
+
+pid:#d6dddd iyr:1967 ecl:gmt hcl:z byr:1947 eyr:1943 cid:93 hgt:97
+
+ecl:oth hgt:172cm
+hcl:#efcc98 byr:1957
+pid:729531506 iyr:2017
+eyr:2030
+
+ecl:#5a51b9 byr:2023 eyr:2021 iyr:2027
+pid:174cm hgt:80 hcl:6b4f6e
+
+hgt:157cm
+ecl:amb
+eyr:2020 pid:994733990 iyr:2020 cid:174 byr:1966
+hcl:#7d3b0c
+
+eyr:1986
+byr:2020 hcl:#c0946f
+pid:499981246
+iyr:1926 cid:214 ecl:amb hgt:161cm
+
+hcl:#18171d byr:1971
+pid:#ef8a06
+eyr:2019 ecl:blu
+hgt:158cm iyr:2011
+
+byr:1959 cid:298 pid:876132993
+ecl:blu iyr:2011 hgt:176cm
+hcl:#6b5442 eyr:2030
+
+eyr:2030
+byr:1926 hcl:#733820 iyr:2017
+hgt:150cm pid:165cm ecl:blu
+
+byr:1991 eyr:2027
+hgt:183cm
+pid:178cm
+ecl:grn hcl:8a6142 iyr:2017
+cid:265
+
+hgt:183cm
+eyr:2027 hcl:#602927 pid:530884763 byr:1959 ecl:brn iyr:2013
+
+hcl:#b6652a eyr:2030 hgt:171cm cid:97 byr:2002 pid:166795809
+ecl:hzl
+iyr:2016
+
+pid:479944517 hgt:166cm byr:1976 eyr:2022 hcl:#a97842
+ecl:grn iyr:2018
+
+byr:1949
+eyr:2013
+hcl:z ecl:hzl
+pid:152cm hgt:139 iyr:1962
+
+pid:278193062 hcl:#c0946f iyr:2013 byr:1950 eyr:2020 hgt:167cm
+ecl:oth
+
+eyr:1955
+iyr:2018 pid:#ffd4de byr:1922 hgt:178cm hcl:z
+ecl:lzr
+cid:154
+
+ecl:grn hcl:#a189d5 byr:1977 pid:120286096
+eyr:1966
+hgt:178cm
+iyr:2011
+
+eyr:2028
+hcl:#fffffd iyr:2013 byr:1956 pid:565425333 cid:207 ecl:gry hgt:67in
+
+hgt:188cm eyr:2028 cid:90
+iyr:2019 pid:574624890 hcl:#b6652a byr:1937 ecl:oth
+
+hcl:#efcc98 hgt:152cm ecl:hzl iyr:2010 cid:217 byr:1936 eyr:2027 pid:857984889
+
+hgt:124 iyr:2015 byr:1989 ecl:oth eyr:2023 hcl:#ceb3a1 pid:917440765
+
+ecl:#61e880 cid:82
+pid:165cm byr:2019 eyr:1930 hgt:152in hcl:z iyr:2030
+
+byr:1974
+hgt:60in ecl:gry
+hcl:#c0946f
+pid:215085889
+iyr:2017 eyr:2020
+
+ecl:grn hcl:#ceb3a1
+pid:602147794 hgt:180cm eyr:2028 byr:1927 iyr:2018
+
+hcl:#ceb3a1 byr:1958 ecl:gry
+pid:210246609 iyr:2018 hgt:169cm
+eyr:2023
+cid:255
+
+eyr:2025
+byr:1950 hgt:177cm
+ecl:gry pid:547034188
+iyr:2018
+cid:218 hcl:#341e13
+
+pid:380369950
+eyr:2022 hgt:65in iyr:2019 ecl:brn
+byr:1996
+
+hgt:167cm
+iyr:2014
+eyr:2029 cid:199 pid:144048588 byr:1963 ecl:oth hcl:#733820
+
+byr:1962 ecl:brn hgt:161cm eyr:2022 hcl:#cfa07d
+pid:247699670 iyr:2016
+
+hgt:192cm ecl:#8bdb3e pid:#b152a9 hcl:#18171d iyr:2012 byr:2011 cid:335 eyr:2040
+
+hcl:11f8f4 ecl:#86f885 iyr:2022
+hgt:75in
+pid:920078124 byr:1952 eyr:1994
+
+pid:718378772 cid:282
+hcl:#fffffd hgt:166cm eyr:2023 iyr:2019 byr:1944
+ecl:grn
+
+eyr:1963 pid:562051556
+ecl:#793853
+hcl:z byr:2030 iyr:2026
+
+byr:1980
+cid:143 hgt:161cm eyr:2022
+pid:778422225
+hcl:#7d3b0c iyr:2011 ecl:blu
+
+byr:1940 eyr:2021 hgt:74in cid:161 hcl:#a97842 ecl:blu
+pid:864682628 iyr:2014
+
+byr:1991 pid:163871357 ecl:oth
+hgt:189cm cid:229 eyr:2024
+hcl:#efcc98
+iyr:2012
+
+iyr:2013 hcl:#ceb3a1 ecl:hzl byr:1985 pid:801995950 hgt:73in
+eyr:2029
+
+byr:1931 hcl:#ceb3a1 iyr:2013
+cid:289 eyr:2027 ecl:blu
+hgt:150cm pid:969679765
+
+iyr:2015 hgt:176cm eyr:2025 ecl:blu
+byr:1935 pid:388582890 hcl:#efcc98
+
+iyr:1956 eyr:2034 pid:049440894 ecl:xry byr:1950 cid:228
+hgt:186cm
+
+iyr:2014 hcl:#fffffd byr:1985
+eyr:2022
+hgt:176cm pid:556889061 ecl:amb
+
+pid:994755123 hgt:165cm
+ecl:brn
+eyr:2022 byr:1937 iyr:2011
+
+byr:2012
+hcl:z cid:217 iyr:1958
+ecl:brn hgt:160cm
+pid:871866608
+eyr:2027
+
+hcl:#a97842
+ecl:hzl byr:1929
+iyr:2016
+eyr:2029 pid:220410871 hgt:192cm
+
+pid:332596122 byr:1986
+hcl:#cfa07d
+eyr:2022 hgt:189cm ecl:grn iyr:2016
+
+hgt:167cm
+hcl:#6b5442 eyr:2026
+iyr:2020 ecl:grn cid:231 pid:521486150
+
+cid:299
+hgt:178cm byr:1945 ecl:brn iyr:2012
+hcl:#fffffd eyr:2022
+pid:264693268
+
+ecl:lzr pid:157cm hcl:f0a766
+iyr:2029 hgt:175in byr:2004
+
+hcl:#888785
+hgt:159cm eyr:2025
+iyr:2012 ecl:oth
+byr:1995 pid:135442622
+
+eyr:2024 hcl:#a97842
+iyr:2013 pid:186863004 ecl:brn byr:1929 hgt:162cm
+
+pid:518619727 ecl:grn
+hcl:#866857 byr:1954
+iyr:2016
+hgt:69in
+
+eyr:2022 iyr:2018
+byr:1926
+ecl:oth pid:073817633
+hgt:167cm hcl:#b6652a
+
+hgt:190cm iyr:2019
+ecl:dne byr:2010 eyr:2023 pid:979671212
+
+hgt:190
+ecl:#5ddbda byr:2025 iyr:1973 pid:#a082dc eyr:1998 cid:177 hcl:z
+
+iyr:1976 eyr:2026 pid:4862485 hgt:71in
+byr:1975 ecl:#41855f hcl:#ceb3a1
+
+ecl:brn
+byr:1927 iyr:2012 hgt:67in
+pid:479646443 eyr:2039 hcl:z
+
+pid:779458123
+cid:263 hcl:#efcc98
+byr:1951
+hgt:153cm iyr:2011
+ecl:amb eyr:2030
+
+hgt:187cm
+eyr:2028
+byr:1957
+hcl:#b6652a iyr:2015 pid:616963706 ecl:brn
+
+hgt:154cm byr:1947
+pid:51196404
+eyr:2020 iyr:2001
+ecl:hzl
+
+hgt:157cm iyr:2013 eyr:2021
+ecl:blu hcl:d9e6e0
+byr:2023
+
+iyr:2010
+hcl:#866857
+ecl:brn eyr:2022
+cid:163 byr:1962 pid:458396337 hgt:160cm
+
+ecl:amb eyr:2027
+byr:1987
+hgt:184cm
+pid:125222897 cid:214
+iyr:2020
+
+ecl:grt eyr:1942
+iyr:2023
+hcl:901862 hgt:159in
+byr:2009
+
+eyr:2028
+byr:1973 hgt:151cm iyr:2013 ecl:hzl pid:229165831
+
+eyr:2024 hgt:190cm ecl:grn byr:1962 iyr:1921 pid:531272718 hcl:#ceb3a1
+
+hgt:169in pid:1747598652 ecl:dne
+iyr:1974 eyr:2031 hcl:#602927 byr:2030
+
+hgt:177cm iyr:1963 eyr:2006
+cid:276 hcl:#7d3b0c
+pid:192cm
+ecl:grn byr:2022
+
+pid:893346945 hcl:#733820 ecl:oth iyr:2013 byr:1973 hgt:186cm eyr:2025
+
+hgt:177cm
+eyr:2025
+byr:1997 hcl:#733820
+cid:295 iyr:2016 pid:019887743 ecl:grn
+
+iyr:2019
+byr:1982 eyr:2030 ecl:brn pid:041140029 hcl:#a97842 hgt:189cm
+
+pid:165cm iyr:1962 hcl:e5c590 ecl:#e394a4
+eyr:2040
+hgt:70cm byr:2006
+
+byr:1940 eyr:2025 iyr:2020 hcl:#a97842 ecl:brn pid:502841851 cid:121
+hgt:160cm
+
+eyr:2015 ecl:zzz hgt:174 pid:154cm iyr:2021
+hcl:z
+cid:113
+byr:2003
+
+iyr:2020
+eyr:2023 pid:402183362 hcl:#120eb2
+ecl:amb
+hgt:150in
+byr:1921
+
+pid:059311672 cid:290 hcl:#7d3b0c byr:1996
+iyr:2021 hgt:155cm ecl:hzl eyr:2030
+
+pid:790768270 hgt:167cm ecl:gry
+byr:1973
+hcl:#b6652a eyr:2028 iyr:2017
+
+hcl:#18171d eyr:2024 pid:062349624
+byr:2002 iyr:2019 cid:230 ecl:oth
+
+iyr:2015
+hgt:170cm
+cid:193
+eyr:2025 ecl:hzl byr:1947
+pid:484823445
+hcl:#623a2f
+
+pid:5792950369 cid:343
+hcl:1d16b7 eyr:2024
+hgt:185in iyr:1965
+ecl:gmt byr:1948
+
+pid:#a1a101
+ecl:grn
+byr:1945
+iyr:2013 hcl:#ceb3a1 hgt:156cm cid:279 eyr:2026
+
+pid:936593230 eyr:2026 hgt:179cm
+hcl:#7d3b0c
+iyr:2015 byr:1976
+ecl:gry
+
+eyr:2021 pid:210678956 hgt:153cm cid:72 iyr:2018 ecl:grn
+
+pid:995512119
+byr:1937 eyr:2021 hcl:#4d8fe2 ecl:brn
+iyr:2019
+hgt:187cm
+
+hcl:#341e13 pid:282336259 eyr:2022
+cid:95 byr:1977 hgt:101 ecl:#955529
+iyr:2029
+
+pid:934992980 hcl:#fffffd iyr:2028 eyr:1945 ecl:gry byr:1926
+
+iyr:2018 ecl:gry
+hgt:179cm hcl:#866857 pid:573616710
+byr:1987
+
+byr:2010 eyr:2021 hcl:z pid:018180068 hgt:74
+cid:183 iyr:2027 ecl:dne
+
+iyr:2020 hgt:160cm
+pid:760124779 hcl:#b6652a ecl:grn eyr:2030 byr:1951
+
+pid:354858055 ecl:hzl hgt:192cm
+hcl:#ceb3a1 byr:1983 cid:314
+iyr:2016 eyr:2027
+
+eyr:2028 iyr:2013 hgt:171cm hcl:54be83 ecl:xry byr:2021
+pid:89895052
+
+byr:1963 iyr:2019
+pid:298992037 eyr:2024
+hgt:63in hcl:#341e13
+
+hgt:64cm
+pid:7645482607 ecl:#c94773 cid:231 hcl:621e9d eyr:2000 byr:2013
+
+hcl:#ceb3a1 ecl:gry iyr:2015 hgt:178cm byr:1945
+pid:416960939
+
+hgt:178cm
+cid:121
+byr:1961 iyr:2019 hcl:#6b5442
+eyr:2028 pid:098226989
+
+iyr:2015 eyr:2028
+ecl:amb
+hgt:154cm
+pid:364426658 byr:1960
+hcl:#623a2f
+
+byr:1998
+pid:#e5ab03 hcl:z ecl:grn
+iyr:2006 hgt:61cm eyr:2038
+
+hcl:#866857 eyr:2020
+hgt:187in
+pid:#8239dc iyr:2010 ecl:#6259e7 byr:1939
+
+pid:#6082fa eyr:2028 ecl:gry hcl:937410 iyr:2010
+hgt:173cm
+
+eyr:1922 ecl:grt pid:228396726 hgt:65cm
+hcl:#6b5442 byr:2024 iyr:2010
+
+hcl:#c0946f iyr:2016 byr:1978
+pid:774430678 eyr:2026
+ecl:oth hgt:61in
+
+cid:208 pid:714195768 iyr:2019 eyr:2022 byr:1937 ecl:gry hcl:#ceb3a1 hgt:159cm
+
+eyr:2028 ecl:gry iyr:2010 byr:2001 hgt:163cm pid:409136005 hcl:#623a2f cid:200
+
+pid:471094613 eyr:2028 hgt:165cm iyr:2010 ecl:amb byr:1995 hcl:#a97842
+
+ecl:oth iyr:2011 pid:907249487 eyr:2020
+byr:1924 cid:68 hcl:#a97842
+hgt:155cm
+
+byr:1983
+hgt:69cm
+eyr:2027 iyr:2010 hcl:#866857
+pid:671371092
+ecl:amb
+
+hgt:97 pid:168cm cid:67
+eyr:1957 hcl:#623a2f byr:2027 ecl:gry iyr:2019
+
+ecl:blu iyr:2012 pid:287999130 hgt:178cm eyr:2020
+byr:1940
+hcl:#888785
+
+hcl:z hgt:63cm ecl:grt
+iyr:2024 eyr:2031 pid:167cm
+byr:2013
+
+hgt:65in hcl:z cid:300 ecl:amb pid:58257193
+byr:1969 iyr:2011 eyr:1985
+
+hcl:#341e13 eyr:2036 hgt:189in
+pid:58541401
+ecl:#d793f2 iyr:2010 byr:2006
+
+cid:259 ecl:grn
+hcl:#a97842
+hgt:167cm
+pid:641690548 eyr:2021
+byr:1930
+iyr:2010
+
+eyr:2027
+hgt:75in
+cid:335 hcl:#602927 iyr:2012 ecl:blu pid:724014178
+byr:1928
+
+eyr:2027
+hcl:#8345d8 ecl:grn byr:1965 pid:728151722
+hgt:182cm iyr:2016
+
+iyr:2020 pid:794922933
+hcl:#341e13
+ecl:oth
+byr:1985
+hgt:71in
+eyr:2022
+
+ecl:#025c94
+hcl:#fffffd
+iyr:2027
+byr:1987 hgt:186cm cid:135 pid:005852205
+eyr:2021
+
+byr:2020
+ecl:grn
+pid:91200233
+iyr:2014 eyr:2020 hgt:179cm hcl:be0c95
+
+ecl:gmt iyr:2010 pid:171cm byr:2010 eyr:2036 hgt:159in hcl:424df0
+
+ecl:gry iyr:2013 hcl:#7d3b0c hgt:175cm pid:337611432 byr:1953 eyr:2021
+
+byr:1926 pid:678688040
+hcl:#cfa07d
+cid:311 eyr:2027 hgt:183cm iyr:2018
+ecl:blu
+
+byr:2021
+pid:156cm
+ecl:dne
+hgt:156cm
+hcl:#6b5442
+iyr:2027
+
+pid:380639402 eyr:2025
+cid:196
+hgt:163cm
+hcl:#602927 ecl:hzl
+iyr:2015
+
+eyr:2039 hcl:5aa018 byr:2007 ecl:dne
+hgt:77 pid:#d30c1c iyr:2025
+
+ecl:blu
+iyr:1986 pid:3544865154 eyr:2027 byr:2007 hgt:74cm hcl:ca33b3
+
+pid:#b05294 byr:1951 hcl:#ceb3a1 cid:221
+iyr:2000 hgt:110 eyr:2021
+
+byr:1954 hcl:#efcc98 iyr:2018 ecl:#f4ea81
+pid:414210788 hgt:174cm eyr:2037
+
+pid:#abbdd9
+hgt:164in
+iyr:2003 cid:319 eyr:2035
+byr:2015
+ecl:#9b38c7
+
+ecl:amb
+iyr:2018 byr:1922
+hgt:157cm pid:801421993 eyr:2029
+hcl:#efcc98
+
+eyr:2022
+hcl:#b6652a
+ecl:amb byr:1942
+hgt:153cm iyr:2018
+pid:805225382
+
+byr:1925
+hcl:#efcc98 ecl:amb pid:539625393 cid:269
+hgt:161cm iyr:2013 eyr:2025
+
+cid:305 hgt:154cm
+hcl:#18171d byr:1998
+eyr:2029 iyr:2011 pid:634235387 ecl:gry
+
+hcl:#6b5442 pid:504467634 iyr:2018 cid:96 byr:1970
+ecl:gry eyr:2023 hgt:167cm
+
+iyr:2020 hgt:163cm hcl:#fffffd pid:762271916 byr:2029 eyr:2022
+ecl:#12027c
+
+byr:1978
+cid:134 hcl:#6b5442
+iyr:2010 pid:627335191 ecl:blu eyr:2023 hgt:171cm
+
+pid:260340768 hcl:#a97842 byr:1947 ecl:#2150e3 iyr:2019
+cid:153
+hgt:65in eyr:2025
+
+byr:1973 eyr:2022
+cid:229 pid:515108192 ecl:amb hcl:z
+iyr:2013 hgt:178cm
+
+ecl:hzl
+hgt:158cm hcl:#a97842
+pid:657117959 byr:1977 eyr:2023 iyr:2018
+
+ecl:gry eyr:2024
+hgt:163cm byr:1976 iyr:2017
+pid:653769092 hcl:#18171d
+
+ecl:amb pid:161694953
+hcl:#602927 hgt:188cm eyr:2021 byr:1946
+iyr:2016
+
+eyr:2021
+hgt:178cm ecl:grn
+byr:1961 pid:472866063 iyr:2011 hcl:#cfa07d cid:160
+
+eyr:2037 iyr:2011
+hgt:187cm byr:1973 pid:163cm hcl:#b6652a
+ecl:brn cid:283
+
+iyr:2017 hcl:#18171d eyr:2020 pid:059926864 hgt:160cm ecl:brn
+
+byr:2010
+hcl:8217d4 hgt:153in iyr:1989 eyr:2037 pid:#74e0a4 ecl:#ba5782
+
+ecl:#28f922
+byr:1951 hgt:65cm
+iyr:2025 pid:151cm hcl:z eyr:2028
+
+pid:302959013
+hgt:167cm eyr:2022 ecl:hzl iyr:2014
+cid:168
+hcl:#888785 byr:1969
+
+pid:013861920 hcl:#623a2f
+ecl:gry
+byr:1928
+iyr:2017 hgt:174cm eyr:2028 cid:250
+
+byr:1997 hgt:74cm hcl:#efcc98 eyr:2039 ecl:#d3dc6a
+cid:243
+iyr:2030 pid:189cm
+
+hgt:67cm byr:2011 eyr:2040 pid:192cm ecl:#b7a5a8 hcl:281b25
+
+iyr:2014 ecl:brn byr:1954 hcl:#fffffd pid:285922660 hgt:76in eyr:2028
+
+iyr:2021 byr:2028
+eyr:2023
+hgt:69in hcl:e832ef pid:714568559 ecl:#f10004 cid:208
+
+ecl:brn hgt:166cm hcl:#cfa07d
+cid:59 pid:4884483993
+iyr:2012
+eyr:1932
+
+iyr:2029 byr:2025
+cid:238 ecl:utc
+eyr:2022
+pid:887425834 hgt:177in
+
+pid:014383055 cid:342 hgt:183cm eyr:2025
+iyr:2014 ecl:blu byr:1969 hcl:#7d3b0c
+
+eyr:2033
+hcl:#341e13
+iyr:2014
+hgt:71cm ecl:#750eec
+byr:1980 pid:#e2d3ac
+
+hgt:154cm iyr:2019 hcl:#341e13 ecl:hzl byr:1942 pid:393181243 eyr:2025
+cid:316
+
+ecl:amb
+hgt:158cm
+eyr:2025 byr:1986 hcl:#fffffd pid:379180765 iyr:2014
+
+pid:8191674491 eyr:2028 hcl:#efcc98 byr:2015 iyr:2012
+ecl:amb cid:140
+
+byr:2015 hcl:8e3e81 eyr:2024 hgt:180cm iyr:1984 pid:#56cd0e
+ecl:zzz
+
+pid:247138863 eyr:2022 hgt:176cm iyr:2014 byr:1929
+ecl:gry cid:87 hcl:#b6652a
+
+hcl:z pid:#c4cdee ecl:#ca97a6 byr:1971 eyr:2032
+iyr:1997 hgt:156in
+
+ecl:gry
+hgt:167cm eyr:2030 byr:1984 hcl:#cfa07d iyr:2016
+
+hcl:#a97842 hgt:163cm
+pid:373461578 iyr:2017
+byr:1926 ecl:amb
+eyr:2021
+
+cid:161 hcl:#b6652a byr:1930 ecl:brn eyr:2028 hgt:166cm iyr:2016
+
+ecl:amb cid:126
+eyr:2024
+hcl:#18171d iyr:2019
+byr:1991 hgt:183cm
+
+ecl:lzr iyr:2026 byr:1996
+hgt:69in pid:#ccef7e eyr:2028
+hcl:#fffffd
+
+hgt:68cm iyr:1945
+ecl:brn byr:2009 pid:#56e987 hcl:fdd212 eyr:2023
+
+pid:72039060 eyr:2036 hgt:172cm
+hcl:#fffffd iyr:2011
+byr:1944 ecl:xry cid:202
+
+ecl:hzl
+eyr:2025
+byr:1922 hcl:#efcc98
+pid:795790549
+iyr:2020 hgt:150cm
+
+hgt:155cm
+hcl:#373de2 pid:#707dc6 iyr:2017 byr:2002 eyr:2038
+ecl:oth
+
+hcl:#888785 iyr:2011
+hgt:159cm
+byr:1962 eyr:2026 ecl:amb pid:672792762
+
+cid:217 eyr:2025 hgt:164cm byr:1999 pid:975218035 ecl:grn hcl:#18171d iyr:2011
+
+pid:655501194 eyr:2029 byr:1999 iyr:2013
+hgt:183cm hcl:#a97842 ecl:hzl
+
+byr:1986 hcl:#efcc98 pid:160cm ecl:oth eyr:2022 iyr:2022 hgt:150cm
+cid:63
+
+hgt:69in byr:2002 pid:0528229881 ecl:blu hcl:z iyr:2022
+eyr:2033
+
+iyr:2020 pid:007754028 hcl:z cid:232 ecl:dne hgt:73in
+
+ecl:hzl
+iyr:2016 hcl:#7d3b0c byr:1948
+eyr:2021
+cid:269 hgt:173cm pid:176430746
+
+cid:310
+ecl:xry
+eyr:2032 hgt:64cm
+pid:190cm hcl:z byr:2019
+
+hgt:150cm pid:660176034 hcl:#c0946f
+ecl:hzl byr:1986 eyr:2021 iyr:2019
+
+pid:7876582
+eyr:2021 iyr:2020
+hgt:185cm hcl:#18171d cid:319 ecl:amb byr:1943
+
+ecl:hzl hcl:#623a2f iyr:1950 byr:2012 cid:334 eyr:2028
+
+eyr:2028
+byr:1992 hcl:#b6652a ecl:hzl cid:222
+hgt:189cm iyr:2016
+pid:092856842
+
+hcl:a3c52a
+iyr:2025 byr:2023
+hgt:182cm ecl:#be1503 pid:9311657615 eyr:2005
+
+eyr:2035
+byr:1988 hgt:193cm
+iyr:2028 cid:128 hcl:#18171d ecl:utc pid:9743739773
+
+ecl:zzz hcl:z
+hgt:64cm pid:160cm byr:2026 eyr:1943 iyr:2028 cid:74
+
+ecl:oth
+pid:874577361
+iyr:2010 eyr:2021
+hgt:160cm hcl:#c0946f
+byr:1959
diff --git a/data/advent04a.txt b/data/advent04a.txt
new file mode 100644 (file)
index 0000000..0ff208e
--- /dev/null
@@ -0,0 +1,13 @@
+ecl:gry pid:860033327 eyr:2020 hcl:#fffffd
+byr:1937 iyr:2017 cid:147 hgt:183cm
+
+iyr:2013 ecl:amb cid:350 eyr:2023 pid:028048884
+hcl:#cfa07d byr:1929
+
+hcl:#ae17e1 iyr:2013
+eyr:2024
+ecl:brn pid:760753108 byr:1931
+hgt:179cm
+
+hcl:#cfa07d eyr:2025 pid:166559648
+iyr:2011 ecl:brn hgt:59in
diff --git a/problems/day4.html b/problems/day4.html
new file mode 100644 (file)
index 0000000..0fa2d68
--- /dev/null
@@ -0,0 +1,222 @@
+<!DOCTYPE html>
+<html lang="en-us">
+<head>
+<meta charset="utf-8"/>
+<title>Day 4 - Advent of Code 2020</title>
+<!--[if lt IE 9]><script src="/static/html5.js"></script><![endif]-->
+<link href='//fonts.googleapis.com/css?family=Source+Code+Pro:300&subset=latin,latin-ext' rel='stylesheet' type='text/css'/>
+<link rel="stylesheet" type="text/css" href="/static/style.css?25"/>
+<link rel="stylesheet alternate" type="text/css" href="/static/highcontrast.css?0" title="High Contrast"/>
+<link rel="shortcut icon" href="/favicon.png"/>
+</head><!--
+
+
+
+
+Oh, hello!  Funny seeing you here.
+
+I appreciate your enthusiasm, but you aren't going to find much down here.
+There certainly aren't clues to any of the puzzles.  The best surprises don't
+even appear in the source until you unlock them for real.
+
+Please be careful with automated requests; I'm not a massive company, and I can
+only take so much traffic.  Please be considerate so that everyone gets to play.
+
+If you're curious about how Advent of Code works, it's running on some custom
+Perl code. Other than a few integrations (auth, analytics, social media), I
+built the whole thing myself, including the design, animations, prose, and all
+of the puzzles.
+
+The puzzles are most of the work; preparing a new calendar and a new set of
+puzzles each year takes all of my free time for 4-5 months. A lot of effort
+went into building this thing - I hope you're enjoying playing it as much as I
+enjoyed making it for you!
+
+If you'd like to hang out, I'm @ericwastl on Twitter.
+
+- Eric Wastl
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+-->
+<body>
+<header><div><h1 class="title-global"><a href="/">Advent of Code</a></h1><nav><ul><li><a href="/2020/about">[About]</a></li><li><a href="/2020/events">[Events]</a></li><li><a href="https://teespring.com/stores/advent-of-code" target="_blank">[Shop]</a></li><li><a href="/2020/settings">[Settings]</a></li><li><a href="/2020/auth/logout">[Log Out]</a></li></ul></nav><div class="user">Neil Smith <a href="/2020/support" class="supporter-badge" title="Advent of Code Supporter">(AoC++)</a> <span class="star-count">8*</span></div></div><div><h1 class="title-event">&nbsp;&nbsp;&nbsp;<span class="title-event-wrap">0x0000|</span><a href="/2020">2020</a><span class="title-event-wrap"></span></h1><nav><ul><li><a href="/2020">[Calendar]</a></li><li><a href="/2020/support">[AoC++]</a></li><li><a href="/2020/sponsors">[Sponsors]</a></li><li><a href="/2020/leaderboard">[Leaderboard]</a></li><li><a href="/2020/stats">[Stats]</a></li></ul></nav></div></header>
+
+<div id="sidebar">
+<div id="sponsor"><div class="quiet">Our <a href="/2020/sponsors">sponsors</a> help make Advent of Code possible:</div><div class="sponsor"><a href="https://medium.com/building-trayio" target="_blank" onclick="if(ga)ga('send','event','sponsor','sidebar',this.href);" rel="noopener">tray.io</a> - Building a platform that connects people with technology.</div></div>
+</div><!--/sidebar-->
+
+<main>
+<script>window.addEventListener('click', function(e,s,r){if(e.target.nodeName==='CODE'&&e.detail===3){s=window.getSelection();s.removeAllRanges();r=document.createRange();r.selectNodeContents(e.target);s.addRange(r);}});</script>
+<article class="day-desc"><h2>--- Day 4: Passport Processing ---</h2><p>You arrive at the airport only to realize that you grabbed your North Pole Credentials instead of your passport. While these documents are extremely similar, North Pole Credentials aren't issued by a country and therefore aren't actually valid documentation for travel in most of the world.</p>
+<p>It seems like you're not the only one having problems, though; a very long line has formed for the automatic passport scanners, and the delay could upset your travel itinerary.</p>
+<p>Due to some questionable network security, you realize you might be able to solve both of these problems at the same time.</p>
+<p>The automatic passport scanners are slow because they're having trouble <em>detecting which passports have all required fields</em>. The expected fields are as follows:</p>
+<ul>
+<li><code>byr</code> (Birth Year)</li>
+<li><code>iyr</code> (Issue Year)</li>
+<li><code>eyr</code> (Expiration Year)</li>
+<li><code>hgt</code> (Height)</li>
+<li><code>hcl</code> (Hair Color)</li>
+<li><code>ecl</code> (Eye Color)</li>
+<li><code>pid</code> (Passport ID)</li>
+<li><code>cid</code> (Country ID)</li>
+</ul>
+<p>Passport data is validated in batch files (your puzzle input). Each passport is represented as a sequence of <code>key:value</code> pairs separated by spaces or newlines. Passports are separated by blank lines.</p>
+<p>Here is an example batch file containing four passports:</p>
+<pre><code>ecl:gry pid:860033327 eyr:2020 hcl:#fffffd
+byr:1937 iyr:2017 cid:147 hgt:183cm
+
+iyr:2013 ecl:amb cid:350 eyr:2023 pid:028048884
+hcl:#cfa07d byr:1929
+
+hcl:#ae17e1 iyr:2013
+eyr:2024
+ecl:brn pid:760753108 byr:1931
+hgt:179cm
+
+hcl:#cfa07d eyr:2025 pid:166559648
+iyr:2011 ecl:brn hgt:59in
+</code></pre>
+<p>The first passport is <em>valid</em> - all eight fields are present. The second passport is <em>invalid</em> - it is missing <code>hgt</code> (the Height field).</p>
+<p>The third passport is interesting; the <em>only missing field</em> is <code>cid</code>, so it looks like data from North Pole Credentials, not a passport at all! Surely, nobody would mind if you made the system temporarily ignore missing <code>cid</code> fields.  Treat this "passport" as <em>valid</em>.</p>
+<p>The fourth passport is missing two fields, <code>cid</code> and <code>byr</code>. Missing <code>cid</code> is fine, but missing any other field is not, so this passport is <em>invalid</em>.</p>
+<p>According to the above rules, your improved system would report <code><em>2</em></code> valid passports.</p>
+<p>Count the number of <em>valid</em> passports - those that have all required fields. Treat <code>cid</code> as optional. <em>In your batch file, how many passports are valid?</em></p>
+</article>
+<p>Your puzzle answer was <code>247</code>.</p><article class="day-desc"><h2 id="part2">--- Part Two ---</h2><p>The line is moving more quickly now, but you overhear airport security talking about how passports with invalid data are getting through. Better add some data validation, quick!</p>
+<p>You can continue to ignore the <code>cid</code> field, but each other field has <span title="GLORY TO ARSTOTZKA">strict rules</span> about what values are valid for automatic validation:</p>
+<ul>
+<li><code>byr</code> (Birth Year) - four digits; at least <code>1920</code> and at most <code>2002</code>.</li>
+<li><code>iyr</code> (Issue Year) - four digits; at least <code>2010</code> and at most <code>2020</code>.</li>
+<li><code>eyr</code> (Expiration Year) - four digits; at least <code>2020</code> and at most <code>2030</code>.</li>
+<li><code>hgt</code> (Height) - a number followed by either <code>cm</code> or <code>in</code>:
+  <ul>
+  <li>If <code>cm</code>, the number must be at least <code>150</code> and at most <code>193</code>.</li>
+  <li>If <code>in</code>, the number must be at least <code>59</code> and at most <code>76</code>.</li>
+  </ul>
+</li>
+<li><code>hcl</code> (Hair Color) - a <code>#</code> followed by exactly six characters <code>0</code>-<code>9</code> or <code>a</code>-<code>f</code>.</li>
+<li><code>ecl</code> (Eye Color) - exactly one of: <code>amb</code> <code>blu</code> <code>brn</code> <code>gry</code> <code>grn</code> <code>hzl</code> <code>oth</code>.</li>
+<li><code>pid</code> (Passport ID) - a nine-digit number, including leading zeroes.</li>
+<li><code>cid</code> (Country ID) - ignored, missing or not.</li>
+</ul>
+<p>Your job is to count the passports where all required fields are both <em>present</em> and <em>valid</em> according to the above rules. Here are some example values:</p>
+<pre><code>byr valid:   2002
+byr invalid: 2003
+
+hgt valid:   60in
+hgt valid:   190cm
+hgt invalid: 190in
+hgt invalid: 190
+
+hcl valid:   #123abc
+hcl invalid: #123abz
+hcl invalid: 123abc
+
+ecl valid:   brn
+ecl invalid: wat
+
+pid valid:   000000001
+pid invalid: 0123456789
+</code></pre>
+<p>Here are some invalid passports:</p>
+<pre><code>eyr:1972 cid:100
+hcl:#18171d ecl:amb hgt:170 pid:186cm iyr:2018 byr:1926
+
+iyr:2019
+hcl:#602927 eyr:1967 hgt:170cm
+ecl:grn pid:012533040 byr:1946
+
+hcl:dab227 iyr:2012
+ecl:brn hgt:182cm pid:021572410 eyr:2020 byr:1992 cid:277
+
+hgt:59cm ecl:zzz
+eyr:2038 hcl:74454a iyr:2023
+pid:3556412378 byr:2007
+</code></pre>
+<p>Here are some valid passports:</p>
+<pre><code>pid:087499704 hgt:74in ecl:grn iyr:2012 eyr:2030 byr:1980
+hcl:#623a2f
+
+eyr:2029 ecl:blu cid:129 byr:1989
+iyr:2014 pid:896056539 hcl:#a97842 hgt:165cm
+
+hcl:#888785
+hgt:164cm byr:2001 iyr:2015 cid:88
+pid:545766238 ecl:hzl
+eyr:2022
+
+iyr:2010 hgt:158cm hcl:#b6652a ecl:blu byr:1944 eyr:2021 pid:093154719
+</code></pre>
+<p>Count the number of <em>valid</em> passports - those that have all required fields <em>and valid values</em>. Continue to treat <code>cid</code> as optional. <em>In your batch file, how many passports are valid?</em></p>
+</article>
+<p>Your puzzle answer was <code>145</code>.</p><p class="day-success">Both parts of this puzzle are complete! They provide two gold stars: **</p>
+<p>At this point, you should <a href="/2020">return to your Advent calendar</a> and try another puzzle.</p>
+<p>If you still want to see it, you can <a href="4/input" target="_blank">get your puzzle input</a>.</p>
+<p>You can also <span class="share">[Share<span class="share-content">on
+  <a href="https://twitter.com/intent/tweet?text=I%27ve+completed+%22Passport+Processing%22+%2D+Day+4+%2D+Advent+of+Code+2020&amp;url=https%3A%2F%2Fadventofcode%2Ecom%2F2020%2Fday%2F4&amp;related=ericwastl&amp;hashtags=AdventOfCode" target="_blank">Twitter</a>
+  <a href="javascript:void(0);" onclick="var mastodon_instance=prompt('Mastodon Instance / Server Name?'); if(typeof mastodon_instance==='string' && mastodon_instance.length){this.href='https://'+mastodon_instance+'/share?text=I%27ve+completed+%22Passport+Processing%22+%2D+Day+4+%2D+Advent+of+Code+2020+%23AdventOfCode+https%3A%2F%2Fadventofcode%2Ecom%2F2020%2Fday%2F4'}else{return false;}" target="_blank">Mastodon</a
+></span>]</span> this puzzle.</p>
+</main>
+
+<!-- ga -->
+<script>
+(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+ga('create', 'UA-69522494-1', 'auto');
+ga('set', 'anonymizeIp', true);
+ga('send', 'pageview');
+</script>
+<!-- /ga -->
+</body>
+</html>
\ No newline at end of file
index 4659b84dc51ac4316296ca5206943d0c86e51a71..6066fdea7f65a819c277e88d7c6d4dc43172eb32 100644 (file)
@@ -38,6 +38,7 @@ packages:
 - advent01
 - advent02
 - advent03
+- advent04
 
 # Dependency packages to be pulled from upstream that are not in the resolver.
 # These entries can reference officially published versions as well as