advent-of-code

Perserverance, or the lack thereof

git clone git://git.shimmy1996.com/advent-of-code.git

day10.scm (6367B)

    1 (use-modules (ice-9 popen))
    2 (use-modules (ice-9 rdelim))
    3 (use-modules (ice-9 format))
    4 (use-modules (ice-9 receive))
    5 (use-modules (ice-9 hash-table))
    6 (use-modules (ice-9 match))
    7 (use-modules (srfi srfi-1))
    8 
    9 (define (parse-input filename)
   10   (let ((file (open-input-file filename))
   11         (tiles '()))
   12     (while #t
   13            (let ((line (car (%read-line file))))
   14              (if (eof-object? line)
   15                  (break)
   16                  (set! tiles (cons (string->list line) tiles)))))
   17     (reverse tiles)))
   18 
   19 (define (parse-pipes tiles)
   20   (let ((connections (make-hash-table))
   21         (double-connections (make-hash-table))
   22         (start '())
   23         (y-max (length tiles))
   24         (x-max (length (car tiles))))
   25     (do ((y 0 (1+ y))) ((>= y y-max))
   26       (do ((x 0 (1+ x))) ((>= x x-max))
   27         (let ((c (list-ref (list-ref tiles y) x)))
   28           (case c
   29             ((#\|)
   30              (begin (hash-set! connections (list (cons x y) (cons x (1- y))) #t)
   31                     (hash-set! connections (list (cons x y) (cons x (1+ y))) #t)))
   32             ((#\-)
   33              (begin (hash-set! connections (list (cons x y) (cons (1+ x) y)) #t)
   34                     (hash-set! connections (list (cons x y) (cons (1- x) y)) #t)))
   35             ((#\L)
   36              (begin (hash-set! connections (list (cons x y) (cons x (1- y))) #t)
   37                     (hash-set! connections (list (cons x y) (cons (1+ x) y)) #t)))
   38             ((#\J)
   39              (begin (hash-set! connections (list (cons x y) (cons x (1- y))) #t)
   40                     (hash-set! connections (list (cons x y) (cons (1- x) y)) #t)))
   41             ((#\7)
   42              (begin (hash-set! connections (list (cons x y) (cons x (1+ y))) #t)
   43                     (hash-set! connections (list (cons x y) (cons (1- x) y)) #t)))
   44             ((#\F)
   45              (begin (hash-set! connections (list (cons x y) (cons x (1+ y))) #t)
   46                     (hash-set! connections (list (cons x y) (cons (1+ x) y)) #t)))
   47             ((#\S) (set! start (cons x y)))
   48             (else '())))))
   49     (hash-for-each
   50      (lambda (k v)
   51        (let ((a (car k))
   52              (b (car (cdr k))))
   53          (if (or (hash-ref connections (list b a)) (equal? b start))
   54              (begin (hash-set! double-connections a (cons b (hash-ref double-connections a '())))
   55                     (if (equal? b start)
   56                         (hash-set! double-connections b (cons a (hash-ref double-connections b '()))))))))
   57      connections)
   58     (for-each
   59      (lambda (x) (hash-set! connections (list start x) #t))
   60      (hash-ref double-connections start))
   61     (let* ((up-conn (hash-ref connections (list start (cons (+ (car start) 0) (+ (cdr start) -1)))))
   62            (down-conn (hash-ref connections (list start (cons (+ (car start) 0) (+ (cdr start) 1)))))
   63            (left-conn (hash-ref connections (list start (cons (+ (car start) -1) (+ (cdr start) 0)))))
   64            (right-conn (hash-ref connections (list start (cons (+ (car start) 1) (+ (cdr start) 0)))))
   65            (conns (list up-conn down-conn left-conn right-conn))
   66            (start-tile (cond
   67                         ((equal? conns (list #t #t #f #f)) #\|)
   68                         ((equal? conns (list #t #f #t #f)) #\J)
   69                         ((equal? conns (list #t #f #f #t)) #\L)
   70                         ((equal? conns (list #f #t #t #f)) #\7)
   71                         ((equal? conns (list #f #t #f #t)) #\F)
   72                         ((equal? conns (list #f #f #t #t)) #\-))))
   73       (list-set! (list-ref tiles (cdr start)) (car start) start-tile))
   74     (values start double-connections tiles)))
   75 
   76 (define (find-furthest start double-connections)
   77   (let ((dist (make-hash-table))
   78         (queue (list start))
   79         (steps 0))
   80     (hash-set! dist start steps)
   81     (let ((queue-next '()))
   82       (while #t
   83              (set! steps (1+ steps))
   84              (for-each
   85               (lambda (curr)
   86                 (for-each
   87                  (lambda (next)
   88                    (if (not (hash-ref dist next))
   89                        (begin (hash-set! dist next steps)
   90                               (set! queue-next (cons next queue-next)))))
   91                  (hash-ref double-connections curr)))
   92               queue)
   93              (if (null? queue-next)
   94                  (break))
   95              (set! queue queue-next)
   96              (set! queue-next '())))
   97     (let ((max-steps (1- steps)))
   98       (values max-steps dist))))
   99 
  100 (define (count-wall-to-edge tiles dist curr count)
  101   (let* ((y-max (length tiles))
  102          (x-max (length (car tiles)))
  103          (dx 0)
  104          (dy 1)
  105          (next (cons (+ (car curr) dx) (+ (cdr curr) dy)))
  106          (in-range (and (and (>= (car next) 0) (< (car next) x-max))
  107                         (and (>= (cdr next) 0) (< (cdr next) y-max))))
  108          (in-loop (hash-ref dist next)))
  109     (if in-range
  110         (begin
  111           (if in-loop
  112               (let ((next-pipe (list-ref (list-ref tiles (cdr next)) (car next))))
  113                 (set! count
  114                       (+ count (case next-pipe
  115                                  ((#\J) 1)
  116                                  ((#\F) 0)
  117                                  ((#\7) 1)
  118                                  ((#\L) 0)
  119                                  ((#\-) 1)
  120                                  ((#\|) 0))))))
  121           (count-wall-to-edge tiles dist next count))
  122         count)))
  123 
  124 (define (in-nest tiles dist curr)
  125   (let ((wall-count (count-wall-to-edge tiles dist curr 0)))
  126     (= (floor-remainder wall-count 2) 1)))
  127 
  128 (define (get-candidates dist tiles)
  129   (let ((y-max (length tiles))
  130         (x-max (length (car tiles)))
  131         (candidates '()))
  132     (do ((y 0 (1+ y))) ((>= y y-max))
  133       (do ((x 0 (1+ x))) ((>= x x-max))
  134         (if (not (hash-ref dist (cons x y)))
  135             (set! candidates (cons (cons x y) candidates)))))
  136     candidates))
  137 
  138 (let* ((tiles (parse-input "input.txt")))
  139   (receive (start double-connections tiles-patched) (parse-pipes tiles)
  140     (receive (max-dist dist) (find-furthest start double-connections)
  141       ;; 6856
  142       (format #t "Part 1: ~d" max-dist)
  143       (newline)
  144       (let* ((candidates (get-candidates dist tiles-patched))
  145              (nest-tiles (filter
  146                           (lambda (curr) (in-nest tiles-patched dist curr))
  147                           candidates)))
  148         ;; 501
  149         (format #t "Part 2: ~d" (length nest-tiles))
  150         (newline)))))