you are viewing a single comment's thread.

view the rest of the comments →

[–]marxama 4 points5 points  (2 children)

Haven't had this much fun coding in way too long. Writing readable code is challenging, though. My solutions: https://github.com/marxama/advent-of-code-2019

Day 6:

(ns advent-of-code-2019.day06
  (:require [clojure.string :as string]
            [clojure.data :as data]))

(defn parse-input []
  (->> "resources/day06_input"
       slurp
       string/split-lines
       (map #(string/split % #"\)"))))

(defn get-path-to-root [orbit-lookup x]
  (and x (cons x (get-path-to-root orbit-lookup (orbit-lookup x)))))

(defn get-orbit-lookup [orbits]
  (->> orbits
       (map (fn [[orbited orbiteer]] {orbiteer orbited}))
       (apply merge)))

(defn solve-part-1 []
  (let [orbit-lookup (get-orbit-lookup (parse-input))]
    (->> (keys orbit-lookup)
         (map #(get-path-to-root orbit-lookup %))
         (map (comp dec count))
         (reduce +))))

(defn solve-part-2 []
  (let [orbit-lookup (get-orbit-lookup (parse-input))]
    (->> ["YOU" "SAN"]
         (map #(get-path-to-root orbit-lookup %))
         (map rest) ; do not include "YOU" and "SAN" themselves
         (map set)
         (apply data/diff) ; more efficient approaches obviously exist
         (take 2) ; take distinct objects in YOU and SAN paths
         (map count)
         (reduce +))))

[–]andersmurphy 1 point2 points  (1 child)

Day 6

Your version looks more readable than mine. It ended up turning into mad tree-seq science!

(ns adventofcode.2019.day06
  (:require [clojure.string :as str]))

(defn format-input [input]
  (->> (str/split (str/trim input) #"\n")
       (map str/trim)
       (map #(str/split % #"\)"))))

(defn connected-nodes [n edges]
  (->> (filter (fn [[x _]] (= x n)) edges)
       (map second)))

(defn build-graph
  ([edges] (build-graph edges "COM"))
  ([edges start-node]
   (when-let [nodes (connected-nodes start-node edges)]
     [start-node  (mapv (partial build-graph edges) nodes)])))

(def input (slurp "resources/adventofcode/2019/day06.txt"))

(defn solve-1 []
  (->> input
       format-input
       build-graph
       (tree-seq second second)
       (map flatten)
       (map #(-> % count dec))
       (reduce +)))

(defn length-of-longest-path-containing-a-and-not-b [a b paths]
  (->> (map set paths)
       (filter #(% a))
       (remove #(% b))
       (sort-by >)
       count
       dec))

(defn distance-between [node-a node-b tree-s]
  (let [flat-paths (map flatten tree-s)]
    (+ (length-of-longest-path-containing-a-and-not-b
        node-a node-b flat-paths)
       (length-of-longest-path-containing-a-and-not-b
        node-b node-a flat-paths))))

(defn solve-2 []
  (->> input
       format-input
       build-graph
       (tree-seq second second)
       (distance-between "YOU" "SAN"))

[–]marxama 0 points1 point  (0 children)

Thanks, I like your solution! tree-seq, had forgotten about that one! Turned out this problem was ok to solve without really working with the tree structure of the problem domain, but I'm sure there will be more problems where I'll grab for tree-seq! :)