~shunter/advent2021

81cc4884a8bf0623e19b4c88904ce0f2049781d3 — Samuel Hunter 2 years ago b3e9b4b
Solve Day 14
2 files changed, 186 insertions(+), 0 deletions(-)

A day14.lisp
A input/day14.txt
A day14.lisp => day14.lisp +84 -0
@@ 0,0 1,84 @@
(defpackage #:advent2021.day14
  (:use #:cl #:alexandria #:cl-ppcre #:advent2021.util)
  (:export #:solve-part-1 #:solve-part-2))

(in-package #:advent2021.day14)



(with-puzzle-file (stream)
  (defparameter +template+
    (read-line stream))
  (read-line stream)
  (defparameter +rules+
    (loop :with table := (make-hash-table :test 'equal)
          :for line := (read-line stream nil)
          :while line
          :for (pair result) := (split " -> " line)
          :for (a b) := (coerce pair 'list)
          :do (setf (gethash (cons a b) table) (char result 0))
          :finally (return table))))

(defparameter +input+
  (parse-lines #'identity))

(defun insert-pairs (template)
  (with-output-to-string (out)
    (loop :for (a b) :on (coerce template 'list)
          :while b
          :do (write-char a out)
              (write-char (gethash (cons a b) +rules+) out)
          :finally (write-char a out))))

(defun count-elements (template)
  (loop :with dict := (make-hash-table)
        :for elem :across template
        :do (incf (gethash elem dict 0))
        :finally (return dict)))

(defun freq-difference (dict)
  (loop :for elem :being :the :hash-keys :of dict
        :using (hash-value count)
        :maximize count :into highest
        :minimize count :into lowest
        :finally (return (- highest lowest))))

(defun solve-part-1 ()
  (loop :with template := +template+
        :repeat 10
        :do (setf template (insert-pairs template))
        :finally (return (freq-difference (count-elements template)))))

(defun template-table (template)
  (loop :with table := (make-hash-table :test 'equal)
        :for (a b) :on (coerce template 'list)
        :while b
        :do (incf (gethash (cons a b) table 0))
        :finally (return table)))

(defun insert-pairs* (template-table)
  (loop :with next-generation := (make-hash-table :test 'equal)
        :for (a . b) :being :the :hash-keys :of template-table
        :using (hash-value count)
        :for c := (gethash (cons a b) +rules+)
        :do (incf (gethash (cons a c) next-generation 0) count)
            (incf (gethash (cons c b) next-generation 0) count)
        :finally (return next-generation)))

(defun count-elements* (template-table)
  (loop :with freq-dict := (make-hash-table)
        :with template := (coerce +template+ 'list)
        :for (a . b) :being :the :hash-keys :of template-table
        :using (hash-value count)
        :do (incf (gethash a freq-dict 0) (/ count 2))
            (incf (gethash b freq-dict 0) (/ count 2))
        :finally (progn
                   (incf (gethash (first template) freq-dict) 1/2)
                   (incf (gethash (car (last template)) freq-dict) 1/2)
                   (return freq-dict))))

(defun solve-part-2 ()
  (loop :with template := (template-table +template+)
        :repeat 40
        :do (setf template (insert-pairs* template))
        :finally (return (freq-difference (count-elements* template)))))

A input/day14.txt => input/day14.txt +102 -0
@@ 0,0 1,102 @@
VPPHOPVVSFSVFOCOSBKF

CO -> B
CV -> N
HV -> H
ON -> O
FS -> F
NS -> S
VK -> C
BV -> F
SC -> N
NV -> V
NC -> F
NH -> B
BO -> K
FC -> H
NB -> H
HO -> F
SB -> N
KP -> V
OS -> C
OB -> P
SH -> N
BC -> H
CK -> H
SO -> N
SP -> P
CF -> P
KV -> F
CS -> V
FF -> P
VS -> V
CP -> S
PH -> V
OP -> K
KH -> B
FB -> S
CN -> H
KS -> P
FN -> O
PV -> O
VC -> S
HF -> N
OC -> O
PK -> V
KC -> C
HK -> C
PO -> N
OO -> S
VH -> N
CC -> K
BP -> K
HC -> K
FV -> K
KF -> V
VF -> C
HN -> S
VP -> B
HH -> O
FO -> O
PC -> N
KK -> C
PN -> P
NN -> C
FH -> N
VV -> O
OK -> V
CB -> N
SN -> H
VO -> H
BB -> C
PB -> F
NF -> P
KO -> S
PP -> K
NO -> O
SF -> N
KN -> S
PS -> O
VN -> V
SS -> N
BF -> O
HP -> H
HS -> N
BS -> S
VB -> F
PF -> K
SV -> V
BH -> P
FP -> O
CH -> P
OH -> K
OF -> F
HB -> V
FK -> V
BN -> V
SK -> F
OV -> C
NP -> S
NK -> S
BK -> C
KB -> F