Day 09 in Common Lisp
This commit is contained in:
parent
24189ff4c0
commit
12d25e7b7d
|
@ -0,0 +1,5 @@
|
|||
2199943210
|
||||
3987894921
|
||||
9856789892
|
||||
8767896789
|
||||
9899965678
|
|
@ -0,0 +1,83 @@
|
|||
(ql:quickload "split-sequence")
|
||||
|
||||
(defun read-data (path)
|
||||
(with-open-file (stream path)
|
||||
(loop for line = (read-line stream nil)
|
||||
while line collect line)))
|
||||
|
||||
(defparameter *input-source*
|
||||
(cadr *posix-argv*))
|
||||
|
||||
;; Useful in testing
|
||||
;; (defparameter *input-source* "example_input")
|
||||
;; (defparameter *input-source* "input")
|
||||
|
||||
(defun parse-digit (d)
|
||||
(- (char-code d) (char-code #\0)))
|
||||
|
||||
(defun parse-line (line)
|
||||
(map 'list #'parse-digit line))
|
||||
|
||||
(defun parse-input (lines)
|
||||
(let ((numbers (map 'list #'parse-line lines)))
|
||||
(make-array (list (length numbers) (length (car numbers)))
|
||||
:initial-contents numbers)))
|
||||
|
||||
(defparameter *data* (parse-input (read-data *input-source*)))
|
||||
|
||||
(defun within-grid-p (max-x max-y x y)
|
||||
(and (>= x 0)
|
||||
(< x max-x)
|
||||
(>= y 0)
|
||||
(< y max-y)))
|
||||
|
||||
(defun neighbours (grid x y i j)
|
||||
(loop for (a b) in '((1 0) (-1 0) (0 1) (0 -1))
|
||||
when (within-grid-p x y (+ i a) (+ j b))
|
||||
collect (aref grid (+ i a) (+ j b))))
|
||||
|
||||
(defun local-minimum-p (grid x y i j)
|
||||
(every (lambda (neighbour) (< (aref grid i j) neighbour)) (neighbours grid x y i j)))
|
||||
|
||||
(defun low-points (grid)
|
||||
(destructuring-bind (x y) (array-dimensions grid)
|
||||
(loop for i from 0 below x
|
||||
nconcing
|
||||
(loop for j from 0 below y
|
||||
when (local-minimum-p grid x y i j)
|
||||
collect (list i j)))))
|
||||
|
||||
(defun part1 (grid)
|
||||
(reduce #'+ (mapcar (lambda (coordinate) (1+ (apply #'aref grid coordinate))) (low-points grid))))
|
||||
|
||||
(defun flood (hash grid x y)
|
||||
(destructuring-bind (max-x max-y) (array-dimensions grid)
|
||||
(if (and (not (gethash (list x y) hash))
|
||||
(within-grid-p max-x max-y x y)
|
||||
(/= 9 (aref grid x y)))
|
||||
(progn
|
||||
(setf (gethash (list x y) hash) T)
|
||||
(+ 1
|
||||
(flood hash grid (1+ x) y)
|
||||
(flood hash grid (1- x) y)
|
||||
(flood hash grid x (1+ y))
|
||||
(flood hash grid x (1- y))))
|
||||
0)))
|
||||
|
||||
(defun basin (grid low-point)
|
||||
(let ((hash (make-hash-table :test #'equal)))
|
||||
(flood hash grid (car low-point) (cadr low-point))
|
||||
(hash-table-count hash)))
|
||||
|
||||
(defun part2 (grid)
|
||||
(reduce #'*
|
||||
(subseq (sort (mapcar (lambda (point) (basin grid point))
|
||||
(low-points grid))
|
||||
#'>)
|
||||
0 3)))
|
||||
|
||||
(format t "===== Part 1 =====")
|
||||
(format t "Result: ~A~%~%" (time (part1 *data*)))
|
||||
|
||||
(format t "===== Part 2 =====")
|
||||
(format t "Result: ~A~%" (time (part2 *data*)))
|
Reference in New Issue