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.
78 lines
2.3 KiB
Racket
78 lines
2.3 KiB
Racket
#lang typed/racket
|
|
(require typed/rackunit)
|
|
(provide (all-defined-out))
|
|
|
|
(define up-char #\()
|
|
(define down-char #\))
|
|
|
|
(: make-matcher (-> Char (-> String Natural)))
|
|
(define (make-matcher c)
|
|
(λ((str : String)) (length (regexp-match* (regexp (format "\\~a" c)) str))))
|
|
(define get-ups (make-matcher up-char))
|
|
(define get-downs (make-matcher down-char))
|
|
(: get-destination (-> String Integer))
|
|
(define (get-destination str) (- (get-ups str) (get-downs str)))
|
|
|
|
(: q1 (-> String Integer))
|
|
(define (q1 str)
|
|
(get-destination str))
|
|
|
|
(: elevator-string->ints (-> String (Listof Integer)))
|
|
(define (elevator-string->ints str)
|
|
(for/list : (Listof Integer)
|
|
([c (in-string str)])
|
|
(if (equal? c up-char)
|
|
1
|
|
-1)))
|
|
|
|
(: q1-alt (-> String Integer))
|
|
(define (q1-alt str)
|
|
(apply + (elevator-string->ints str)))
|
|
|
|
(: in-basement? (-> (Listof Integer) Boolean))
|
|
(define (in-basement? movements)
|
|
(negative? (apply + movements)))
|
|
|
|
(: q2 (-> String Integer))
|
|
(define (q2 str)
|
|
(define relative-movements
|
|
(for/fold : (Listof Integer)
|
|
([movements-so-far : (Listof Integer) empty])
|
|
([c (in-string str)]
|
|
;#:break (in-basement? movements-so-far)
|
|
)
|
|
(if (in-basement? movements-so-far)
|
|
movements-so-far
|
|
(cons (get-destination (~a c)) movements-so-far))))
|
|
(length relative-movements))
|
|
|
|
(: q2-for/first (-> String (U #f Integer)))
|
|
(define (q2-for/first str)
|
|
(define basement-position
|
|
(let ([ints (elevator-string->ints str)])
|
|
(for/or : (U #f Integer) ;;bg first=>or
|
|
([idx (in-range (length ints))]
|
|
#:when (negative? (apply + (take ints idx))))
|
|
idx)))
|
|
basement-position)
|
|
|
|
(: q2-for/or (-> String (U #f Integer)))
|
|
(define (q2-for/or str)
|
|
(define basement-position
|
|
(let ([ints (elevator-string->ints str)])
|
|
(for/or : (U #f Integer)
|
|
([idx (in-range (length ints))])
|
|
(and (negative? (apply + (take ints idx))) idx))))
|
|
basement-position)
|
|
|
|
|
|
(module+ test
|
|
(define input-str (file->string "../day01-input.txt"))
|
|
(check-equal? (q1 input-str) 74)
|
|
(check-equal? (q1-alt input-str) 74)
|
|
(check-equal? (q2 input-str) 1795)
|
|
(check-equal? (q2-for/first input-str) 1795)
|
|
(check-equal? (q2-for/or input-str) 1795))
|
|
|
|
|