(defun 03/parse-bin-char (x) (case x (#\1 1) (#\0 0))) (defun 03/parse-bin-char-inv (x) (case x (1 #\1) (0 #\0))) ;; Turn the input file into whatever form you will use for both parts ;; (get-file-lines) and (get-file-string) will be useful (defun 03/parse-input-direct (input) (mapcar (lambda (x) (mapcar #'03/parse-bin-char (coerce x 'list))) input)) (defun 03/parse-input (input-file) (03/parse-input-direct (get-file-lines input-file))) (defun 03/is-more (h l) (mapcar (lambda (x) (if (< x h) 0 1)) l)) (defun 03/is-less (h l) (mapcar (lambda (x) (if (>= x h) 0 1)) l)) (defun 03/not-list (l) (mapcar (lambda (x) (if (= x 0) 1 0)) l)) (defun 03/to-dec (l) (parse-integer (coerce (mapcar #'03/parse-bin-char-inv l) 'string) :radix 2)) (defun 03/find-most-common (parsed-input) (let ((half-length (/ (list-length parsed-input) 2))) (03/is-more half-length (apply (partial #'mapcar #'+) parsed-input)))) (defun 03/find-least-common (parsed-input) (let ((half-length (/ (list-length parsed-input) 2))) (03/is-less half-length (apply (partial #'mapcar #'+) parsed-input)))) (defun 03/part-a (parsed-input) (let* ((l (03/find-most-common parsed-input)) (gamma (03/to-dec l)) (epsilon (03/to-dec (03/not-list l)))) (* epsilon gamma))) (defun 03/recursive-b (f input out) (if (member nil input) out (let* ((common (car (funcall f input))) (rest-tmp (mapcar #'cdr (remove-if-not (lambda (x) (equalp (car x) common)) input))) (rest (if rest-tmp rest-tmp (progn (setf common (car (car input))) (mapcar #'cdr input))))) (03/recursive-b f rest (append out (list common)))))) (defun 03/part-b (parsed-input) (* (03/to-dec (03/recursive-b #'03/find-most-common parsed-input nil)) (03/to-dec (03/recursive-b #'03/find-least-common parsed-input nil))))