src/2021/days/day-17.lisp @ 861dab6dff4c
default tip
Clean up last day
author |
Steve Losh <steve@stevelosh.com> |
date |
Wed, 06 Dec 2023 08:56:28 -0500 |
parents |
cb7df3835cd1 |
children |
(none) |
(advent:defpackage* :advent/2021/17 (:shadow x y))
(in-package :advent/2021/17)
(defstruct (p (:constructor p (&optional (x 0) (y 0))) (:conc-name nil))
(x 0 :type fixnum)
(y 0 :type fixnum))
(defstruct (box (:constructor box (xmin xmax ymin ymax)) (:conc-name nil))
(xmin 0 :type fixnum)
(xmax 0 :type fixnum)
(ymin 0 :type fixnum)
(ymax 0 :type fixnum))
(defun-inline in-box-p (p box)
(and (<= (xmin box) (x p) (xmax box))
(<= (ymin box) (y p) (ymax box))))
(defun-inline step! (pos vel)
(incf (x pos) (x vel))
(incf (y pos) (y vel))
(decf (x vel) (signum (x vel)))
(decf (y vel)))
(defun-inline simulate (vel target)
(iterate (with v = (copy-p vel))
(with p = (p 0 0))
(step! p v)
(maximizing (y p) :into height)
(until (or (> (x p) (xmax target))
(< (y p) (ymin target))))
(when (in-box-p p target)
(return height))))
(defun solve (target)
;; Could allocate one single velocity struct here and reuse it everywhere to
;; reduce consing, but it's already fast enough, so whatever.
(iterate (for vx :from 0 :to (xmax target))
(do-irange ((vy (ymin target) (- (ymin target))))
(for height = (simulate (p vx vy) target))
(when height
(maximizing height :into part1)
(counting t :into part2)))
(returning part1 part2)))
(defun parse (stream &aux (line (read-line stream)))
(ppcre:register-groups-bind ((#'parse-integer xmin xmax ymin ymax))
("target area: x=(-?\\d+)\\.\\.(-?\\d+), y=(-?\\d+)\\.\\.(-?\\d+)" line)
(box xmin xmax ymin ymax)))
(define-problem (2021 17) (target parse) (8646 5945)
(solve target))
#; Scratch --------------------------------------------------------------------