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/day11.rkt

57 lines
2.0 KiB
Racket

#lang typed/racket
(require typed/rackunit trivial/regexp/no-colon)
(provide (all-defined-out))
(: increment-password (-> String String))
(define (increment-password password)
(: increment-letter (-> String String))
(define (increment-letter c)
(~a (integer->char (add1 (char->integer (car (string->list c)))))))
;bg;((compose1 ~a integer->char add1 char->integer car string->list) c)
(match-define (list _ prefix letter-to-increment trailing-zs)
(regexp-match #rx"^(.*?)(.)(z*)$" password))
(string-append* (list prefix (increment-letter letter-to-increment)
(regexp-replace* #rx"z" trailing-zs "a"))))
(: three-consecutive-letters? (-> String Boolean))
(define (three-consecutive-letters? str)
(define ints (map char->integer (string->list str)))
(let loop : Boolean ([differences (map - (cdr ints) (drop-right ints 1))])
(if (empty? differences)
#f
(or (list-prefix? '(1 1) differences) (loop (cdr differences))))))
(: no-iol? (-> String Boolean))
(define (no-iol? str)
(not (regexp-match #rx"[iol]" str)))
(: two-nonoverlapping-doubles? (-> String Boolean))
(define (two-nonoverlapping-doubles? str)
(regexp-match? #px"(\\w)\\1.*?(\\w)\\2" str)) ;;bg: add ?
(: valid? (-> String Boolean))
(define (valid? password)
(and (three-consecutive-letters? password)
(no-iol? password)
(two-nonoverlapping-doubles? password)))
(: find-next-valid-password (-> String String))
(define (find-next-valid-password starting-password)
(define candidate-pw (increment-password starting-password))
(if (valid? candidate-pw)
candidate-pw
(find-next-valid-password candidate-pw)))
(: q1 (-> String String))
(define (q1 input-key)
(find-next-valid-password input-key))
(: q2 (-> String String))
(define (q2 input-key)
(find-next-valid-password (q1 input-key)))
(module+ test
(define input-key (file->string "../day11-input.txt"))
(check-equal? (q1 input-key) "hxbxxyzz")
(check-equal? (q2 input-key) "hxcaabcc"))