(require :senzill) (use-package :senzill.math) (use-package :senzill.collections) (use-package :senzill.io) (defmacro { (&rest body) (loop for com in body unless (and (symbolp com) (string= com '})) if (string= (car com) 'var) collect (cdr com) into localvars else if (string= (car com) 'fun) collect (cdr com) into localfuncs else collect com into newbody finally (return `(let ,localvars (flet ,localfuncs ,@newbody))))) (defun split-seq (seq &key (delim #\ ) (delim-len 1) (start 0)) (loop for itms = (subseq seq start) then (subseq itms (+ delim-len sppos)) for sppos = (position delim itms) then (position delim itms) collect (subseq itms 0 sppos) while sppos)) ;;;;;;;;; (defparameter +rounds+ 20) ({ (fun monkey-ctor (starting-items operation divisible throw-t throw-f) ({ (var opfun (if (symbolp (second operation)) (lambda (old) (funcall (first operation) old old)) (lambda (old) (funcall (first operation) old (second operation))))) (var testfun (lambda (worry-level) (zerop (% worry-level divisible)))) (list :i starting-items :op opfun :test testfun :t throw-t :f throw-f :insp 0) })) (fun inspect-throw (m mt mf) ({ (setf (first (getf m :i)) (floor (/ (funcall (getf m :op) (first (getf m :i))) 3))) (++1 (getf m :insp)) (if (funcall (getf m :test) (first (getf m :i))) (push-back (pop (getf m :i)) (getf mt :i)) (push-back (pop (getf m :i)) (getf mf :i))) })) (var monkeys '()) (var cmonkey '(() (+ 0) 1 -1 -1)) (ask-for-stream (prog-input) (doread-lines (inpt :read-line-options (prog-input NIL)) (cond ((zerop (length inpt))) ((char= (char inpt 0) #\M) ; Monkey #: (push-back (apply #'monkey-ctor cmonkey) monkeys) (setf cmonkey '())) ((char= (char inpt 2) #\S) ; Starting items: (push-back (map 'list #'parse-integer (split-seq inpt :delim #\, :delim-len 2 :start 18)) cmonkey)) ((char= (char inpt 2) #\O) ; Operation: (push-back (map 'list #'read-from-string (split-seq inpt :start 23)) cmonkey)) ((char= (char inpt 2) #\T) ; Test: (push-back (parse-integer inpt :start 21) cmonkey)) ((char= (char inpt 7) #\t) ; If true: (push-back (parse-integer inpt :start 29) cmonkey)) ((char= (char inpt 7) #\f) ; If false: (push-back (parse-integer inpt :start 30) cmonkey))))) (pop monkeys) (push-back (apply #'monkey-ctor cmonkey) monkeys) (dotimes (r +rounds+) (loop for m in monkeys do (loop for item in (getf m :i) do (inspect-throw m (nth (getf m :t) monkeys) (nth (getf m :f) monkeys)) (print r)))) (print monkeys) })