6b72c45ad3
Finally an excuse to use some cl-defstruct magic in Elisp!
73 lines
2.4 KiB
EmacsLisp
73 lines
2.4 KiB
EmacsLisp
;; -*- lexical-binding: t; -*-
|
|
;; Advent of Code 2019 - Day 4
|
|
|
|
(require 'cl-lib)
|
|
(require 'dash)
|
|
|
|
;; Puzzle 1
|
|
|
|
(defun day4/to-digits (num)
|
|
"Convert NUM to a list of its digits."
|
|
(cl-labels ((steps (n digits)
|
|
(if (= n 0) digits
|
|
(steps (/ n 10) (cons (% n 10) digits)))))
|
|
(steps num '())))
|
|
|
|
(defvar day4/input (-map #'day4/to-digits (number-sequence 128392 643281)))
|
|
|
|
(defun day4/filter-password (digits)
|
|
"Determines whether the given rules match the supplied
|
|
number."
|
|
|
|
(and
|
|
;; It is a six digit number
|
|
(= 6 (length digits))
|
|
|
|
;; Value is within the range given in puzzle input
|
|
;; (noop because the range is generated from the input)
|
|
|
|
;; Two adjacent digits are the same (like 22 in 122345).
|
|
(car (-reduce-from (-lambda ((acc . prev) next)
|
|
(cons (or acc (= prev next)) next))
|
|
'(nil . 0) digits))
|
|
|
|
;; Going from left to right, the digits never decrease; they only
|
|
;; ever increase or stay the same (like 111123 or 135679).
|
|
(car (-reduce-from (-lambda ((acc . prev) next)
|
|
(cons (and acc (>= next prev)) next))
|
|
'(t . 0) digits))))
|
|
|
|
;; Puzzle 2
|
|
;;
|
|
;; Additional criteria: If there's matching digits, they're not in a group.
|
|
|
|
(cl-defstruct day4/acc state prev count)
|
|
|
|
(defun day4/filter-longer-groups (digits)
|
|
(let ((res (-reduce-from
|
|
(lambda (acc next)
|
|
(cond ;; sequence is broken and count was at 1 ->
|
|
;; match!
|
|
((and (= (day4/acc-count acc) 2)
|
|
(/= (day4/acc-prev acc) next))
|
|
(setf (day4/acc-state acc) t))
|
|
|
|
;; sequence continues, counter increment!
|
|
((= (day4/acc-prev acc) next)
|
|
(setf (day4/acc-count acc) (+ 1 (day4/acc-count acc))))
|
|
|
|
;; sequence broken, reset counter
|
|
((/= (day4/acc-prev acc) next)
|
|
(setf (day4/acc-count acc) 1)))
|
|
|
|
(setf (day4/acc-prev acc) next)
|
|
acc)
|
|
(make-day4/acc :prev 0 :count 0) digits)))
|
|
(or (day4/acc-state res)
|
|
(= 2 (day4/acc-count res)))))
|
|
|
|
(let* ((simple (-filter #'day4/filter-password day4/input))
|
|
(complex (-filter #'day4/filter-longer-groups simple)))
|
|
(message "Solution to day4/1: %d" (length simple))
|
|
(message "Solution to day4/2: %d" (length complex)))
|
|
|