aoc2023/day1.ss

56 lines
1.9 KiB
Scheme

(import (rnrs)
(only (chezscheme) make-parameter parameterize printf))
(define filename (make-parameter "in/day1"))
(define (string-reverse str) (list->string (reverse (string->list str))))
(define default-numbers
'(("one" . 1) ("two" . 2) ("three" . 3) ("four" . 4) ("five" . 5)
("six" . 6) ("seven" . 7) ("eight" . 8) ("nine" . 9)))
(define numbers (make-parameter default-numbers))
(define (digit? c) (and (char<=? #\0 c #\9) c))
(define (digit-val c) (- (char->integer c) (char->integer #\0)))
(define (at? start short&val long)
(let* [(short (car short&val))
(val (cdr short&val))
(end (+ start (string-length short)))]
(cond [(> end (string-length long)) #f]
[(string=? short (substring long start end)) val]
[else #f])))
(define (find-first str)
(let loop [(i 0)]
(cond [(digit? (string-ref str i)) => digit-val]
[(exists (lambda (n) (at? i n str)) (numbers))]
[else (loop (+ i 1))])))
(define (find-last str)
(let* [(rev-car (lambda (p) (cons (string-reverse (car p)) (cdr p))))
(rnums (map rev-car (numbers)))
(rstr (string-reverse str))]
(parameterize [(numbers rnums)] (find-first rstr))))
(define (make-value first last) (+ (* 10 first) last))
(define (value line) (make-value (find-first line) (find-last line)))
(define (value1 line) (parameterize [(numbers '())] (value line)))
(define (value2 line) (parameterize [(numbers default-numbers)] (value line)))
(define (all-lines file)
(let [(next (lambda () (get-line file)))]
(do [(line (next) (next))
(acc '() (cons line acc))]
[(eof-object? line) (reverse acc)])))
(define (input) (call-with-input-file (filename) all-lines))
(define (part1 input) (apply + (map value1 input)))
(define (part2 input) (apply + (map value2 input)))
(let [(in (input))] (printf "~a~n~a~n" (part1 in) (part2 in)))