diff --git a/day10.lisp b/day10.lisp index 41062d3..f8d3218 100644 --- a/day10.lisp +++ b/day10.lisp @@ -211,3 +211,106 @@ while line do (parse-command-line line my-machine)) (accumulated-signal my-machine))) + +;;; Cleaning up: +;;; part 1 + +;; state of the CPU +(defclass machine () + ((clock :reader clock :initform 0) + (register :reader register :initform 1) + (accumulated-signal :reader accumulated-signal :initform 0) + (next-special-clock :reader next-special-clock :initform 20))) + +(defmethod print-object ((obj machine) stream) + (print-unreadable-object (obj stream :type t) + (with-accessors ((clock clock ) + (register register ) + (accumulated-signal accumulated-signal) + (next-special-clock next-special-clock)) + obj + (format stream "clock: ~a, register: ~a, accum: ~a; next-special: ~a" clock register accumulated-signal next-special-clock)))) + +;; passing of sinlge step +(defgeneric tick (obj) + (:method ((obj machine)) + (incf (slot-value obj 'clock)) + (when (= (next-special-clock obj) (clock obj)) + (incf (slot-value obj 'accumulated-signal) (* (clock obj) (register obj))) + (update-special-clock obj)))) + +(defgeneric update-special-clock (obj) + (:method ((obj machine)) + (incf (slot-value obj 'next-special-clock) 40))) + +;; actual cpu commands in terms of ticks and register changes: +(defgeneric noop (mach) + (:method ((mach machine)) + (tick mach))) + +(defgeneric addx (mach num) + (:method ((mach machine) num) + (tick mach) + (tick mach) + (incf (slot-value mach 'register) num ))) + +(require 'cl-ppcre) +(defun parse-command-line (line machine) + (let* ((the-split (cl-ppcre:split " " line)) + (command (intern (string-upcase (first the-split))))) + (case command + ('addx (addx machine (parse-integer (second the-split)))) + ('noop (noop machine)) + (t "hello")))) + +;; now it's time to simiulate the file evaluation +(let ((my-machine (make-instance 'machine))) + (with-open-file (in "day10-test.txt") + (loop + for line = (read-line in nil nil) + while line + do (parse-command-line line my-machine)) + (accumulated-signal my-machine))) + +(let ((my-machine (make-instance 'machine))) + (with-open-file (in "day10-input.txt") + (loop + for line = (read-line in nil nil) + while line + do (parse-command-line line my-machine)) + (accumulated-signal my-machine))) + +;;; PART 2 + +(defclass crt (machine) + ((next-special-clock :reader next-special-clock :initform 40))) + +(defun cur-pixel-in-sprite (pixel-index sprite-center) + (and (>= pixel-index (1- sprite-center)) + (<= pixel-index (1+ sprite-center)))) + +(defmethod tick :before ((obj crt)) + (let ((pixel (if (cur-pixel-in-sprite (clock obj) (register obj)) + "#" + "."))) + (format t pixel)) + (when (= (clock obj) (1- (next-special-clock obj))) + (incf (slot-value obj 'register) 40) + (terpri))) + +;; and same code reading in commands, but with CRT results in printing +(let ((my-machine (make-instance 'crt))) + (with-open-file (in "day10-test.txt") + (loop + for line = (read-line in nil nil) + while line + do (parse-command-line line my-machine)) + (accumulated-signal my-machine))) + +(let ((my-machine (make-instance 'crt))) + (with-open-file (in "day10-input.txt") + (loop + for line = (read-line in nil nil) + while line + do (parse-command-line line my-machine)) + (accumulated-signal my-machine)))