1
1
(ns advent-2020-clojure.day19
2
2
(:require [clojure.string :as str]
3
- [advent-2020-clojure.utils :as utils]))
3
+ [advent-2020-clojure.utils :as utils]
4
+ [clojure.set :as set]))
4
5
5
6
(defn parse-rule [input]
6
7
(let [[_ id rule-str] (re-matches #"(\d +): (.*)" input)]
12
13
(defn parse-rules [rule-str]
13
14
(->> rule-str str/split-lines (map parse-rule) (into {})))
14
15
15
- (defn word-combinations [[a-words b-words & others]]
16
- (if (some? b-words)
17
- (let [words (for [a a-words
18
- b b-words]
19
- (str a b))]
20
- (word-combinations (cons words others)))
21
- a-words))
16
+ (defn match-length [rules word rule]
17
+ (let [{:keys [s paths]} (rules rule)]
18
+ (cond
19
+ (str/blank? word) nil
20
+ (some? s) (when (= s (subs word 0 (count s))) #{(count s)})
21
+ :else (->> (for [path paths]
22
+ (reduce (fn [lengths id]
23
+ (if (empty? lengths)
24
+ #{}
25
+ (->> (map (fn [length]
26
+ (->> (match-length rules (subs word length) id)
27
+ (keep identity)
28
+ (map (fn [p] (+ length p)))
29
+ set))
30
+ lengths)
31
+ (apply set/union))))
32
+ #{0 }
33
+ path))
34
+ (keep identity)
35
+ (apply set/union)))))
22
36
23
- (defn valid-strings [rules id]
24
- (let [{:keys [s paths]} (rules id)]
25
- (if (some? s)
26
- (list s)
27
- (->> paths
28
- (map (fn [path]
29
- (->> path
30
- (map #(valid-strings rules %))
31
- word-combinations)))
32
- (apply concat)))))
37
+ (defn valid? [rules word]
38
+ (some #(= % (count word)) (match-length rules word " 0" )))
33
39
34
40
(defn part1 [input]
35
41
(let [[rule-str message-str] (utils/split-blank-line input)
36
- rules (parse-rules rule-str)
37
- messages (str/split-lines message-str)
38
- valids (set (valid-strings rules " 0" ))]
39
- (->> messages
40
- (filter #(valids %))
42
+ rules (parse-rules rule-str)]
43
+ (->> (str/split-lines message-str)
44
+ (keep #(valid? rules %))
45
+ count)))
46
+
47
+ (defn part2 [input]
48
+ (let [[rule-str message-str] (utils/split-blank-line input)
49
+ rules (-> (parse-rules rule-str)
50
+ (assoc " 8" (second (parse-rule " 8: 42 | 42 8" )))
51
+ (assoc " 11" (second (parse-rule " 11: 42 31 | 42 11 31" ))))]
52
+ (->> (str/split-lines message-str)
53
+ (keep #(when (valid? rules %) %))
41
54
count)))
0 commit comments