Skip to content

Instantly share code, notes, and snippets.

@cyppan
Created December 12, 2021 21:29
Show Gist options
  • Save cyppan/4bce81a4b09bec30ec711653e4b6219b to your computer and use it in GitHub Desktop.
Save cyppan/4bce81a4b09bec30ec711653e4b6219b to your computer and use it in GitHub Desktop.
Advent of Code 2021 - day 12: Passage Pathing
(ns aoc.day12
(:require [clojure.java.io :as io]
[clojure.string :as str]))
(defn parse-input [file-name]
(reduce (fn [graph [a b]]
(-> graph
(update a conj b)
(update b conj a)))
{}
(->> (str/split (slurp (io/resource (str "day12/" file-name ".txt"))) #"\n")
(map (fn [line] (str/split line #"-"))))))
(defn start-or-end? [node]
(contains? #{"start" "end"} node))
(defn small-cave? [node]
(and (not (start-or-end? node))
(= (str/lower-case node) node)))
(defn should-end-walk-part1 [node visited]
(and (or (start-or-end? node)
(small-cave? node))
(contains? visited node)))
(defn should-end-walk-part2 [node visited!]
(or
(and (start-or-end? node)
(contains? visited! node))
(and (small-cave? node)
(contains? visited! node)
(contains? visited! :twice))))
(defn compute-paths
([graph node part]
(compute-paths graph node part #{}))
([graph node part visited]
(let [should-end-walk? (if (= part :part1) should-end-walk-part1 should-end-walk-part2)]
(cond
(= node "end") 1
(should-end-walk? node visited) 0
:else (let [visited! (if (and (small-cave? node) (contains? visited node))
(conj visited :twice)
(conj visited node))]
(reduce + (map #(compute-paths graph % part visited!) (get graph node))))))))
(comment
;; part 1
(time (compute-paths (parse-input "input") "start" :part1))
;; part 2
(time (compute-paths (parse-input "input") "start" :part2))
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment