src/old/2017/main.lisp @ 7e8b6d68c899

Update some old problems
author Steve Losh <steve@stevelosh.com>
date Fri, 29 Nov 2019 15:15:05 -0500
parents 75998992ab3c
children (none)
(in-package :advent)
(named-readtables:in-readtable :interpol-syntax)

(asdf:test-system )

(define-problem (2017 1 1) (data read-file-of-digits)
  (iterate
    (for (x . y) :pairs-of-list data)
    (when (= x y)
      (sum x))))

(define-problem (2017 1 2) (data read-file-of-digits)
  (iterate
    (with data = (coerce data 'vector))
    (with length = (length data))
    (for x :in-vector data)
    (for iy :modulo length :from (truncate length 2))
    (for y = (aref data iy))
    (when (= x y)
      (sum x))))


(define-problem (2017 2 1) (data read-file-of-lines-of-numbers)
  (flet ((checksum (line)
           (- (extremum line #'>)
              (extremum line #'<))))
    (summation data :key #'checksum)))

(define-problem (2017 2 2) (data read-file-of-lines-of-numbers)
  (labels ((validp (a b)
             (dividesp (max a b) (min a b)))
           (head-valid-p (list)
             (destructuring-bind (n . remaining) list
               (some (curry #'validp n) remaining)))
           (checksum (line)
             (somelist #'head-valid-p line)))
    (summation data :key #'checksum)))


(define-problem (2017 3 1) (data read-form-from-file)
  (labels ((manhattan-distance (a b)
             (+ (abs (- (realpart a)
                        (realpart b)))
                (abs (- (imagpart a)
                        (imagpart b)))))
           (distance-to-origin (p)
             (manhattan-distance #c(0 0) p)))
    (distance-to-origin (advent.spiral:number-coordinates data))))

(define-problem (2017 3 2) (data read-form-from-file)
  (flet ((neighbors (coord)
           (gathering
             (do-irange ((dx -1 1)
                         (dy -1 1))
               (unless (= 0 dx dy)
                 (gather (+ coord (complex dx dy))))))))
    (iterate
      (with memory = (make-hash-table))
      (initially (setf (gethash #c(0 0) memory) 1))
      (for n :from 2)
      (for coord = (advent.spiral:number-coordinates n))
      (for value = (summation (neighbors coord) :key (rcurry #'gethash memory 0)))
      (finding value :such-that (> value data))
      (setf (gethash coord memory) value))))


(define-problem (2017 4 1) (data read-file-of-lines-of-words)
  (labels ((contains-duplicates-p (list &key (test #'eql))
             (iterate (for (head . tail) :on list)
                      (thereis (member head tail :test test))))
           (validp (phrase)
             (not (contains-duplicates-p phrase :test #'string=))))
    (count-if #'validp data)))

(define-problem (2017 4 2) (data read-file-of-lines-of-words)
  (labels ((anagramp (string1 string2)
             (hash-table= (frequencies string1) (frequencies string2)))
           (contains-anagram-p (phrase)
             (iterate (for (word . tail) :on phrase)
                      (thereis (member-if (curry #'anagramp word) tail)))))
    (count-if-not #'contains-anagram-p data)))


(define-problem (2017 5 1) (data read-all-from-file)
  (iterate
    (with maze = (coerce data 'simple-vector))
    (with bound = (1- (length maze)))
    (with address = 0)
    (for steps :from 0)
    (finding steps :such-that (not (<= 0 address bound)))
    (for offset = (aref maze address))
    (incf (aref maze address))
    (incf address offset)))

(define-problem (2017 5 2) (data read-all-from-file)
  (iterate
    (with maze = (coerce data 'simple-vector))
    (with bound = (1- (length maze)))
    (with address = 0)
    (for steps :from 0)
    (finding steps :such-that (not (<= 0 address bound)))
    (for offset = (aref maze address))
    (incf (aref maze address)
          (if (>= offset 3) -1 1))
    (incf address offset)))


(define-problem (2017 6) (data read-all-from-file)
  (let ((banks (coerce data 'vector))
        (seen (make-hash-table :test 'equalp)))
    (labels ((bank-to-redistribute ()
               (iterate (for blocks :in-vector banks :with-index bank)
                        (finding bank :maximizing blocks)))
             (redistribute ()
               (iterate
                 (with bank = (bank-to-redistribute))
                 (with blocks-to-redistribute = (aref banks bank))
                 (initially (setf (aref banks bank) 0))
                 (repeat blocks-to-redistribute)
                 (for b :modulo (length banks) :from (1+ bank))
                 (incf (aref banks b))))
             (mark-seen (banks cycles)
               (setf (gethash (copy-seq banks) seen) cycles)))
      (iterate
        (mark-seen banks cycle)
        (summing 1 :into cycle)
        (redistribute)
        (for last-seen = (gethash banks seen))
        (until last-seen)
        (finally (return (values cycle (- cycle last-seen))))))))


(define-problem (2017 7) (data read-lines-from-file)
  (labels
      ((parse-line (line)
         (ppcre:register-groups-bind
             (name (#'parse-integer weight) ((curry #'str:split ", ") holding))
             (#?/(\w+) \((\d+)\)(?: -> (.+))?/ line)
           (values name weight holding)))
       (insert-edge (digraph pred succ)
         (digraph:insert-vertex digraph pred)
         (digraph:insert-vertex digraph succ)
         (digraph:insert-edge digraph pred succ))
       (build-tower (lines)
         (iterate
           (with tower = (digraph:make-digraph :test #'equal))
           (for line :in lines)
           (for (values name weight holding) = (parse-line line))
           (collect-hash (name weight) :into weights :test #'equal)
           (digraph:insert-vertex tower name)
           (map nil (curry #'insert-edge tower name) holding)
           (finally (return (values tower weights))))))
    (multiple-value-bind (tower individual-weights) (build-tower data)
      (declare (ignore individual-weights))
      ;; (digraph.dot:draw tower)
      (first (digraph:roots tower)))))