summaryrefslogtreecommitdiffstats
path: root/src/03.lisp
blob: ae2f0bd8783d7b0d411d0e9953aa98f9bca612af (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
(load "~/quicklisp/setup.lisp")
(ql:quickload "uiop")

(defun get-file-lines (name)
  (uiop:read-file-lines name))

(defun parse-bin-char (x) (case x (#\1 1) (#\0 0)))

;; Turn the input file into whatever form you will use for both parts
;; (get-file-lines) and (get-file-string) will be useful
(defun parse-input (input-file)
  (mapcar (lambda (x) (mapcar #'parse-bin-char (coerce x 'list))) (get-file-lines input-file)))

;; Loops through two item windows on input and counts each time the first is less than the second
(defun partial (func &rest args1)
  (lambda (&rest args2)
    (apply func (append args1 args2))))

(defun is-less (h l)
  (mapcar (lambda (x) (if (< x h) 0 1)) l))

(defun not-list (l)
  (mapcar (lambda (x) (if (= x 0) 1 0)) l))

(defun range (max &key (min 0) (step 1))
   (loop :for n :from (- max 1) :above (- min 1) :by step
      :collect n))

(defun to-dec (l)
  (apply #'+ (mapcar (lambda (a b) (* a (expt 2 b))) l (range (list-length l)))))

(defun part-a (parsed-input)
  (let* ((half-length (/ (list-length parsed-input) 2))
         (l (is-less half-length (apply (partial #'mapcar #'+) parsed-input)))
         (gamma (to-dec l))
         (epsilon (to-dec (not-list l))))
    (* epsilon gamma)))

;; Similar to part a, but with four item windows, comparing the sum of the first 3 with the next 3
(defun part-b (parsed-input)
  (loop for (w x y z) on parsed-input until (null z) if (< (+ w x y) (+ x y z)) count w))

(time (format t "part 1: ~a~%" (part-a (parse-input "../inputs/03.txt"))))
;;(time (format t "part 1: ~a~%" (part-a (parse-input "test.txt"))))
;;(time (format t "part 1: ~a~%" (part-b (parse-input "../inputs/01.txt"))))