# HG changeset patch # User Steve Losh # Date 1701870988 18000 # Node ID 861dab6dff4cd5c11287034fa0c35647eddb6d5f # Parent 59d313b4c898e370fe9c86e974327222b10f66ae Clean up last day diff -r 59d313b4c898 -r 861dab6dff4c src/2023/days/day-05.lisp --- a/src/2023/days/day-05.lisp Wed Dec 06 08:17:12 2023 -0500 +++ b/src/2023/days/day-05.lisp Wed Dec 06 08:56:28 2023 -0500 @@ -2,10 +2,6 @@ (in-package :advent/2022/05) -;; Not really mentioned in the problem, but the maps come in sorted, i.e. the're -;; in the correct order. So we don't need to bohter making a hash table of -;; {from: to: [...]} but can just process the maps in the order they're given. - (defstruct (mapping (:constructor make-mapping%)) src-start src-end dst-start) @@ -33,6 +29,9 @@ (parse-body (rest (str:lines string)))) (defun parse (data) + ;; Not really mentioned in the problem, but the maps are given in the correct + ;; order. So we don't need to bohter making a hash table of {from: to: [...]} + ;; but can just reduce over the maps in the order they're given. (destructuring-bind (seeds . maps) (str:split (format nil "~2%") data) (values (parse-seeds seeds) (mapcar #'parse-map maps)))) @@ -42,6 +41,16 @@ (- n (mapping-src-start mapping)))) (defun map-single-range (input ranges) + ;; Take a single input range and a list of mapping ranges and produce a new + ;; list of ranges: + ;; + ;; Input: [10-20] + ;; Ranges: [12-14 -> 100-102] + ;; [18-30 -> 200-212] + ;; Result: [10-11], [100-102], [15-17], [200-202] + ;; + ;; Input should be a cons, ranges a sorted list of mapping structs. Note that + ;; both of these use lispy half-open intervals (unlike the example above). (iterate (with (start . end) = input) (with n = start) @@ -64,24 +73,12 @@ (setf n stop)))))) (defun map-ranges (inputs ranges) - (iterate (for input :in inputs) - (appending (map-single-range input ranges)))) + (alexandria:mappend (rcurry #'map-single-range ranges) inputs)) (defun traverse (almanac seeds) (reduce #'map-ranges almanac :initial-value seeds)) -;; (defun map-number (n ranges) -;; (let ((r (bisect-right #'> ranges n :key #'mapping-src-start))) -;; (if (or (null r) (>= n (mapping-src-end r))) -;; n -;; (let ((i (- n (mapping-src-start r)))) -;; (+ (mapping-dst-start r) i))))) - -;; (defun traverse (almanac seed) -;; (reduce #'map-number almanac :initial-value seed)) - - -(define-problem (2023 5) (data alexandria:read-stream-content-into-string) (324724204) +(define-problem (2023 5) (data alexandria:read-stream-content-into-string) (324724204 104070862) (multiple-value-bind (seeds almanac) (parse data) (let ((part-1 (iterate (for seed :in seeds) (collect (cons seed (1+ seed)))))