#lang br (require racket/file rackunit graph racket/dict) (define (string->orbits str) (for/list ([ln (in-list (string-split str))]) (map string->symbol (string-split ln ")")))) (define orbit-recs (string->orbits (file->string "06.rktd"))) (define (count-orbits orbit-recs) (match/values (bfs (undirected-graph orbit-recs) 'COM) [(dists _) (apply + (hash-values dists))])) ;; 1 (check-eq? (count-orbits orbit-recs) 261306) (define (count-transfers orbit-recs) (match/values (bellman-ford (undirected-graph orbit-recs) 'YOU) [(dists _) (- (hash-ref dists 'SAN) 2)])) ;; 2 (check-eq? (count-transfers orbit-recs) 382) ;; alternate solution, using only lists (define orbit-dict (for/list ([rec (in-list orbit-recs)]) (cons (second rec) (first rec)))) (define orbit-chains ;; path from each object back to 'COM (for/list ([orbiter (in-dict-keys orbit-dict)]) (let loop ([chain (list orbiter)]) (match (assq (car chain) orbit-dict) [#false (reverse chain)] [(app cdr dest) (loop (cons dest chain))])))) ;; 1 ;; orbit count is one less than the length of each chain (check-eq? (apply + (map sub1 (map length orbit-chains))) 261306) (define you-chain (assq 'YOU orbit-chains)) (define san-chain (assq 'SAN orbit-chains)) (define common-tail (take-common-prefix (reverse you-chain) (reverse san-chain))) ;; 2 ;; answer path is two less than the length of path between YOU and SAN (check-eq? (- (+ (- (length you-chain) (length common-tail)) (- (length san-chain) (length common-tail))) 2) 382)