|
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