Change-Id: I9d065b672f4245b81444737dd900c8864447bc4d Reviewed-on: https://cl.tvl.fyi/c/depot/+/2211 Tested-by: BuildkiteCI Reviewed-by: tazjin <mail@tazj.in>
		
			
				
	
	
		
			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)))
 | 
						|
 |