54 lines
1.5 KiB
Racket
54 lines
1.5 KiB
Racket
#lang racket
|
|
|
|
(require "../lib.rkt")
|
|
|
|
(define (string->numbers str)
|
|
(map (λ (c) (- (char->integer c) (char->integer #\0)))
|
|
(string->list str)))
|
|
|
|
(define input-string (car (problem-input 16)))
|
|
|
|
(define input
|
|
(string->numbers input-string))
|
|
|
|
(define (base n)
|
|
(let* ([bs (apply append (map (∂ make-list n) '(0 1 0 -1)))])
|
|
(rac (cdr bs) (car bs))))
|
|
|
|
(define (prod-sum l1 l2)
|
|
(let* ([len (min (length l1) (length l2))]
|
|
[l1 (take l1 len)]
|
|
[l2 (take l2 len)])
|
|
(sum (map * l1 l2))))
|
|
|
|
(define (fft ns)
|
|
(let* ([base-reps (λ (n) (ceiling (/ (length ns) (* 4 n))))]
|
|
[base-n (λ (n) (repeat (base-reps n) (base n)))])
|
|
(map (λ (n) (remainder (abs (prod-sum ns (base-n n))) 10))
|
|
(range 1 (add1 (length ns))))))
|
|
|
|
(define (part1)
|
|
(let loop ([signal input]
|
|
[count 0])
|
|
(if (= 100 count)
|
|
(take signal 8)
|
|
(loop (fft signal) (add1 count)))))
|
|
|
|
(define (fft-half ns)
|
|
(second
|
|
(foldr (λ (v acc)
|
|
(match-let ([(list sum lst) acc])
|
|
(let ([sum (% (+ v sum) 10)])
|
|
(list sum (cons (abs sum) lst)))))
|
|
(list 0 '(0)) ns)))
|
|
|
|
(define (part2)
|
|
(let* ([offset (digits->number (take input 7))]
|
|
[input-long (repeat 10000 input)]
|
|
[half-length (/ (* 10000 (length input)) 2)]
|
|
[input-half (drop input-long half-length)])
|
|
(let loop ([count 0]
|
|
[signal input-half])
|
|
(if (= count 100)
|
|
(take (drop signal (- offset half-length)) 8)
|
|
(loop (add1 count) (fft-half signal)))))) |