;; -*- 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)))