Skip to content

Instantly share code, notes, and snippets.

@qookei
Created December 7, 2024 22:45
Show Gist options
  • Save qookei/e6e3a9da441d1bd4730287527399a10d to your computer and use it in GitHub Desktop.
Save qookei/e6e3a9da441d1bd4730287527399a10d to your computer and use it in GitHub Desktop.
(use-modules (srfi srfi-1) (srfi srfi-26) (ice-9 match) (ice-9 arrays)
(ice-9 receive) (ice-9 pretty-print) (ice-9 textual-ports))
(define (%read-input)
(let ([line (get-line (current-input-port))])
(if (eof-object? line)
'()
(cons (string->list line) (%read-input)))))
(define (read-input)
(list->array 2 (%read-input)))
(define (find-start input)
(let* ([height (cadr (array-dimensions input))]
[width (car (array-dimensions input))]
[limit (* width height)])
(let next ([i 0])
(if (eqv? i limit)
#f
(let ([y (quotient i width)]
[x (remainder i width)])
(if (eqv? #\^ (array-ref input y x))
(list y x)
(next (1+ i))))))))
(define (%next-rotation input y x dy dx)
(if (and (array-in-bounds? input (+ y dy) (+ x dx))
(eqv? (array-ref input (+ y dy) (+ x dx)) #\#))
(match (list dy dx)
[(-1 0) '( 0 1)]
[( 0 1) '( 1 0)]
[( 1 0) '( 0 -1)]
[( 0 -1) '(-1 0)]
[_ (error "illegal dy dx" dy dx)])
(list dy dx)))
(define (guard-visited-set input start-y start-x find-loops?)
(let ([visited-set (make-hash-table)]
[make-key (if find-loops?
(λ v v)
(λ (y x . _) (list y x)))])
(let next ([y start-y]
[x start-x]
[dy -1] [dx 0])
(if (or (not (array-in-bounds? input y x))
(and find-loops?
(hash-ref visited-set (make-key y x dy dx))))
(values
(hash-map->list (λ (k v) k) visited-set)
(hash-ref visited-set (make-key y x dy dx)))
(match-let ([(new-dy new-dx) (%next-rotation input y x dy dx)])
(hash-set! visited-set (make-key y x dy dx) #t)
(if (and (eqv? new-dy dy) (eqv? new-dx dx))
(next (+ y new-dy) (+ x new-dx) new-dy new-dx)
(next y x new-dy new-dx)))))))
(define (part2 input visited-set start-y start-x)
(count
(λ (yx)
(match-let ([(y x) yx])
(if (eqv? #\. (array-ref input y x))
(begin
(array-set! input #\# y x)
(receive [__ loop?]
(guard-visited-set input start-y start-x #t)
(array-set! input #\. y x)
loop?)
)
#f)))
visited-set))
(match-let* ([input (read-input)]
[(start-y start-x) (find-start input)]
[visited-set (guard-visited-set input start-y start-x #f)])
(pretty-print (length visited-set))
(pretty-print (part2 input visited-set start-y start-x)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment