#lang racket (require threading) (define sample-pos (~> "16,1,2,0,4,2,7,1,2,14" #; (with-input-from-file "/tmp/input" (λ () (port->string (current-input-port)))) string-trim (string-split _ ",") (map string->number _))) (define real-pos (~> (with-input-from-file "/tmp/input" (λ () (port->string (current-input-port)))) string-trim (string-split _ ",") (map string->number _))) (define (average lst) (define sum (apply + lst)) (floor (/ sum (length lst)))) (define memo (make-hash '())) (module+ test (require rackunit)) (define (indv-cost target at) (define dist (abs (- target at))) (define (f dist acc) (if (zero? dist) acc (f (sub1 dist) (+ dist acc)))) (f dist 0)) (module+ test (check-equal? (indv-cost 16 5) 66) (check-equal? (indv-cost 1 5) 10)) (define (cost target lst) (if (hash-has-key? memo target) (hash-ref memo target) (let* [ (result (apply + (map (λ (i) (indv-cost i target)) lst)))] (begin (hash-set! memo target result) result)))) (module+ test (check-equal? (cost 5 sample-pos) 168) (check-equal? (cost 2 sample-pos) 206)) (define (list-range lst) (define mx (foldl max (first lst) lst)) (define mn (foldl min (first lst) lst)) (in-range mn mx)) (define start (average sample-pos)) (define (go-left? target lst) (< (cost (sub1 target) lst) (cost target lst))) (define (go-right? target lst) (< (cost (add1 target) lst) (cost target lst))) (define (done? target lst) (not (or (go-left? target lst) (go-right? target lst)))) (define (step target lst) (if (go-right? target lst) (add1 target) (sub1 target))) (define (loop target lst) (if (done? target lst) (cost target lst) (loop (step target lst) lst)))