46 lines
1.5 KiB
Scheme
46 lines
1.5 KiB
Scheme
(import (chicken io)
|
|
(chicken format)
|
|
srfi-1
|
|
srfi-42
|
|
srfi-69
|
|
srfi-152)
|
|
|
|
(define (read-input #!optional (port (current-input-port)))
|
|
(apply values (map (lambda (s) (string->number (string-drop s 28))) (read-lines port))))
|
|
|
|
(define (part1 start1 start2)
|
|
(let lp ((k 0)
|
|
(pos1 (- start1 1))
|
|
(pos2 (- start2 1))
|
|
(score1 0)
|
|
(score2 0))
|
|
(cond
|
|
((>= score1 1000) (* score2 k 3))
|
|
((>= score2 1000) (* score1 k 3))
|
|
((even? k) (let* ((dice (+ (* 9 k) 6))
|
|
(new-pos1 (remainder (+ pos1 dice) 10)))
|
|
(lp (+ k 1) new-pos1 pos2 (+ score1 new-pos1 1) score2)))
|
|
((odd? k) (let* ((dice (+ (* 9 k) 6))
|
|
(new-pos2 (remainder (+ pos2 dice) 10)))
|
|
(lp (+ k 1) pos1 new-pos2 score1 (+ score2 new-pos2 1)))))))
|
|
|
|
(define (part2 start1 start2)
|
|
(define cache (make-hash-table))
|
|
(define (play pos1 pos2 score1 score2)
|
|
(if (>= score2 21)
|
|
(list 0 1)
|
|
(fold-ec (list 0 0)
|
|
(: d1 '(1 2 3)) (: d2 '(1 2 3)) (: d3 '(1 2 3))
|
|
(:let new-pos1 (remainder (+ pos1 d1 d2 d3) 10))
|
|
(:let key (list pos2 new-pos1 score2 (+ score1 new-pos1 1)))
|
|
(reverse (if (hash-table-exists? cache key)
|
|
(hash-table-ref cache key)
|
|
(let ((val (apply play key)))
|
|
(hash-table-set! cache key val)
|
|
val)))
|
|
(lambda (x acc) (list (+ (car x) (car acc)) (+ (cadr x) (cadr acc)))))))
|
|
(apply max (play (- start1 1) (- start2 1) 0 0)))
|
|
|
|
(let-values (((start1 start2) (read-input)))
|
|
(print (part1 start1 start2))
|
|
(print (part2 start1 start2)))
|