You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
aoc-racket/typed/day14.rkt

76 lines
2.8 KiB
Racket

#lang typed/racket
(require typed/rackunit (for-syntax racket/file))
(provide (all-defined-out))
(define-syntax (convert-input-to-reindeer-functions stx)
(syntax-case stx ()
[(_)
(let* ([input-strings (file->lines "../day14-input.txt")]
[reindeer-strings
(map (λ(str) (format "(reindeer ~a)" (string-downcase str))) input-strings)]
[reindeer-datums
(map (compose1 read open-input-string) reindeer-strings)])
(datum->syntax stx `(begin ,@reindeer-datums)))]))
(define-type Deer-Func (-> Integer Natural))
(define-syntax (reindeer stx)
(syntax-case stx (can fly seconds but then must rest for)
[(_ deer-name can fly speed km/s for fly-secs seconds, but then must rest for rest-secs seconds.)
#'(define (deer-name (total-secs : Integer)) : Natural
(calc-distance total-secs speed fly-secs rest-secs))]
[else #'(void)]))
(convert-input-to-reindeer-functions)
(: calc-distance (-> Integer Natural Natural Natural Natural))
(define (calc-distance total-secs speed fly-secs rest-secs)
(let loop : Natural ([secs-remaining : Integer total-secs] [distance : Natural 0])
(if (<= secs-remaining 0)
distance
(let ([secs-in-flight (min secs-remaining fly-secs)])
(loop (- secs-remaining fly-secs rest-secs)
(+ (* secs-in-flight speed) distance))))))
(: q1 (-> Natural))
(define (q1)
(define seconds-to-travel 2503)
(apply max (map (λ((deer-func : Deer-Func)) (deer-func seconds-to-travel))
(list dasher dancer prancer vixen comet
cupid donner blitzen rudolph))))
;;bg added submodule, because (HashTable A B) cannot be converted to a flat contract :/
(module sugar racket/base
(require (only-in sugar/list frequency-hash))
(define frequency-list
(compose1 hash-values frequency-hash))
(provide frequency-list))
(require/typed (submod "." sugar)
(frequency-list (-> (Listof Any) (Listof Natural))))
(: q2 (-> Natural))
(define (q2)
(define deer-funcs (list dasher dancer prancer vixen comet
cupid donner blitzen rudolph))
(define winners
(frequency-list
(flatten
(for/list : (Listof Any) ([sec (in-range 1 (add1 2503))])
(define deer-results
(map (λ([deer-func : Deer-Func]) (deer-func sec)) deer-funcs))
(define max-result (apply max deer-results))
(map (λ([deer-result : Natural] [deer-func : Deer-Func])
(if (= deer-result max-result)
deer-func
empty))
deer-results deer-funcs)))))
(apply max winners))
(module+ test
(define input-str (file->string "../day14-input.txt"))
(check-equal? (q1) 2640)
(check-equal? (q2) 1102))