Skip to content

Instantly share code, notes, and snippets.

@KennyMonster
Created December 7, 2020 20:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KennyMonster/4e965505f0a8b592a91dd25b5306023f to your computer and use it in GitHub Desktop.
Save KennyMonster/4e965505f0a8b592a91dd25b5306023f to your computer and use it in GitHub Desktop.
AOC 2020 day 7
(ns day-7
(:require [clojure.string :as str]
[clojure.set :refer [difference]]))
(def data (slurp "input/day_7.txt"))
(def sample-data "light red bags contain 1 bright white bag, 2 muted yellow bags.\ndark orange bags contain 3 bright white bags, 4 muted yellow bags.\nbright white bags contain 1 shiny gold bag.\nmuted yellow bags contain 2 shiny gold bags, 9 faded blue bags.\nshiny gold bags contain 1 dark olive bag, 2 vibrant plum bags.\ndark olive bags contain 3 faded blue bags, 4 dotted black bags.\nvibrant plum bags contain 5 faded blue bags, 6 dotted black bags.\nfaded blue bags contain no other bags.\ndotted black bags contain no other bags.")
(defn parse-bag-rule [s]
(let [bag-color (str/join " " (take 2 (str/split s #" ")))
parse-contained-bag (fn [[count color]] {:color color :count (Integer/parseInt count)})
contain (->> (re-seq #"(\d+) (\w+ \w+) bags?" s)
(map rest)
(map parse-contained-bag))]
{:color bag-color
:contain contain}))
(comment
(parse-bag-rule "light red bags contain 1 bright white bag, 2 muted yellow bags.")
(parse-bag-rule "dotted black bags contain no other bags.")
(parse-bag-rule "plaid lavender bags contain 5 mirrored red bags, 1 striped salmon bag, 2 mirrored turquoise bags, 4 dotted cyan bags."))
(def bags (map parse-bag-rule (str/split-lines data)))
(def sample-bags (map parse-bag-rule (str/split-lines sample-data)))
(defn bag-contains-color [color bag]
(contains? (set (map :color (:contain bag))) color))
(defn bag-parents [color bags]
(map :color (filter #(bag-contains-color color %) bags)))
(comment
(bag-parents "bright white" bags))
(defn bag-ancestors [color bags]
(loop [bags-to-check [color]
bag-ancestors []]
(if (seq bags-to-check)
(let [next-bag-parents (bag-parents (first bags-to-check) bags)]
(recur (concat (rest bags-to-check) next-bag-parents)
(concat bag-ancestors next-bag-parents)))
(set bag-ancestors))))
(comment
(count (bag-ancestors "shiny gold" sample-bags)))
;; part 2
(defn contained-bag-colors-as-seq [bag]
(repeat (:count bag) (:color bag)))
(defn bag-children [color bags]
(let [bags-lookup (into {} (map #(vector (:color %) %) bags))]
(loop [colors-to-walk [color]
bag-children []]
(if (seq colors-to-walk)
(let [contained-bags (mapcat contained-bag-colors-as-seq (:contain (bags-lookup (first colors-to-walk))))]
(recur (concat (rest colors-to-walk) contained-bags)
(concat bag-children contained-bags)))
bag-children))))
(comment (count (bag-children "shiny gold" bags)))
@Solaxun
Copy link

Solaxun commented Dec 7, 2020

Your problem was concat, as explained by Stuart Sierra here

(defn bag-children [color bags]
  (let [bags-lookup (into {} (map #(vector (:color %) %) bags))]
    (loop [colors-to-walk [color]
           bag-children  []]
      (if (seq colors-to-walk)
        (let [contained-bags (mapcat contained-bag-colors-as-seq (:contain (bags-lookup (first colors-to-walk))))]
          (recur (into (subvec colors-to-walk 1) contained-bags)  ;; replace concat calls with into []
                 (into bag-children contained-bags)))
        bag-children))))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment