summary refs log tree commit diff
path: root/2024/d02.lisp
blob: 96817a704d0ddd5c8da6b0d1b3eed172f880f902 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
(in-package :aoc/2024)

(defparameter *input/d2*
  (asdf:system-relative-pathname :advent "2024/d02.input"))

(defun split-by-one-space (string)
  "Splits the string at spaces and parses the values as ints"
  (loop for i = 0 then (1+ j)
        as j = (position #\Space string :start i)
        collect (parse-integer (subseq string i j))
        while j))

(defun readlists (filename)
  "Reads the given file into a list of reports containing levels"
  (let ((reports '()))
    (with-open-file (stream filename :direction :input)
                    (loop for line = (read-line stream nil nil)
                          while line
                          do (push (split-by-one-space line) reports)))
    (nreverse reports)))

(defun diff-safe-p (a b)
  "Checks if the given two numbers are within of 3 of each other"
  (<= (abs (- a b)) 3))

(defun ordered-p (lst)
  "Checks if all conditions apply"
  (and (or (apply #'< lst) (apply #'> lst))
       (every #'diff-safe-p lst (rest lst))))

(print (count-if #'ordered-p (readlists *input/d2*)))
; 287

(defun remove-nth (n lst)
  "Remove the nth value from the given list"
  (remove-if (constantly t) lst :start n :count 1))

(defun fixable (lst)
  "Check if the given list if fixable when removing a value"
  (loop for i from 0 below (length lst)
        thereis (ordered-p (remove-nth i lst))))

(defun part-2 (lst)
  "The conditions for the second part"
  (or (ordered-p lst) (fixable lst)))

(print (count-if #'part-2 (readlists *input/d2*)))
; 354