advent-of-code/2021/day17/day17.scm
2024-11-12 21:46:18 +01:00

59 lines
1.6 KiB
Scheme

(import (chicken io)
(chicken format)
srfi-1
srfi-42
srfi-152
matchable)
(define (read-input #!optional (port (current-input-port)))
(map (lambda (s) (map string->number (string-split (string-drop s 2) "..")))
(string-split (string-drop (read-line port) 13) ", ")))
(define-record state
x y vx vy)
(set! (record-printer state)
(lambda (st out)
(fprintf out "#,(state ~S ~S ~S ~S)" (state-x st) (state-y st) (state-vx st) (state-vy st))))
(define (too-far? target-area st)
(match-let ((((x1 x2) (y1 y2)) target-area)
(($ state x y vx vy) st))
(< y (min y1 y2))))
(define (in-target? target-area st)
(match-let ((((x1 x2) (y1 y2)) target-area)
(($ state x y vx vy) st))
(and (<= x1 x x2) (<= y1 y y2))))
(define (sign x)
(cond
((zero? x) 0)
((> x 0) 1)
((< x 0) -1)))
(define (step st)
(match-let ((($ state x y vx vy) st))
(make-state (+ x vx) (+ y vy)
(- vx (sign vx)) (- vy 1))))
(define (simulate target-area vx vy)
(let lp ((st (make-state 0 0 vx vy))
(prev-st (make-state 0 0 vx vy))
(max-height 0))
(cond
((in-target? target-area st) (list st (max max-height (state-y st))))
((too-far? target-area st) (list prev-st max-height))
(else (lp (step st) st (max max-height (state-y st)))))))
(define (find-max-height target-area)
(list-ec (: vx 0 500)
(: vy -100 1000)
(:let st (simulate target-area vx vy))
(if (in-target? target-area (car st)))
(cadr st)))
(let* ((target-area (read-input))
(max-heights (find-max-height target-area)))
(print (apply max max-heights))
(print (length max-heights)))