Created
December 5, 2020 04:55
-
-
Save shayelkin/06437d1da05787ec1db44e1897d50c39 to your computer and use it in GitHub Desktop.
AoC 2020 Day 4. Solve by generating a huge regex
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; AoC 2020 Day 4. Solve by generating a huge regex. | |
(require '[clojure.string :as s]) | |
(def sample-passports | |
"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") | |
(def mandatory-fields | |
{"byr" "19[2-9]\\d|200[0-2]" | |
"iyr" "20(?:1\\d|20)" | |
"eyr" "20(?:2\\d|30)" | |
"hgt" "(?:59|6\\d|7[0-6])in|(?:1(?:[5-8]\\d|9[0-3]))cm" | |
"hcl" "#[\\da-f]{6}" | |
"ecl" "amb|blu|brn|gry|grn|hzl|oth" | |
"pid" "\\d{9}"}) | |
(def re-valid-passport | |
(letfn [(make-inner [xs start-idx] | |
(s/join | |
["(?:" "\\b(?:" | |
;; trick: to make sure we don't catch the same key twice, add an | |
;; empty capturing group after each field, then re-match on them all. | |
;; if we didn't match on all the fields, we'd be lacking groups to | |
;; match on, and fail. | |
;; note that we may have previous fields, so we need an index to start with | |
(s/join "()|" xs) | |
"()):\\S+(?:\\s+|$)" ;; assume field values are of length ≥ 1 | |
"){" (count xs) "}" | |
(s/join | |
(map (partial str "\\") | |
(range start-idx (+ start-idx (count xs)))))]))] | |
(re-pattern | |
(str (make-inner (keys mandatory-fields) 1) | |
"|" | |
(make-inner (conj (keys mandatory-fields) "cid") (inc (count mandatory-fields))) | |
"(?:\\v|$)")))) | |
;; => #"(?:\b(?:byr()|iyr()|eyr()|hgt()|hcl()|ecl()|pid()):\S+(?:\s+|$)){7}\1\2\3\4\5\6\7|(?:\b(?:cid()|byr()|iyr()|eyr()|hgt()|hcl()|ecl()|pid()):\S+(?:\s+|$)){8}\8\9\10\11\12\13\14\15(?:\v|$)" | |
(defn count-passports [re passports] | |
(count (re-seq re passports))) | |
(assert (= 2 (count-passports re-valid-fields sample-passports))) | |
(def re-valid-passport-with-vals | |
(letfn [(make-inner [xs start-idx] | |
(s/join | |
["(?:" "\\b(?:" | |
(s/join | |
"()|" | |
(map (partial apply (partial format "%s:(?:%s)")) xs)) | |
"())(?:\\s+|$)" ;; assume field values are of length ≥ 1 | |
"){" (count xs) "}" | |
(s/join | |
(map (partial str "\\") | |
(range start-idx (+ start-idx (count xs)))))]))] | |
(re-pattern | |
(str (make-inner mandatory-fields 1) | |
"|" | |
(make-inner (conj mandatory-fields ["cid" ".+"]) (inc (count mandatory-fields))) | |
"(?:\\v|$)")))) | |
;; => #"(?:\b(?:byr:(?:19[2-9]\d|200[0-2])()|iyr:(?:20(?:1\d|20))()|eyr:(?:20(?:2\d|30))()|hgt:(?:(?:59|6\d|7[0-6])in|(?:1(?:[5-8]\d|9[0-3]))cm)()|hcl:(?:#[\da-f]{6})()|ecl:(?:amb|blu|brn|gry|grn|hzl|oth)()|pid:(?:\d{9})())(?:\s+|$)){7}\1\2\3\4\5\6\7|(?:\b(?:byr:(?:19[2-9]\d|200[0-2])()|iyr:(?:20(?:1\d|20))()|eyr:(?:20(?:2\d|30))()|hgt:(?:(?:59|6\d|7[0-6])in|(?:1(?:[5-8]\d|9[0-3]))cm)()|hcl:(?:#[\da-f]{6})()|ecl:(?:amb|blu|brn|gry|grn|hzl|oth)()|pid:(?:\d{9})()|cid:(?:.+)())(?:\s+|$)){8}\8\9\10\11\12\13\14\15(?:\v|$)" | |
(def sample-invalid-passports | |
"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") | |
(assert (= 0 (count-passports re-valid-passport-with-vals sample-invalid-passports))) | |
(def sample-valid-passports | |
"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") | |
(assert (= 4 (count-passports re-valid-passport-with-vals sample-valid-passports))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment