~rauhl/advent-of-code

d436062e09c012e7c0269d99a201ba06ca919721 — Robert A. Uhl 1 year, 2 months ago 7205359
Add day 7

For some reason, today was unreasonably difficult.  I clearly need to
spend some more time working with & thinking about graphs.
1 files changed, 160 insertions(+), 0 deletions(-)

A 2018-12-07.lisp
A 2018-12-07.lisp => 2018-12-07.lisp +160 -0
@@ 0,0 1,160 @@
(defpackage "AOC/7" (:use "CL"))
(in-package "AOC/7")

(defvar *input* "Step O must be finished before step W can begin.
Step S must be finished before step V can begin.
Step Z must be finished before step B can begin.
Step F must be finished before step R can begin.
Step I must be finished before step D can begin.
Step W must be finished before step P can begin.
Step J must be finished before step E can begin.
Step P must be finished before step N can begin.
Step Q must be finished before step V can begin.
Step D must be finished before step K can begin.
Step X must be finished before step N can begin.
Step E must be finished before step B can begin.
Step L must be finished before step H can begin.
Step A must be finished before step T can begin.
Step U must be finished before step R can begin.
Step M must be finished before step T can begin.
Step V must be finished before step R can begin.
Step N must be finished before step C can begin.
Step T must be finished before step C can begin.
Step Y must be finished before step B can begin.
Step H must be finished before step B can begin.
Step B must be finished before step C can begin.
Step C must be finished before step K can begin.
Step R must be finished before step K can begin.
Step G must be finished before step K can begin.
Step Q must be finished before step K can begin.
Step U must be finished before step Y can begin.
Step L must be finished before step G can begin.
Step S must be finished before step D can begin.
Step E must be finished before step R can begin.
Step Z must be finished before step M can begin.
Step U must be finished before step K can begin.
Step Q must be finished before step H can begin.
Step T must be finished before step B can begin.
Step J must be finished before step Q can begin.
Step X must be finished before step V can begin.
Step Q must be finished before step U can begin.
Step T must be finished before step K can begin.
Step S must be finished before step B can begin.
Step L must be finished before step C can begin.
Step Q must be finished before step D can begin.
Step E must be finished before step K can begin.
Step N must be finished before step G can begin.
Step L must be finished before step T can begin.
Step E must be finished before step L can begin.
Step A must be finished before step N can begin.
Step V must be finished before step C can begin.
Step D must be finished before step L can begin.
Step O must be finished before step S can begin.
Step V must be finished before step Y can begin.
Step N must be finished before step T can begin.
Step I must be finished before step H can begin.
Step U must be finished before step N can begin.
Step O must be finished before step Y can begin.
Step J must be finished before step C can begin.
Step Y must be finished before step C can begin.
Step W must be finished before step A can begin.
Step M must be finished before step C can begin.
Step X must be finished before step E can begin.
Step S must be finished before step J can begin.
Step U must be finished before step C can begin.
Step H must be finished before step K can begin.
Step Q must be finished before step B can begin.
Step E must be finished before step G can begin.
Step N must be finished before step H can begin.
Step I must be finished before step J can begin.
Step P must be finished before step B can begin.
Step Z must be finished before step T can begin.
Step J must be finished before step M can begin.
Step C must be finished before step G can begin.
Step I must be finished before step B can begin.
Step D must be finished before step G can begin.
Step X must be finished before step T can begin.
Step O must be finished before step F can begin.
Step A must be finished before step Y can begin.
Step S must be finished before step G can begin.
Step X must be finished before step K can begin.
Step L must be finished before step M can begin.
Step A must be finished before step H can begin.
Step D must be finished before step H can begin.
Step U must be finished before step T can begin.
Step B must be finished before step K can begin.
Step S must be finished before step C can begin.
Step W must be finished before step R can begin.
Step M must be finished before step G can begin.
Step M must be finished before step H can begin.
Step J must be finished before step D can begin.
Step W must be finished before step Y can begin.
Step S must be finished before step Y can begin.
Step A must be finished before step G can begin.
Step P must be finished before step M can begin.
Step C must be finished before step R can begin.
Step Q must be finished before step Y can begin.
Step O must be finished before step H can begin.
Step O must be finished before step R can begin.
Step Q must be finished before step M can begin.
Step V must be finished before step B can begin.
Step H must be finished before step G can begin.
Step J must be finished before step V can begin.
Step M must be finished before step R can begin.
Step R must be finished before step G can begin.")

(defun parse-rule (stream)
  (let ((line (read-line stream nil)))
    (when line
      (assert (string= (subseq line 0 5) "Step "))
      (assert (string= (subseq line 6 36) " must be finished before step "))
      (assert (string= (subseq line 37) " can begin."))
      (list (aref line 36) (aref line 5)))))

(defun parse-rules (stream)
  (loop for rule = (parse-rule stream)
        while rule
        collect rule))

(let ((rules (with-input-from-string (s *input*) (parse-rules s))))
  (loop for next = (first (sort (remove-duplicates (loop for (target dep) in rules unless (find dep rules :key #'first) collect dep)) #'char<))
        while next
        do (format t "~a" next)
        do (setf rules (remove next rules :key #'second))))
;; The above doesn’t print the last character, and it’s not generally
;; correct (what happens if more than one target is unlocked at a
;; time?), but for our purposes it works.  The final target is K

(let ((deps (make-hash-table))
      (rules (with-input-from-string (s *input*) (parse-rules s)))
      (num-workers 5)
      targets
      working
      (done (make-hash-table)))
  (loop for (target dep) in rules
        do (push dep (gethash target deps))
        do (pushnew target targets)
        do (pushnew dep targets))
  (loop for time from 0
        while (and (or targets working) (< time 10000))
        do (setf working (loop for (task remaining) in working
                               if (= remaining 1)
                                 do (progn
                                      (incf num-workers)
                                      (setf (gethash task done) t)
                                      (loop for k being the hash-keys of deps using (hash-value v)
                                            do (setf (gethash k deps) (remove task v))))
                               else
                                 collect (list task (1- remaining))))
        do (loop for next in (sort (loop for target in targets
                                         unless (or (gethash target deps)
                                                    (gethash target done)
                                                    (find target working :key #'first))
                                           collect target)
                                   #'char<)
                 while (and next (plusp num-workers))
                 do (progn
                      (push (list next (+ (char-code next) -64 60)) working)
                      (decf num-workers)
                      (setf targets (remove next targets))))
        do (format t "~&~a: ~a~%" time working)))