71 lines
2.2 KiB
Scheme
71 lines
2.2 KiB
Scheme
(import (srfi :43)) ; vector extensions
|
|
|
|
; returns a list of numbers parsed from the first line of the file,
|
|
; separated by commas
|
|
(define (read-comma-separated-numbers file)
|
|
(let loop [(draws '()) (n 0)]
|
|
(let [(c (get-char file))]
|
|
(cond
|
|
[(char=? c #\,) (loop (cons n draws) 0)]
|
|
[(char-whitespace? c) (reverse (cons n draws))]
|
|
[else (loop draws (+ (* n 10) (string->number (string c))))]))))
|
|
|
|
;; naive version, as per the example
|
|
; simulate lanterfish growth and returns the number of fishes after given days
|
|
;(define (simulate-growth fishes days)
|
|
; (let days-loop [(day 0) (fishes fishes)]
|
|
; (if (= day days)
|
|
; (length fishes)
|
|
; (days-loop
|
|
; (+ day 1)
|
|
; (let grow [(new '()) (old fishes)]
|
|
; (if (null? old)
|
|
; new
|
|
; (if (= (car old) 0)
|
|
; (grow (cons 6 (cons 8 new)) (cdr old))
|
|
; (grow (cons (- (car old) 1) new) (cdr old)))))))))
|
|
|
|
;; optimized version
|
|
;; instead of keeping track of fishes
|
|
;; we just keep track of how many are living at each age.
|
|
;; so, the living vector is actually indexed by age
|
|
(define (sum living)
|
|
(vector-fold (lambda (i sum value) (+ sum value)) 0 living))
|
|
|
|
; returns a new vector with the new number of fishes at each age
|
|
(define (grow living)
|
|
(let [(new (make-vector 9 0))]
|
|
(vector-for-each
|
|
(lambda (age count)
|
|
(if (= age 0)
|
|
(begin
|
|
(vector-set! new 8 count)
|
|
(vector-set! new 6 count))
|
|
(vector-set! new (- age 1)
|
|
(+ count (vector-ref new (- age 1))))))
|
|
living)
|
|
new))
|
|
|
|
; simulate lanterfish growth and returns the number of fishes after given days
|
|
(define (simulate-growth fishes days)
|
|
(let [(living-per-day (make-vector 9 0))]
|
|
(let init-loop [(fishes fishes)]
|
|
(when (not (null? fishes))
|
|
(vector-set! living-per-day (car fishes)
|
|
(+ 1 (vector-ref living-per-day (car fishes))))
|
|
(init-loop (cdr fishes))))
|
|
(let loop [(day 0)
|
|
(living-per-day living-per-day)]
|
|
(if (= day days)
|
|
(sum living-per-day)
|
|
(loop (+ day 1) (grow living-per-day))))))
|
|
|
|
(call-with-input-file
|
|
"input"
|
|
(lambda (file)
|
|
(let [(input (read-comma-separated-numbers file))]
|
|
(printf "part 1:~% count after 80 days: ~a~%"
|
|
(simulate-growth input 80))
|
|
(printf "part 1:~% count after 256 days: ~a~%"
|
|
(simulate-growth input 256)))))
|