From b35d0ada0e079991658d147eb81ee4f9ce62f39e Mon Sep 17 00:00:00 2001 From: Matteo Landi Date: Sun, 28 Jan 2024 15:29:10 +0100 Subject: [PATCH] Refactor 2023/16 - Use DEFINE-PROBLEM / DEFINE-TEST - Parse the input once, instead of one per iteration --- package.lisp | 1 + src/2023/day16.lisp | 47 +++++++++++++++------------------------------ src/utils.lisp | 9 +++++++++ 3 files changed, 25 insertions(+), 32 deletions(-) diff --git a/package.lisp b/package.lisp index 5b69ba9..b48c98d 100644 --- a/package.lisp +++ b/package.lisp @@ -21,6 +21,7 @@ :partial-2 :defun/memo :memoizing + :unless-already-seen :with-complex-parts :complex-rotate-cw diff --git a/src/2023/day16.lisp b/src/2023/day16.lisp index 4f6ca6f..87afcf9 100644 --- a/src/2023/day16.lisp +++ b/src/2023/day16.lisp @@ -2,7 +2,7 @@ (in-package :aoc/2023/16) -(defun parse-grid (&optional (strings (uiop:read-file-lines #P"src/2023/day16.txt"))) +(defun parse-grid (&optional (strings (aoc::read-problem-input 2023 16))) (bnd* ((rows (length strings)) (cols (length (first strings))) (map (make-hash-table :test 'equal))) @@ -10,32 +10,18 @@ (doseq ((j ch) (enumerate s)) (setf (gethash (list i j) map) ch))) (list map rows cols))) -#+#:excluded (parse-grid) (defun move-straight (pos dir) (mapcar #'+ pos dir)) (defun rotate-cw (dir) (list (second dir) (- (first dir)))) (defun rotate-ccw (dir) (list (- (second dir)) (first dir))) -(defun total-energy (energized) (count-if #'plusp (hash-table-values energized))) - -(defmacro unless-already-seen ((ht &rest key-parts) &body body) - (with-gensyms (memo key) - `(let ((,memo ,ht) - (,key (list ,@key-parts))) - (unless (gethash ,key ,memo) - (setf (gethash ,key ,memo) t) - (block unless-already-seen - ,@body))))) - (defun radiate (start dir &optional (map (first (parse-grid)))) (bnd* ((energized (make-hash-table :test 'equal)) (seen (make-hash-table :test 'equal))) (labels ((dfs (pos dir &aux (ch (gethash pos map))) (if (not ch) (return-from dfs)) (unless-already-seen (seen pos dir) - (if (> (gethash pos energized 0) 1000) - (return-from dfs)) - (incf (gethash pos energized 0)) + (setf (gethash pos energized) t) (cond ((char= ch #\.) (dfs (move-straight dir pos) dir)) ((char= ch #\\) (bnd1 (dir (if (zerop (first dir)) (rotate-cw dir) @@ -59,21 +45,18 @@ (dfs (move-straight pos dir) dir))) (t (error 'wtf)))))) (dfs start dir) - (total-energy energized)))) -#+#:excluded (radiate (list 0 0) (list 0 1)) -; 8249 + (hash-table-count energized)))) + -(defun part2 (&optional (input (parse-grid)) - &aux (map (first input)) - (rows (second input)) - (cols (third input))) - (looping - (dorange (j 0 cols) - (maximize! (radiate (list 0 j) (list 1 0))) - (maximize! (radiate (list (1- rows) j) (list -1 0)))) - (dorange (i 0 rows) - (maximize! (radiate (list i 0) (list 0 1))) - (maximize! (radiate (list i (1- cols)) (list 0 -1)))))) +(define-solution (2023 16) (input parse-grid) + (destructuring-bind (map rows cols) input + (values (radiate (list 0 0) (list 0 1) map) + (looping + (dorange (j 0 cols) + (maximize! (radiate (list 0 j) (list 1 0) map)) + (maximize! (radiate (list (1- rows) j) (list -1 0) map))) + (dorange (i 0 rows) + (maximize! (radiate (list i 0) (list 0 1) map)) + (maximize! (radiate (list i (1- cols)) (list 0 -1) map))))))) -#+#:excluded (part2) -; 8444 +(define-test (2023 16) (8249 8444)) diff --git a/src/utils.lisp b/src/utils.lisp index d03287a..9ddafe4 100644 --- a/src/utils.lisp +++ b/src/utils.lisp @@ -367,6 +367,15 @@ (block memo ,@body))))))) +(defmacro unless-already-seen ((ht &rest key-parts) &body body) + (with-gensyms (memo key) + `(let ((,memo ,ht) + (,key (list ,@key-parts))) + (unless (gethash ,key ,memo) + (setf (gethash ,key ,memo) t) + (block unless-already-seen + ,@body))))) + ;;;; Math --------------------------------------------------------------------- (defmacro with-complex-parts ((real img) c &body body)