aboutsummaryrefslogtreecommitdiff
path: root/aoc2023-racket/day-23/day-23.rkt
diff options
context:
space:
mode:
Diffstat (limited to 'aoc2023-racket/day-23/day-23.rkt')
-rw-r--r--aoc2023-racket/day-23/day-23.rkt89
1 files changed, 0 insertions, 89 deletions
diff --git a/aoc2023-racket/day-23/day-23.rkt b/aoc2023-racket/day-23/day-23.rkt
deleted file mode 100644
index c048013..0000000
--- a/aoc2023-racket/day-23/day-23.rkt
+++ /dev/null
@@ -1,89 +0,0 @@
-#lang racket
-
-(require advent-of-code
- threading
- graph)
-
-(define input (fetch-aoc-input (find-session) 2023 23 #:cache #true))
-(define trails
- (for*/hash ([(row r) (in-indexed (string-split input "\n"))]
- [(col c) (in-indexed row)]
- #:when (not (equal? col #\#)))
- ; for now, we don't actually need to detect paths and slopes, just not-rocks
- ; in part 1, all forks in the road go right or down, so we can just infer the path
- ; direction from the shape of the junction and form a network of junctions from there
- ; in part 2, the slopes are removed anyway
- (values (cons (add1 r) (add1 c)) col)))
-
-(define max-row (~> input (string-split "\n") length))
-
-(define start (findf (λ (p) (= (car p) 1)) (hash-keys trails)))
-(define end (findf (λ (p) (= (car p) max-row)) (hash-keys trails)))
-
-(define (get-neighbors posn type)
- (match-define (cons r c) posn)
- (match type
- ['junction
- (~> (set (cons (add1 r) c) (cons r (add1 c))))]
- [_
- (~> (list (cons (add1 r) c) (cons (sub1 r) c) (cons r (add1 c)) (cons r (sub1 c)))
- (filter (curry hash-has-key? trails) _)
- list->set)]))
-
-(define junction-points
- (for/set ([(k v) (in-hash trails)]
- #:when (not (= (set-count (get-neighbors k v)) 2)))
- k))
-
-(define trails-with-junctions
- (for/hash ([k (in-hash-keys trails)])
- (cond
- [(set-member? junction-points k) (values k 'junction)]
- [else (values k 'trail)])))
-
-(define (walk-to-next-junction start current [length 1] [seen (set start)])
- (define next (~> current
- (get-neighbors _ 'trail)
- (set-subtract seen) set-first))
- (cond
- [(equal? (hash-ref trails-with-junctions next) 'junction)
- (list (- (add1 length)) start next)] ; weird format is due to graph library
- [else
- (walk-to-next-junction start next (add1 length) (set-add seen current))]))
-
-(define routes-to-junctions
- (for*/list ([j (in-set junction-points)]
- [neighbor (in-set (get-neighbors j 'junction))]
- #:when (hash-has-key? trails neighbor))
- (walk-to-next-junction j neighbor)))
-
-;; part 1 -- using graph library for Bellman-Ford on negative weighted graph
-;; Bellman-Ford finds the shortest path, but negating all the path weights
-;; will give us the longest path instead
-;;
-;; unlike Dijkstra which can't handle negative path lengths, Bellman-Ford
-;; works as long as the graph is currently directed and acyclic
-(define slippery-trail (weighted-graph/directed routes-to-junctions))
-(match-define-values (distances _) (bellman-ford slippery-trail start))
-(- (hash-ref distances end))
-
-;; part 2 -- rolling my own DFS that can reject seen junctions and dead ends
-(define routes-to-junctions-with-traction
- (for/fold ([trails (hash)]) ([route (in-list routes-to-junctions)])
- (match-define (list (app - weight) from to) route)
- (~> trails
- (hash-update _ from (curry cons (cons to weight)) '())
- (hash-update _ to (curry cons (cons from weight)) '()))))
-
-(define (dfs g from to [acc 0] [seen (set from)])
- (cond
- [(equal? from to) acc]
- [else
- (define choices (filter (λ (path) (not (set-member? seen (car path)))) (hash-ref g from)))
- (if (empty? choices) 0 ; long dead-ends don't count
- (for/fold ([best acc])
- ([path (in-list choices)]
- #:do [(match-define (cons next dist) path)])
- (max best (dfs g next to (+ acc dist) (set-add seen next)))))]))
-
-(dfs routes-to-junctions-with-traction start end) \ No newline at end of file