# HG changeset patch # User Steve Losh # Date 1638641485 18000 # Node ID 77fa6a483e0e8f72fd262bb93387311ea15c49d7 # Parent a1c5d160d73892b77f62066e0566bbc5367f9b1b 2021/04 diff -r a1c5d160d738 -r 77fa6a483e0e advent.asd --- a/advent.asd Fri Dec 03 12:43:45 2021 -0500 +++ b/advent.asd Sat Dec 04 13:11:25 2021 -0500 @@ -33,6 +33,7 @@ :md5 :named-readtables :pileup + :safe-read :split-sequence :str diff -r a1c5d160d738 -r 77fa6a483e0e data/2021/04.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/data/2021/04.txt Sat Dec 04 13:11:25 2021 -0500 @@ -0,0 +1,601 @@ +31,50,68,16,25,15,28,80,41,8,75,45,96,9,3,98,83,27,62,42,59,99,95,13,55,10,23,84,18,76,87,56,88,66,1,58,92,89,19,54,85,74,39,93,77,26,30,52,69,48,91,73,72,38,64,53,32,51,6,29,17,90,34,61,70,4,7,57,44,97,82,37,43,14,81,65,11,22,5,36,71,35,78,12,0,94,47,49,33,79,63,86,40,21,24,46,20,2,67,60 + +95 91 54 75 45 +46 94 39 44 85 +31 43 24 2 70 +90 58 4 30 77 +13 26 38 52 34 + +68 14 99 63 46 +67 16 82 10 8 +55 52 41 51 4 +90 17 32 44 74 +89 94 73 56 36 + + 6 91 2 28 71 + 7 88 37 21 36 +95 32 84 57 8 +13 79 89 75 48 +47 81 66 17 5 + +44 55 48 16 41 +35 5 43 53 11 + 0 79 19 82 49 +30 85 31 72 39 +27 68 65 66 95 + + 6 46 55 24 40 +87 16 62 11 64 + 8 49 18 59 91 +72 28 48 19 96 +39 73 9 88 0 + +46 1 18 93 6 +50 96 41 81 58 +62 66 49 32 55 +29 11 65 2 10 +71 30 17 69 43 + +84 57 6 56 95 +39 15 32 1 10 +55 43 40 3 22 +89 54 13 80 38 +72 12 59 71 77 + + 3 51 72 88 6 +56 64 99 82 36 +75 81 42 67 24 +41 79 35 40 73 + 2 14 61 50 87 + +72 7 0 99 24 +29 81 92 74 38 +84 53 20 56 91 +93 64 44 48 2 +37 40 88 96 97 + +39 87 99 75 38 +45 81 46 72 62 +40 8 24 67 79 +96 1 77 73 70 +34 13 55 83 59 + +18 38 55 84 58 +35 97 31 26 44 +80 1 28 71 85 +45 46 10 32 99 +60 48 72 11 53 + +53 44 6 30 82 +65 64 10 0 86 +81 50 5 21 60 +16 19 97 66 73 +20 24 96 68 69 + +33 85 88 58 20 +19 2 99 40 70 +69 10 17 67 23 +48 9 29 34 3 +89 30 43 41 94 + +30 83 37 14 78 +57 42 98 90 28 + 5 82 51 15 55 +77 79 96 67 53 +22 76 0 59 47 + +10 93 84 54 11 +59 30 6 94 75 + 9 62 68 37 24 +61 3 66 58 74 +64 0 83 32 13 + +24 77 15 5 49 +23 11 70 17 10 +62 33 38 36 12 + 3 61 0 26 65 +63 47 54 50 9 + +34 28 24 55 38 +69 37 36 32 72 +91 85 9 64 68 +94 22 96 90 82 +30 20 97 19 56 + +35 90 58 93 2 +72 8 27 88 16 +25 54 69 60 61 + 1 15 9 71 78 +89 42 46 57 91 + +43 38 47 1 82 +19 32 2 95 51 +78 74 91 10 22 +80 77 33 60 14 + 0 98 70 54 50 + +71 94 3 84 31 +10 59 12 28 46 +68 69 13 48 36 +37 49 24 26 61 +72 65 38 16 25 + +68 78 10 90 29 +40 14 45 43 44 +27 75 72 39 87 +96 93 53 12 11 +37 64 56 59 76 + +19 78 84 68 41 +36 96 87 15 55 +47 33 10 91 85 +11 94 31 49 35 +83 63 86 4 76 + + 5 89 55 46 96 +67 22 95 82 56 +61 94 84 99 28 +71 70 16 57 63 +98 92 86 73 83 + +56 24 93 88 29 +74 89 50 44 79 +97 49 87 31 8 +70 6 57 3 82 +20 25 99 48 78 + +80 20 45 22 57 +43 35 48 44 52 +29 98 38 27 11 +64 49 84 60 31 + 7 97 17 85 74 + +21 1 18 41 62 +76 38 13 46 27 + 0 16 43 28 53 +54 42 22 83 20 + 4 25 50 11 56 + +21 71 73 30 51 +92 27 14 16 11 +89 43 38 62 31 +65 4 36 84 94 +56 13 59 22 6 + +46 28 45 57 6 +16 67 33 20 44 +36 86 92 3 11 +98 27 26 84 31 + 5 76 13 65 25 + +49 55 99 31 73 +80 0 83 26 65 + 3 96 60 37 50 +57 34 7 20 23 +70 52 93 13 71 + +78 41 81 32 76 +37 36 16 99 48 + 3 93 33 85 35 +60 38 74 80 56 +86 29 87 20 7 + +98 24 4 9 82 +22 37 52 81 30 +51 70 17 23 8 +60 61 75 35 85 +33 48 88 13 57 + +49 52 91 21 46 +90 51 70 5 35 +57 68 31 86 87 +42 36 25 95 3 +73 64 17 96 80 + + 6 42 13 16 24 +51 72 55 78 47 +67 28 7 97 64 +44 77 98 71 25 +82 8 31 76 73 + +63 79 18 80 27 +57 66 47 89 14 +15 61 94 38 29 +21 53 73 17 76 +65 7 23 36 3 + +93 22 8 52 4 +63 31 90 46 68 +51 14 95 50 23 +17 34 60 75 36 +88 55 7 0 73 + +42 67 91 15 83 + 1 37 76 12 25 +29 82 50 70 86 +74 66 39 90 16 +31 71 47 5 92 + +98 48 27 87 2 +60 0 25 30 14 +44 61 94 82 16 +17 19 53 49 59 +15 85 50 63 8 + +63 12 52 81 97 +87 68 44 31 41 +39 24 99 27 6 + 1 21 35 59 51 + 4 92 3 90 62 + +66 43 98 25 47 +59 16 75 44 82 +40 58 48 60 37 +13 81 61 45 83 +24 89 93 19 67 + + 8 86 47 81 83 + 1 91 57 59 68 + 0 52 25 93 95 +27 84 63 45 36 +39 62 20 99 88 + +67 28 65 4 17 +44 33 12 99 84 +27 36 34 5 10 +38 63 97 82 64 +94 19 58 41 6 + +28 41 96 16 39 +93 78 56 69 75 +74 60 9 30 7 +12 81 35 84 94 +45 20 6 49 2 + +33 7 5 43 9 +97 65 50 2 1 +26 86 76 47 98 +83 31 30 58 52 +93 51 34 63 12 + +65 81 10 46 59 +51 89 85 2 52 +13 54 18 70 4 +37 94 75 92 56 +58 99 91 32 41 + +44 23 18 16 75 + 5 3 45 76 90 +20 71 69 37 99 +49 91 43 32 82 + 4 79 51 2 39 + +54 80 71 61 76 +81 52 6 89 34 +58 14 20 26 40 +25 60 45 0 3 +36 33 65 41 94 + +53 23 56 55 92 + 3 81 59 0 35 +32 30 93 70 40 +45 91 24 65 6 +95 88 16 47 8 + +24 23 10 47 63 +38 79 18 77 62 +13 88 72 68 36 +96 27 12 69 89 +28 94 6 98 20 + +70 1 61 77 28 +92 22 30 48 96 +66 3 34 29 45 +85 6 17 87 5 +97 89 14 80 20 + +40 86 97 5 54 +91 57 12 19 7 +62 88 92 20 32 +50 77 11 39 22 +33 2 21 95 35 + +51 79 64 24 28 +95 19 82 58 76 +69 30 9 14 42 +27 16 56 80 83 +52 5 49 43 45 + +26 65 68 18 55 +58 83 30 48 4 +69 42 78 96 22 +91 13 82 38 41 +67 33 10 98 53 + +74 97 43 1 18 +49 30 28 10 15 +42 12 80 20 96 +41 92 67 22 36 + 5 26 13 47 4 + +85 60 72 19 48 +61 21 43 34 83 +51 75 94 11 78 +27 89 45 49 79 +97 15 5 28 50 + +69 99 97 77 98 +37 80 86 7 34 +85 28 31 23 16 +32 47 8 40 4 +46 91 71 54 74 + +23 43 29 7 21 +58 34 42 4 38 +64 96 16 73 49 +36 92 52 81 31 +85 71 78 13 5 + +65 71 46 5 11 +24 4 6 0 23 +13 17 76 15 34 +27 79 10 56 85 +90 19 30 94 78 + +81 40 65 12 35 +23 93 24 96 53 +27 60 87 59 33 +76 56 4 17 6 +78 49 90 3 80 + + 7 25 42 85 39 +40 6 26 11 63 +48 20 62 61 89 +78 15 18 21 53 +69 4 87 47 5 + +38 65 87 72 26 +88 75 10 30 3 +89 58 7 20 32 +85 2 97 63 15 +28 77 82 57 64 + +16 89 6 31 27 +45 69 61 5 15 +40 75 64 94 98 +36 18 26 58 90 +10 44 59 13 67 + +80 13 39 49 42 +50 94 12 14 88 +97 48 15 68 69 +21 18 51 99 91 +89 64 35 63 84 + +81 96 26 43 30 + 5 74 9 93 60 +63 41 1 14 22 + 4 77 33 53 3 +38 90 50 25 10 + +58 66 17 0 16 + 5 67 41 48 40 +43 93 76 95 68 + 4 13 14 51 8 +56 74 23 57 94 + +18 15 92 4 20 +69 26 84 23 2 +72 35 56 96 9 +61 41 85 91 25 +13 70 1 14 77 + +15 20 77 80 47 +45 34 63 55 75 +65 12 66 44 22 +74 3 25 38 93 + 9 31 68 87 67 + +54 95 79 50 75 +18 36 20 34 43 +17 65 55 98 61 +27 46 56 6 52 +91 31 30 40 0 + +25 30 24 64 98 + 8 72 53 45 3 +27 77 0 33 44 +89 39 34 71 38 +54 21 20 80 23 + +69 38 63 60 4 +55 37 83 68 61 +67 25 86 24 18 +22 59 65 28 70 +84 46 44 91 96 + +35 27 65 31 0 +46 97 44 74 4 +56 61 7 49 88 + 5 38 50 20 26 +62 9 45 64 51 + + 3 28 43 97 7 +88 57 17 82 73 +16 94 74 22 39 +84 99 31 1 47 +92 91 55 38 78 + +60 31 29 49 72 +89 41 5 79 22 +58 28 90 76 95 +93 45 14 47 37 +65 25 7 59 62 + +58 1 73 30 55 +95 46 5 80 63 +52 16 70 20 71 +84 60 15 0 77 +99 89 17 72 31 + +83 21 68 18 42 + 1 28 97 31 35 + 2 38 67 63 74 +77 27 48 90 86 +12 52 26 29 60 + +81 53 80 85 96 +19 32 31 15 88 +91 92 66 37 34 +74 75 33 39 78 +42 40 30 83 58 + +40 41 80 69 67 +24 63 97 33 5 +28 84 34 72 11 +36 79 91 14 92 +55 89 59 10 44 + + 0 51 49 24 60 +48 65 28 70 66 +86 58 78 77 18 + 6 44 50 37 36 + 4 73 91 97 43 + +66 42 76 12 48 +77 83 35 18 50 +30 87 95 99 11 + 0 52 92 16 51 +26 56 39 64 62 + +83 89 52 61 45 +74 77 66 59 30 +85 17 38 10 8 +97 67 54 21 26 +34 63 11 94 40 + +93 91 14 49 38 +77 53 29 36 39 +12 52 0 48 92 +95 82 71 76 37 +19 70 75 9 74 + +80 49 59 67 27 +43 66 97 81 12 +10 77 24 75 68 +16 57 14 28 85 +41 52 23 15 2 + +39 89 66 27 11 +63 84 21 44 69 +56 51 58 70 83 +14 0 8 41 31 +98 18 61 97 74 + +97 18 63 29 24 +75 73 80 8 7 +81 37 46 93 68 +57 32 2 41 5 + 4 65 88 45 54 + +87 26 81 12 50 +19 9 68 23 71 +74 38 4 34 16 +18 99 86 45 7 +35 8 11 98 57 + +13 31 78 59 58 +51 61 96 68 44 +41 85 26 55 92 +11 62 30 7 64 +18 19 73 27 17 + +48 85 71 39 29 +33 79 24 0 72 +95 52 12 77 40 +70 31 46 44 43 +61 88 73 49 65 + +60 81 51 24 27 +23 28 47 85 67 +35 57 45 76 84 +19 48 30 37 74 +15 78 56 87 16 + +12 5 45 26 21 + 1 71 51 10 25 +37 68 73 46 56 +55 20 63 87 91 +22 32 66 90 19 + +20 59 12 29 97 +92 30 77 27 49 +14 98 23 50 6 +11 47 61 34 36 +55 82 13 22 21 + +29 37 0 40 71 + 2 43 97 18 59 +32 72 89 99 24 +58 90 73 60 85 +69 53 95 78 27 + +58 28 32 52 55 +86 33 1 41 60 + 8 53 42 92 5 +43 69 96 54 24 +74 10 17 89 85 + +51 74 99 21 64 +54 27 60 32 37 +14 45 50 81 94 +28 11 77 17 23 +93 95 53 57 79 + +16 5 80 45 71 +22 57 9 90 43 + 3 52 47 59 84 +28 53 14 15 7 +50 76 46 56 34 + +83 62 77 56 26 +82 35 11 6 51 +96 97 15 1 78 +92 45 55 84 94 +20 8 70 21 31 + + 4 47 68 81 12 +66 23 35 8 39 +73 94 27 69 22 +59 11 53 26 99 + 7 20 87 60 88 + +90 0 88 81 43 +47 54 42 29 97 +60 13 85 51 71 +56 14 94 80 41 +75 8 35 69 61 + +51 38 40 17 42 +19 26 92 64 67 +33 66 82 27 55 +62 2 68 59 31 + 7 24 20 91 79 + +21 83 45 35 88 +85 11 5 86 72 +78 3 58 0 89 +67 1 39 59 63 +79 87 19 4 57 + +25 16 40 17 27 +96 72 29 32 87 +50 63 35 81 66 + 7 11 92 68 69 +54 83 12 51 95 + +64 98 67 54 75 + 8 10 31 5 57 +89 23 25 34 47 +72 74 37 48 94 +39 59 15 55 87 diff -r a1c5d160d738 -r 77fa6a483e0e package.lisp --- a/package.lisp Fri Dec 03 12:43:45 2021 -0500 +++ b/package.lisp Sat Dec 04 13:11:25 2021 -0500 @@ -3,18 +3,21 @@ (:export :define-problem + :read-2d-array :read-all + :read-and-collect + :read-before + :read-chunks + :read-comma-separated-values + :read-digits :read-lines + :read-lines-of-numbers-and-garbage :read-lines-of-words - :read-lines-of-numbers-and-garbage :read-numbers :read-numbers-from-string - :read-comma-separated-values - :read-2d-array - :read-before :read-to - :read-digits - :read-chunks + :read-word + :with-eof-handled :ensure-string :ensure-stream @@ -87,9 +90,11 @@ :print-hash-table-map :print-2d-array + :bold :clear :green :reset + :underline :mkinput diff -r a1c5d160d738 -r 77fa6a483e0e src/2021/days/day-03.lisp --- a/src/2021/days/day-03.lisp Fri Dec 03 12:43:45 2021 -0500 +++ b/src/2021/days/day-03.lisp Sat Dec 04 13:11:25 2021 -0500 @@ -2,6 +2,7 @@ (in-package :advent/2021/03) (defun-inline bool->bit (b) (if b 1 0)) + (defun-inline char->δ (ch) (ecase ch (#\0 -1) (#\1 1))) (defun count-bits (data) diff -r a1c5d160d738 -r 77fa6a483e0e src/2021/days/day-04.lisp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/2021/days/day-04.lisp Sat Dec 04 13:11:25 2021 -0500 @@ -0,0 +1,100 @@ +(advent:defpackage* :advent/2021/04) +(in-package :advent/2021/04) + + +(defun cell (num) (cons num nil)) +(defun num (cell) (car cell)) +(defun markedp (cell) (cdr cell)) +(defun unmarkedp (cell) (not (markedp cell))) +(defun mark (cell) (setf (cdr cell) t)) + +(defun read-bingo-numbers (stream) + (read-numbers-from-string (read-line stream))) + +(defun read-board (&optional (stream *standard-input*) (eof-error-p t) eof-value) + (peek-char t stream nil) + (with-eof-handled (stream eof-error-p eof-value) + (do-array (v (make-array '(5 5))) + (setf v (cell (parse-integer (read-word stream))))))) + +(defun parse (stream) + (values (read-bingo-numbers stream) + (read-and-collect stream #'read-board))) + +(defun copy-board (board) + (do-array (cell (alexandria:copy-array board)) + (setf cell (cons (car cell) (cdr cell))))) + +(defun print-board (board) + (print-2d-array board :printer (lambda (cell) + (when (markedp cell) (green) (bold)) + (format t "~3D" (num cell)) + (when (markedp cell) (reset))))) + + +(defun print-boards (boards &optional heading) + (when heading (write-line heading)) + (dolist (board boards) + (print-board board) + (terpri))) + +(defun mark-number-on-board (n board) + (do-array (cell board) + (when (= n (num cell)) + (return (mark cell))))) + +(defun mark-number-on-boards (n boards) + (dolist (board boards) + (mark-number-on-board n board))) + +(defun winning-row-p (board row) + (iterate (for col :below 5) (always (markedp (aref board row col))))) + +(defun winning-col-p (board col) + (iterate (for row :below 5) (always (markedp (aref board row col))))) + +(defun winning-board-p (board) + (or (iterate (for row :below 5) (thereis (winning-row-p board row))) + (iterate (for col :below 5) (thereis (winning-col-p board col))))) + +(defun play-first (numbers boards) + (iterate + (with boards = (mapcar #'copy-board boards)) + (for n :in numbers) + (mark-number-on-boards n boards) + (dolist (board boards) + (when (winning-board-p board) + (return-from play-first (values n board)))))) + +(defun play-last (numbers boards) + (iterate + (with boards = (mapcar #'copy-board boards)) + (for n :in numbers) + (mark-number-on-boards n boards) + (if (null (rest boards)) + (when (winning-board-p (first boards)) ;; Run last board to completion. + (return-from play-last (values n (first boards)))) + (setf boards (delete-if #'winning-board-p boards))))) ;; Still pruning boards. + +(defun unmarked-sum (board) + (iterate (for cell :across-flat-array board) + (when (unmarkedp cell) + (summing (num cell))))) + +(defun score (last-number board) + (* last-number (unmarked-sum board))) + +(define-problem (2021 4) (data) (49860 24628) + (multiple-value-bind (numbers boards) (parse data) + (values + (multiple-value-call #'score (play-first numbers boards)) + (multiple-value-call #'score (play-last numbers boards))))) + + + + + + + + +#; Scratch -------------------------------------------------------------------- diff -r a1c5d160d738 -r 77fa6a483e0e src/utils.lisp --- a/src/utils.lisp Fri Dec 03 12:43:45 2021 -0500 +++ b/src/utils.lisp Sat Dec 04 13:11:25 2021 -0500 @@ -73,6 +73,10 @@ ;;;; Readers ------------------------------------------------------------------ +(alexandria:define-constant +whitespace-chars+ + '(#\Space #\Newline #\Backspace #\Tab #\Linefeed #\Page #\Return #\Rubout) + :test #'equal) + (defun read-numbers-from-string (line) (mapcar #'parse-integer (ppcre:all-matches-as-strings "-?\\d+" line))) @@ -81,6 +85,14 @@ (collect value))) +(defmacro with-eof-handled ((stream eof-error-p eof-value) &body body) + (once-only (stream eof-error-p eof-value) + `(if (null (peek-char nil ,stream nil)) + (if ,eof-error-p + (error 'end-of-file) + ,eof-value) + (progn ,@body)))) + (defun read-before (char &optional (discard-delimiter t) (stream *standard-input*) (eof-error-p t) eof-value) "Read characters from `stream` up to, but *not* including, `char`. @@ -94,10 +106,7 @@ invocation). " - (if (null (peek-char nil stream nil)) - (if eof-error-p - (error 'end-of-file) - eof-value) + (with-eof-handled (stream eof-error-p eof-value) (iterate (for c = (peek-char nil stream nil)) (until (null c)) @@ -117,16 +126,27 @@ invocation). " - (if (null (peek-char nil stream nil)) - (if eof-error-p - (error 'end-of-file) - eof-value) + (with-eof-handled (stream eof-error-p eof-value) (iterate (for c = (peek-char nil stream nil)) (until (null c)) (collect (read-char stream) :result-type 'string) (until (char= char c))))) +(defun read-word (&optional (stream *standard-input*) (eof-error-p t) eof-value) + "Read the next word from `stream` and return it as a string. + + A word is a sequence of non-whitespace characters. Leading whitespace will be + skipped. + + " + (peek-char t stream nil) + (with-eof-handled (stream eof-error-p eof-value) + (iterate + (for c = (read-char stream nil #\space)) + (until (member c +whitespace-chars+)) + (collect c :result-type 'string)))) + (defun read-all (stream) "Read all forms from `stream` and return them as a fresh list." @@ -139,6 +159,7 @@ "Read all lines from `stream` and return them as a fresh list of strings." (read-and-collect stream #'read-line)) + (defun read-lines-of-numbers-and-garbage (stream) "Read the lines of numbers in `stream` into a list of lists of numbers. @@ -839,18 +860,17 @@ (esc "[2J") (esc "[;H")) -(defun green () - (esc "[32m")) - -(defun reset () - (esc "[0m")) +(defun green () (esc "[32m")) +(defun bold () (esc "[1m")) +(defun underline () (esc "[4m")) +(defun reset () (esc "[0m")) -(defun print-2d-array (array) +(defun print-2d-array (array &key (printer #'princ) (key #'identity)) (destructuring-bind (rows cols) (array-dimensions array) (dotimes (r rows) (dotimes (c cols) - (princ (aref array r c))) + (funcall printer (funcall key (aref array r c)))) (terpri))))