|
|
|
;;;; AoC 2020
|
|
|
|
|
|
|
|
(defun read-1 (file)
|
|
|
|
(with-open-file (stream file)
|
|
|
|
(loop for line = (read-line stream nil)
|
|
|
|
while line
|
|
|
|
collect (parse-integer line))))
|
|
|
|
|
|
|
|
(defvar *input-1-0* nil)
|
|
|
|
(setf *input-1-0* (read-1 "inputs/1-0"))
|
|
|
|
(defvar *input-1-1* nil)
|
|
|
|
(setf *input-1-1* (read-1 "inputs/1-1.txt"))
|
|
|
|
|
|
|
|
(defun solve-1-1 (data target)
|
|
|
|
(let ((deficits (map 'list (lambda (n) (- target n)) data)))
|
|
|
|
(reduce #'* (intersection data deficits))))
|
|
|
|
|
|
|
|
(defun make-deficits (list difference)
|
|
|
|
(map 'list (lambda (n) (- difference n)) list))
|
|
|
|
|
|
|
|
|
|
|
|
(defun solve-1-2 (data target)
|
|
|
|
(let ((first-deficits (make-deficits data target)))
|
|
|
|
(reduce #'*
|
|
|
|
(remove-duplicates
|
|
|
|
(mapcan (lambda (n)
|
|
|
|
(intersection (make-deficits data n) data))
|
|
|
|
first-deficits)))))
|
|
|
|
|
|
|
|
(defun solve-1 (data target)
|
|
|
|
(time (progn
|
|
|
|
(print (solve-1-1 data target))
|
|
|
|
(print (solve-1-2 data target)))))
|
|
|
|
|
|
|
|
(defstruct password
|
|
|
|
(pchar)
|
|
|
|
(prange)
|
|
|
|
(word))
|
|
|
|
|
|
|
|
(defun read-2 (file)
|
|
|
|
(with-open-file (stream file)
|
|
|
|
(loop for line = (read-line stream nil)
|
|
|
|
while line
|
|
|
|
collect (let* ((pwlist (split-sequence:split-sequence #\space line))
|
|
|
|
(range (multiple-value-bind (n index)
|
|
|
|
(parse-integer (first pwlist) :junk-allowed t)
|
|
|
|
(list n (parse-integer (first pwlist) :start (1+ index))))))
|
|
|
|
(make-password
|
|
|
|
:pchar (char (second pwlist) 0)
|
|
|
|
:prange range
|
|
|
|
:word (third pwlist))))))
|
|
|
|
|
|
|
|
(defun %solve-2-1 (pw)
|
|
|
|
(let ((n (count (password-pchar pw) (password-word pw))))
|
|
|
|
(and (not (> (first (password-prange pw)) n))
|
|
|
|
(not (< (second (password-prange pw)) n)))))
|
|
|
|
|
|
|
|
(defun %solve-2-2 (pw)
|
|
|
|
(let ((valid 0))
|
|
|
|
(loop for index in (password-prange pw)
|
|
|
|
do (if (eq (password-pchar pw) (elt (password-word pw) (1- index)))
|
|
|
|
(incf valid)))
|
|
|
|
(= valid 1)))
|
|
|
|
|
|
|
|
(defun %solve-2 (data test)
|
|
|
|
(let ((pn 0))
|
|
|
|
(loop for p in data
|
|
|
|
do (if (funcall test p)
|
|
|
|
(incf pn)))
|
|
|
|
pn))
|
|
|
|
|
|
|
|
(defun solve-2 (file)
|
|
|
|
(let ((data (read-2 file)))
|
|
|
|
(time (progn (print (%solve-2 data #'%solve-2-1))
|
|
|
|
(print (%solve-2 data #'%solve-2-2))))))
|
|
|
|
|
|
|
|
(defun read-3 (file)
|
|
|
|
(with-open-file (stream file)
|
|
|
|
(let ((temp-map (loop for line = (read-line stream nil)
|
|
|
|
while line
|
|
|
|
collect line)))
|
|
|
|
(make-array (list (length temp-map) (length (first temp-map)))
|
|
|
|
:initial-contents temp-map
|
|
|
|
:element-type 'character))))
|
|
|
|
|
|
|
|
(defun step-slope (position direction map)
|
|
|
|
(let* ((temp-position (map 'list #'+ direction position))
|
|
|
|
(overflow (map 'list #'> temp-position (array-dimensions map))))
|
|
|
|
(cond ((first overflow) :bottom)
|
|
|
|
((second overflow)
|
|
|
|
(progn (decf (second temp-position) (second (array-dimensions map)))
|
|
|
|
temp-position))
|
|
|
|
(t temp-position))))
|
|
|
|
|
|
|
|
(defun solve-3-1 (direction map)
|
|
|
|
(let ((tree-count 0))
|
|
|
|
(labels ((rec (position)
|
|
|
|
(let ((zero-pos (map 'list #'1- position))
|
|
|
|
(new-pos (step-slope position direction map)))
|
|
|
|
(if (char= (aref map (first zero-pos) (second zero-pos))
|
|
|
|
#\#)
|
|
|
|
(incf tree-count))
|
|
|
|
(unless (eq new-pos :bottom)
|
|
|
|
(rec new-pos)))))
|
|
|
|
(rec '(1 1))
|
|
|
|
tree-count)))
|
|
|
|
|
|
|
|
;; (height width)
|
|
|
|
|
|
|
|
(defun solve-3-2 (slopes map)
|
|
|
|
(reduce #'* (loop for slope in slopes
|
|
|
|
collecting (solve-3-1 slope map))))
|
|
|
|
|
|
|
|
(defun solve-3 (map)
|
|
|
|
(time (let ((data (read-3 map)))
|
|
|
|
(print (solve-3-1 '(1 3) data))
|
|
|
|
(print (solve-3-2 '((1 1) (1 3) (1 5) (1 7) (2 1)) data)))))
|