aoc2021-day14b Clojure/JVM program
source code
; SPDX-License-Identifier: MIT
; Copyright (C) 2021 Tito Sacchi <tito@tilde.team>
; WARNING: These solutions were written while I was still learning Clojure and
; should by no means be taken as examples of good programming practice or fast
; implementations.
(ns aoc.2021.14b
(:require
[clojure.string :as str]
[clojure.java.io :as io]))
(defn parse-rule [line]
(let [[in out] (str/split line #" -> ")]
[(vec in) (first out)]))
(def input *in*)
(def reader (io/reader input))
(def polymer-template (first (line-seq reader)))
(def insertion-rules
(persistent!
(reduce #(conj! %1 (parse-rule %2))
(transient {})
(rest (line-seq reader)))))
; Transducer that construct sliding windows of size 2 with step 1
(defn adjacent-pairs []
(fn [xf]
(let [l (volatile! nil)]
(fn
([] (xf))
([result] (xf (xf result [@l])))
([result x] (let [l- @l]
(vreset! l x)
(if l- (xf result [l- x]) result)))))))
(defn apply-rule [[a b]]
(let [c (insertion-rules [a b])]
(if c [a c] [a])))
(def substitute-polymers
(comp
(adjacent-pairs)
(mapcat apply-rule)))
(def evolve-pair
(memoize
(fn [input n]
(let [notlast (drop-last input)
freqs (frequencies notlast)]
(if (= n 0)
[freqs]
(into [freqs]
(apply mapv (partial merge-with +)
(for [pair (eduction
(comp substitute-polymers (adjacent-pairs))
input)]
(evolve-pair pair (dec n))))))))))
(defn evolve-string [input n]
(apply mapv
(partial merge-with +)
(map #(evolve-pair % n) (eduction (adjacent-pairs) input))))
(println
(let [starting (conj (vec polymer-template) ::none)
final (peek (evolve-string starting 40))
freqs (vals final)]
(- (apply max freqs) (apply min freqs))))
notes, command-line, and program output
NOTES:
Linux
Sun, 23 Jan 2022 21:52:45 GMT
COMMAND LINE:
clojure -cp /usr/share/java/data.priority-map.jar aoc2021_day14b.clj-1.clj 0 < aoc2021_day14b-input2.txt
PROGRAM OUTPUT:
2265039461737