Created
December 17, 2020 11:39
-
-
Save humbhenri/f57c363c21d81aa8c088d9aa24e35889 to your computer and use it in GitHub Desktop.
This file contains 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
(ns p16 | |
(:require [clojure.string :as str])) | |
(defn to-int[s] | |
(if (re-matches #"\d+" s) | |
(Integer/parseInt s) | |
s)) | |
(defn parse-rule[rule] | |
(->> rule | |
(re-matches #"(.*): (\d+)-(\d+) or (\d+)-(\d+)") | |
rest | |
(map to-int) | |
(zipmap [:field :range1-start :range1-end :range2-start :range2-end]))) | |
(defn debug[x] | |
(println x) | |
x) | |
(defn parse-rules [{rules :rules :as notes}] | |
(->> (map parse-rule (str/split rules #"\n")) | |
(assoc notes :rules))) | |
(defn parse-values [{my-ticket :my-ticket nearby-tickets :nearby-tickets :as notes}] | |
(->> (map #(->> % (re-seq #"\d+") (map to-int)) [my-ticket nearby-tickets]) | |
(zipmap [:my-ticket :nearby-tickets]) | |
(merge notes))) | |
(defn parse-input [file] | |
(as-> file x | |
(slurp x) | |
(str/split x #"\n\n") | |
(zipmap [:rules :my-ticket :nearby-tickets] x) | |
(parse-rules x) | |
(parse-values x))) | |
(defn in? [coll elem] | |
(some #(= elem %) coll)) | |
(defn validate [{r1s :range1-start r1e :range1-end r2s :range2-start r2e :range2-end} value] | |
(or (in? (range r1s (inc r1e)) value) | |
(in? (range r2s (inc r2e)) value))) | |
(defn validate-rules [rules value] | |
(map #(validate % value) rules)) | |
(defn find-invalid-values [{rules :rules nearby-tickets :nearby-tickets}] | |
(->> nearby-tickets | |
(filter #(every? nil? (validate-rules rules %))))) | |
(defn error-rate [notes] | |
(->> notes | |
find-invalid-values | |
(reduce +))) | |
(defn transpose [m] | |
(apply mapv vector m)) | |
(defn positions [{nearby-tickets :nearby-tickets my-ticket :my-ticket}] | |
(->> (concat my-ticket nearby-tickets) | |
(partition (count my-ticket)) | |
transpose)) | |
(defn validate-discarding [rule value invalids] | |
(or (validate rule value) | |
(in? invalids value))) | |
(defn find-field [rules values invalids] | |
(for [r rules | |
:let [v (map #(validate-discarding r % invalids) values)] | |
:when (every? (comp not nil?) v)] | |
(:field r))) | |
(defn remove-field [field fields] | |
(cond (not (seq? fields)) fields | |
(and (= 1 (count fields)) (= field (first fields))) field | |
:else (remove #(= field %) fields))) | |
(defn find-single [fields] | |
(first (first (filter #(and (seq? %) (= 1 (count %))) fields)))) | |
(defn remove-singles [candidates] | |
(let [single (find-single candidates)] | |
(if single | |
(remove-singles (into [] (map #(remove-field single %) candidates))) | |
candidates))) | |
(defn find-fields [{rules :rules nearby-tickets :nearby-tickets my-ticket :my-ticket :as notes}] | |
(let [invalids (find-invalid-values notes)] | |
(->> notes | |
positions | |
(map #(find-field rules % invalids)) | |
remove-singles))) | |
(defn part2 [notes] | |
(as-> notes x | |
(find-fields x) | |
(zipmap x (:my-ticket notes)) | |
(filter (fn [[k v]] (str/starts-with? k "departure")) x) | |
(map second x) | |
(reduce * 1 x))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment