summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYann Herklotz <git@yannherklotz.com>2021-12-22 15:02:02 +0100
committerYann Herklotz <git@yannherklotz.com>2021-12-22 15:02:02 +0100
commit475d382b0baaa085910d6066d3a51943e777b147 (patch)
tree8d18ba97d5eb03e0e11ed799211359c4ecd7aa76
parent771f9fdf08671b2673a7b19d7980f15f2288eb26 (diff)
downloadaoc21-475d382b0baaa085910d6066d3a51943e777b147.tar.gz
aoc21-475d382b0baaa085910d6066d3a51943e777b147.zip
Pass the 4th day in AOC
-rw-r--r--src/03.lisp9
-rw-r--r--src/04.lisp64
-rw-r--r--src/common.lisp15
-rw-r--r--test/04.lisp6
-rw-r--r--top.lisp7
5 files changed, 90 insertions, 11 deletions
diff --git a/src/03.lisp b/src/03.lisp
index a9cd314..2a4b2fa 100644
--- a/src/03.lisp
+++ b/src/03.lisp
@@ -10,11 +10,6 @@
(defun 03/parse-input (input-file)
(03/parse-input-direct (get-file-lines input-file)))
-;; Loops through two item windows on input and counts each time the first is less than the second
-(defun 03/partial (func &rest args1)
- (lambda (&rest args2)
- (apply func (append args1 args2))))
-
(defun 03/is-more (h l)
(mapcar (lambda (x) (if (< x h) 0 1)) l))
@@ -29,11 +24,11 @@
(defun 03/find-most-common (parsed-input)
(let ((half-length (/ (list-length parsed-input) 2)))
- (03/is-more half-length (apply (03/partial #'mapcar #'+) parsed-input))))
+ (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 (03/partial #'mapcar #'+) parsed-input))))
+ (03/is-less half-length (apply (partial #'mapcar #'+) parsed-input))))
(defun 03/part-a (parsed-input)
(let* ((l (03/find-most-common parsed-input))
diff --git a/src/04.lisp b/src/04.lisp
new file mode 100644
index 0000000..33436c2
--- /dev/null
+++ b/src/04.lisp
@@ -0,0 +1,64 @@
+(use-package 'cl-ppcre)
+(use-package 'cl-utilities)
+(use-package 'trivia)
+
+(defun 04/parse-input-direct (input)
+ (let ((in-list (mapcar #'parse-integer (split "," (car input))))
+ (boards (mapcar (lambda (x) (mapcar (lambda (y)
+ (mapcar (lambda (z)
+ (list (parse-integer z) nil)) (split " +" (trim y)))) x))
+ (split-sequence-if (lambda (x) (equalp x "")) (cddr input)))))
+ (list in-list boards)))
+
+(defun 04/parse-input (input-file)
+ (04/parse-input-direct (get-file-lines input-file)))
+
+(defun 04/update-board (num board)
+ (mapcar (lambda (row)
+ (mapcar (lambda (val)
+ (if (equalp num (car val)) (list (car val) t) val))
+ row))
+ board))
+
+(defun rotate (list-of-lists)
+ (apply #'mapcar #'list list-of-lists))
+
+(defun 04/check-rows (row) (every #'cadr row))
+
+(defun 04/check-board (board)
+ (if (or (some #'04/check-rows board)
+ (some #'04/check-rows (rotate board)))
+ board nil))
+
+;; (04/check-board '(((2 t) (3 nil)) ((2 nil) (3 t))))
+;; ==> nil
+
+(defun 04/to-val (v) (if (cadr v) 0 (car v)))
+
+(defun 04/sum-unmarked (board)
+ (apply #'+ (mapcar (compose
+ (partial #'apply #'+)
+ (partial #'mapcar #'04/to-val))
+ board)))
+
+(defun 04/part-a (parsed-input)
+ (let ((inputs (car parsed-input))
+ (boards (cadr parsed-input)))
+ (match (loop :for i :in inputs
+ :do (setf boards (mapcar (partial #'04/update-board i) boards))
+ :when (some #'04/check-board boards)
+ :return (list i (some #'04/check-board boards)))
+ ((list i board)
+ (* i (04/sum-unmarked board))))))
+
+(defun 04/part-b (parsed-input)
+ (let ((inputs (car parsed-input))
+ (boards (cadr parsed-input)))
+ (match (loop :for i :in inputs
+ :do (setf boards (mapcar (partial #'04/update-board i) boards))
+ :when (not (equalp (list-length boards) 1))
+ :do (setf boards (filter (compose #'not #'04/check-board) boards))
+ :when (and (equalp (list-length boards) 1) (04/check-board (car boards)))
+ :return (list i (car boards)))
+ ((list i board)
+ (* i (04/sum-unmarked board))))))
diff --git a/src/common.lisp b/src/common.lisp
index c59ea79..2c56184 100644
--- a/src/common.lisp
+++ b/src/common.lisp
@@ -1,2 +1,17 @@
(defun get-file-lines (name)
(uiop:read-file-lines name))
+
+(defun partial (func &rest args1)
+ (lambda (&rest args2)
+ (apply func (append args1 args2))))
+
+(defun compose (a b)
+ (lambda (&rest args)
+ (funcall a (apply b args))))
+
+(defun filter (func l)
+ (loop :for i :in l :when (funcall func i) :collect i))
+
+(defun trim (input)
+ (string-trim '(#\Space #\Newline #\Backspace #\Tab
+ #\Linefeed #\Page #\Return #\Rubout) input))
diff --git a/test/04.lisp b/test/04.lisp
index cccaf4e..d003649 100644
--- a/test/04.lisp
+++ b/test/04.lisp
@@ -29,14 +29,14 @@
(deftest 04/test-ex-b (04/aoc)
(let ((result (04/part-b (04/parse-input-direct 04/default-input))))
- (assert-equalp 0 result)))
+ (assert-equalp 1924 result)))
(deftest 04/test-a (04/aoc)
(let ((result (04/part-a (04/parse-input "inputs/04.txt"))))
- (assert-equalp 0 result)))
+ (assert-equalp 51776 result)))
(deftest 04/test-b (04/aoc)
(let ((result (04/part-b (04/parse-input "inputs/04.txt"))))
- (assert-equalp 0 result)))
+ (assert-equalp 16830 result)))
(defun 04/run-tests () (run-suite '04/aoc))
diff --git a/top.lisp b/top.lisp
index 4a69a6a..8a6ff40 100644
--- a/top.lisp
+++ b/top.lisp
@@ -8,6 +8,8 @@
(ql:quickload 'uiop :silent t)
(ql:quickload 'cl-ppcre :silent t)
(ql:quickload 'clunit :silent t)
+(ql:quickload 'cl-utilities :silent t)
+(ql:quickload 'trivia :silent t)
(load "src/common.lisp")
@@ -22,4 +24,7 @@
(load "src/03.lisp")
(load "test/03.lisp")
-(defun run-all () (run-suite 'aoc))
+(load "src/04.lisp")
+(load "test/04.lisp")
+
+(defun run-all () (clunit:run-suite 'aoc))