Skip to content

Instantly share code, notes, and snippets.

@death
Created December 6, 2020 11:18
Show Gist options
  • Select an option

  • Save death/ed7980ce7a932585a241a9fffdc2da83 to your computer and use it in GitHub Desktop.

Select an option

Save death/ed7980ce7a932585a241a9fffdc2da83 to your computer and use it in GitHub Desktop.
aoc2020 day6
;;;; +----------------------------------------------------------------+
;;;; | Advent of Code 2020 |
;;;; +----------------------------------------------------------------+
(defpackage #:snippets/aoc2020/day6
(:use #:cl)
(:shadowing-import-from
#:fset
#:set
#:empty-set
#:convert
#:union
#:intersection
#:size)
(:export
#:day6))
(in-package #:snippets/aoc2020/day6)
(defstruct group
(some (empty-set))
(every (empty-set))
(members 0))
(defun parse (input)
(mapcar #'parse-group input))
(defun parse-group (strings)
(reduce #'group-add strings :initial-value (make-group)))
(defun group-add (group answer-string)
(let ((answers (convert 'set answer-string)))
(make-group :some (union (group-some group) answers)
:every (if (zerop (group-members group))
answers
(intersection (group-every group) answers))
:members (1+ (group-members group)))))
(defun group-count-some (group)
(size (group-some group)))
(defun group-count-every (group)
(size (group-every group)))
(defun sum (sequence &key (key #'identity))
(reduce #'+ sequence :key key))
(defun day6 (input)
(let ((groups (parse input)))
(list (sum groups :key #'group-count-some)
(sum groups :key #'group-count-every))))
;; About the input expected by the solving program
;;
;; I wrote a regression tester for puzzles such as Advent of Code,
;; which reads files containing puzzle input and output, loads the
;; solving program, and compares its computed output to the stored
;; output.
;;
;; Many puzzles have similar input structure, e.g. lines of text or
;; lists of numbers. I exploit this by having the regression tester
;; preprocess the input prior to passing it to the solving program.
;;
;; With this puzzle I added a new preprocessing function,
;; grouped-lines (see below), which means my solving program can
;; expect a list of lists of lines, given that I add a test for it
;; like this:
;;
;; (add-test (aoc 2020 6 :input-transform #'grouped-lines))
(defun grouped-lines (string)
"Return a list of lists of lines in STRING.
Empty lines serve as group delimiters."
(let ((lines (lines string))
(group '())
(groups '()))
(flet ((add-group ()
(when group
(push (nreverse group) groups)
(setf group '()))))
(dolist (line lines)
(if (equal line "")
(add-group)
(push line group)))
(add-group)
(nreverse groups))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment