Advent of Code 2020 solutions in Racket, I guess
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

72 lines
2.4 KiB

#lang racket
(require "lib/common.rkt")
(struct password (min max char content) #:transparent)
(define (parse-line line)
(match line
[(pregexp #px"^([0-9]+)\\-([0-9]+) (.): (.*?)$" (list _ min max char pwd))
(password (string->number min)
(string->number max)
(string-ref char 0)
pwd)]
[_ (error "oh no")]))
(define (password-valid?/a pwd)
(define occurrences
(count (curry char=? (password-char pwd))
(string->list (password-content pwd))))
(<= (password-min pwd) occurrences (password-max pwd)))
(define (password-valid?/b pwd)
(define (in-position? n)
(char=? (string-ref (password-content pwd) (sub1 n))
(password-char pwd)))
(xor (in-position? (password-min pwd))
(in-position? (password-max pwd))))
(define (solution lst fn)
(count fn (map parse-line lst)))
(module+ main
(call-with-input-file "data/day2.txt"
(lambda (prt)
(define lines (port->lines prt))
(answer 2 1 (solution lines password-valid?/a))
(answer 2 2 (solution lines password-valid?/b)))))
(module+ test
(require rackunit)
(define example1 (password 1 3 #\a "abcde"))
(define example2 (password 1 3 #\b "cdefg"))
(define example3 (password 2 9 #\c "ccccccccc"))
(check-equal? (parse-line "1-3 a: abcde") example1
"1-3 a: abcde, parse")
(check-equal? (parse-line "1-3 b: cdefg") example2
"1-3 b: cdefg, parse")
(check-equal? (parse-line "2-9 c: ccccccccc") example3
"2-9 c: ccccccccc, parse")
(check-pred password-valid?/a example1
"1-3 a: abcde, part 1 validity")
(check-false (password-valid?/a example2)
"1-3 b: cdefg, part 1 validity")
(check-pred password-valid?/a example3
"2-9 c: ccccccccc, part 1, validity")
(check-pred password-valid?/b example1
"1-3 a: abcde, part 2 validity")
(check-false (password-valid?/b example2)
"1-3 b: cdefg, part 2 validity")
(check-false (password-valid?/b example3)
"2-9 c: ccccccccc, part 2 validity")
(call-with-input-file "data/day2.txt"
(lambda (prt)
(define lines (port->lines prt))
(check-equal? (solution lines password-valid?/a) 572
"final answer part 1")
(check-equal? (solution lines password-valid?/b) 306
"final answer part 2"))))