You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

215 lines
6.5 KiB

;;;; 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)))))
(defvar *passport-fields* (list "byr" "iyr" "eyr" "hgt" "hcl" "ecl" "pid" "cid"))
(defvar *passport-rules-broken* (list nil nil nil nil nil nil nil (lambda (n) (declare (ignore n)) t)))
(defvar *passport-rules* nil)
(setf *passport-rules*
(list (lambda (n) (and n (let ((nn (ignore-errors (parse-integer n))))
(and nn (>= nn 1920) (<= nn 2002)))))
(lambda (n) (and n (let ((nn (ignore-errors (parse-integer n))))
(and nn (>= nn 2010) (<= nn 2020)))))
(lambda (n) (and n (let ((nn (ignore-errors (parse-integer n))))
(and nn (>= nn 2020) (<= nn 2030)))))
(lambda (h) (and h (multiple-value-bind (n offset) (parse-integer h :junk-allowed t)
(let ((unit (subseq h offset)))
(cond ((string= unit "cm")
(and (>= n 150) (<= n 193)))
((string= unit "in")
(and (>= n 59) (<= n 76))))))))
(lambda (c) (and c
(= (length c) 7)
(char= (elt c 0) #\#)
(parse-integer (subseq c 1) :radix 16)))
(lambda (c) (and c (member c '("amb" "blu" "brn" "gry" "grn" "hzl" "oth") :test #'equal)))
(lambda (pid) (and pid
(= 9
(length pid)
(length (remove-if (lambda (n) (not (digit-char-p n))) pid)))))
(lambda (cid) (declare (ignore cid)) t)))
(defun read-passport (stream)
(let ((passport-list
(apply #'concatenate 'list
(loop for line = (read-line stream nil)
while (and line (not (string= line "")))
collect (split-sequence:split-sequence #\space line))))
(current-passport (make-hash-table :test 'equal)))
(loop for key in passport-list
do (setf (gethash (subseq key 0 3) current-passport)
(subseq key 4)))
current-passport))
(defun read-4 (file)
(with-open-file (stream file)
(loop while (peek-char nil stream nil)
collect (read-passport stream))))
(defun %solve-4 (data tests)
(let ((valid-count 0))
(loop for passport in data
do (unless (member 'nil
(map 'list (lambda (field test)
(if test
(funcall test (gethash field passport))
(gethash field passport)))
*passport-fields* tests))
(incf valid-count)))
valid-count))
(defun solve-4 (file)
(let ((data (read-4 file)))
(time (progn (print (%solve-4 data *passport-rules-broken*))
(print (%solve-4 data *passport-rules*))))))
(defun binarize (string bits)
(parse-integer (substitute
#\1 (elt bits 1)
(substitute
#\0 (elt bits 0) string))
:radix 2))
(defun read-5 (file)
(with-open-file (stream file)
(loop for line = (read-line stream nil)
while line
collect (map 'list #'binarize (list (subseq line 0 7) (subseq line 7)) '("FB" "LR")))))
(defun boarding-ids (data)
(map 'list (lambda (seat) (+ (* 8 (first seat)) (second seat))) data))
(defun solve-5-1 (data)
(first (sort (boarding-ids data) #'>)))
(defvar p1-answer)
(defun report-significant-difference (x y)
(if (not (= (- x y) 1))
(setf p1-answer (1- x)))
y)
(defun solve-5-2 (data)
(reduce #'report-significant-difference (sort (boarding-ids data) #'>)))
(defun solve-5 (file)
(declare (special p1-answer)) (let ((data (read-5 file))
(p1-answer nil))
(time (progn (print (solve-5-1 (copy-seq data)))
(solve-5-2 data)
(print p1-answer)))))