|
1 | 1 | #lang typed/racket
|
| 2 | +(require (only-in racket/unsafe/ops [unsafe-fx+ +] [unsafe-fxmax max])) |
2 | 3 |
|
3 |
| -(struct route ([dest : Integer] [cost : Integer]) #:transparent) |
| 4 | +(struct route ([dest : node] [cost : Integer]) #:transparent) |
| 5 | +(struct node ([neighbours : (Listof route)] [visited? : Boolean]) #:transparent #:mutable) |
4 | 6 |
|
5 |
| -(struct node ([neighbours : (Listof route)]) #:transparent) |
6 |
| - |
7 |
| -(: str->int (String -> Integer)) |
8 |
| -(define (str->int str) |
9 |
| - (define n (string->number str)) |
10 |
| - (if n (numerator (inexact->exact (real-part n))) 0)) |
11 |
| - |
12 |
| -(: read-places (-> (Vectorof node))) |
| 7 | +(: read-places : -> node) |
13 | 8 | (define (read-places)
|
14 |
| - (define lines |
15 |
| - (file->lines "agraph")) |
| 9 | + (define (str->int [str : String]) |
| 10 | + (assert (string->number str) exact-integer?)) |
| 11 | + (define lines (file->lines "agraph")) |
16 | 12 | (define num-lines (str->int (car lines)))
|
17 |
| - (define nodes (build-vector num-lines (lambda (n) (node `())))) |
18 |
| - (let loop ([i : Integer 0]) |
19 |
| - (define nums (string-split (list-ref (cdr lines) i))) |
20 |
| - (define len (length nums)) |
21 |
| - (when (and (> len 2) (> (length lines) (+ i 2))) |
22 |
| - (let ([node-id (str->int (list-ref nums 0))] |
23 |
| - [neighbour (str->int (list-ref nums 1))] |
24 |
| - [cost (str->int (list-ref nums 2))]) |
25 |
| - (define new-node (node |
26 |
| - (append (node-neighbours (vector-ref nodes node-id)) |
27 |
| - (list (route neighbour cost))))) |
28 |
| - (vector-set! nodes node-id new-node) |
29 |
| - (loop (+ i 1))))) |
30 |
| - nodes) |
| 13 | + (define nodes (build-vector num-lines (λ (n) (node '() #f)))) |
| 14 | + (for ([3nums (in-list (rest lines))]) |
| 15 | + (define nums (map str->int (string-split 3nums))) |
| 16 | + (define node (vector-ref nodes (first nums))) |
| 17 | + (define neighbour (vector-ref nodes (second nums))) |
| 18 | + (define cost (third nums)) |
| 19 | + (set-node-neighbours! node (cons (route neighbour (assert cost fixnum?)) |
| 20 | + (node-neighbours node)))) |
| 21 | + (vector-ref nodes 0)) |
31 | 22 |
|
32 |
| -(: get-longest-path ((Vectorof node) Integer (Vectorof Boolean) -> Integer)) |
33 |
| -(define (get-longest-path nodes node-id visited) |
34 |
| - (vector-set! visited node-id #t) |
35 |
| - (define sum |
36 |
| - (for/fold ([max-acc : Integer 0]) |
37 |
| - ;; `in-list` significantly speeds things up here |
38 |
| - ([neighbour (in-list (node-neighbours (vector-ref nodes node-id)))] |
39 |
| - #:unless (vector-ref visited (route-dest neighbour))) |
40 |
| - (max max-acc |
41 |
| - (+ (route-cost neighbour) (get-longest-path nodes (route-dest neighbour) visited))))) |
42 |
| - (vector-set! visited node-id #f) |
43 |
| - sum) |
| 23 | +(: get-longest-path : node -> Fixnum) |
| 24 | +(define (get-longest-path node) |
| 25 | + (set-node-visited?! node #t) |
| 26 | + (begin0 |
| 27 | + (for/fold ([best : Fixnum 0]) |
| 28 | + ([neighbour (in-list (node-neighbours node))] |
| 29 | + #:unless (node-visited? (route-dest neighbour))) |
| 30 | + (max best (+ (route-cost neighbour) |
| 31 | + (get-longest-path (route-dest neighbour))))) |
| 32 | + (set-node-visited?! node #f))) |
44 | 33 |
|
45 |
| -(define nodes (read-places)) |
46 |
| -(define visited : (Vectorof Boolean) (build-vector (vector-length nodes) (lambda (n) #f))) |
| 34 | +(define root (read-places)) |
47 | 35 | (define start (current-inexact-milliseconds))
|
48 |
| -(define len (get-longest-path nodes 0 visited)) |
| 36 | +(define len (get-longest-path root)) |
49 | 37 | (define duration (- (current-inexact-milliseconds) start))
|
50 |
| -(printf "~a LANGUAGE Racket ~a\n" len (inexact->exact (floor duration))) |
| 38 | +(printf "~a LANGUAGE Racket ~a\n" len (inexact->exact (floor duration))) |
0 commit comments