day 20: okay this is some of the worst code ever..
This commit is contained in:
parent
12a57ad8b9
commit
4b2385c9c6
|
@ -0,0 +1,212 @@
|
|||
#lang curly-fn racket
|
||||
|
||||
(require "scripts/aoc.rkt")
|
||||
|
||||
;; solution for day 20
|
||||
|
||||
(define (tile->edges tile)
|
||||
(define n (for/vector ([x (in-range 10)])
|
||||
(vector-ref (vector-ref tile 0) x)))
|
||||
(define e (for/vector ([x (in-range 10)])
|
||||
(vector-ref (vector-ref tile x) 9)))
|
||||
(define s (for/vector ([x (in-range 10)])
|
||||
(vector-ref (vector-ref tile 9) x)))
|
||||
(define w (for/vector ([x (in-range 10)])
|
||||
(vector-ref (vector-ref tile x) 0)))
|
||||
(list e s w n))
|
||||
|
||||
(define (edge-match? e1 e2)
|
||||
(cond
|
||||
[(equal? e1 e2) 'match]
|
||||
[(equal? e1 (list->vector (reverse (vector->list e2)))) 'rev-match]
|
||||
[else #f]))
|
||||
|
||||
(define (input->graph input)
|
||||
(define ids (hash-keys input))
|
||||
(define meta (make-hash))
|
||||
(define edges
|
||||
(for*/list ([id1 (in-list ids)] [id2 (in-list ids)] #:unless (= id1 id2)
|
||||
[i1 (in-range 4)] [i2 (in-range 4)]
|
||||
[es1 (in-value (tile->edges (hash-ref input id1)))]
|
||||
[es2 (in-value (tile->edges (hash-ref input id2)))]
|
||||
[m (in-value (edge-match? (list-ref es1 i1) (list-ref es2 i2)))]
|
||||
#:when m)
|
||||
(hash-set! meta (cons id1 id2) (list i1 i2 m))
|
||||
(list id1 id2)))
|
||||
(values (undirected-graph edges) meta))
|
||||
|
||||
(define (part1 input)
|
||||
(define-values [G _] (input->graph input))
|
||||
(for/product ([v (in-vertices G)])
|
||||
(define nneigh (length (get-neighbors G v)))
|
||||
(if (= nneigh 2) v 1)))
|
||||
|
||||
(define (tile->string tile)
|
||||
(string-join (for/list ([x (in-vector tile)]) (list->string (vector->list x))) "\n"))
|
||||
|
||||
(define (rotate1 vec)
|
||||
(for/vector ([x (in-range (vector-length (vector-ref vec 0)))])
|
||||
(for/vector ([y (in-range (vector-length vec))])
|
||||
(vector-ref (vector-ref vec (- (vector-length vec) y 1)) x))))
|
||||
|
||||
(define (rotaten vec n)
|
||||
(for/fold ([vec vec]) ([i (in-range n)])
|
||||
(rotate1 vec)))
|
||||
|
||||
(define (flip-horiz vec)
|
||||
(for/vector ([y (in-range (vector-length vec))])
|
||||
(for/vector ([x (in-range (vector-length (vector-ref vec 0)))])
|
||||
(vector-ref (vector-ref vec y) (- (vector-length (vector-ref vec 0)) x 1)))))
|
||||
|
||||
(define (flip-vert vec)
|
||||
(for/vector ([y (in-range (vector-length vec))])
|
||||
(for/vector ([x (in-range (vector-length (vector-ref vec 0)))])
|
||||
(vector-ref (vector-ref vec (- (vector-length vec) y 1)) x))))
|
||||
|
||||
(define monster-in
|
||||
'(" # "
|
||||
"# ## ## ###"
|
||||
" # # # # # # "))
|
||||
(define monster
|
||||
(for/vector ([line (in-list monster-in)])
|
||||
(list->vector (string->list line))))
|
||||
|
||||
(define (part2 input)
|
||||
(define-values [G meta] (input->graph input))
|
||||
(define corners
|
||||
(for/list ([v (in-vertices G)] #:when (= 2 (length (get-neighbors G v)))) v))
|
||||
(define rows (make-vector 12 #f))
|
||||
(define used-verts (mutable-set))
|
||||
(define nextrow (for*/first ([cand (in-list (rest corners))]
|
||||
[path (in-value (fewest-vertices-path G (first corners) cand))]
|
||||
#:when (= 12 (length path)))
|
||||
path))
|
||||
(vector-set! rows 0 (list->vector nextrow))
|
||||
(set-union! used-verts (list->set nextrow))
|
||||
(for ([i (in-range 1 12)])
|
||||
(define l (first nextrow))
|
||||
(define r (last nextrow))
|
||||
(define lnext (for/first ([v (in-neighbors G l)] #:unless (set-member? used-verts v)) v))
|
||||
(define rnext (for/first ([v (in-neighbors G r)] #:unless (set-member? used-verts v)) v))
|
||||
(set! nextrow (fewest-vertices-path G lnext rnext))
|
||||
(vector-set! rows i (list->vector nextrow))
|
||||
(set-union! used-verts (list->set nextrow)))
|
||||
(pretty-write rows)
|
||||
(displayln (hash-ref meta (cons (vector-ref (vector-ref rows 0) 0)
|
||||
(vector-ref (vector-ref rows 0) 1))))
|
||||
(displayln (hash-ref meta (cons (vector-ref (vector-ref rows 0) 0)
|
||||
(vector-ref (vector-ref rows 1) 0))))
|
||||
(define corrected (make-hash))
|
||||
(define tl (vector-ref (vector-ref rows 0) 0))
|
||||
;; assume top left is oriented right...
|
||||
;; we tuned the parse to make it so
|
||||
(hash-set! corrected tl (hash-ref input tl))
|
||||
(displayln (tile->string (hash-ref input tl)))
|
||||
(displayln "meow")
|
||||
(for ([x (in-range 1 12)])
|
||||
(define v (vector-ref (vector-ref rows 0) x))
|
||||
(define left (vector-ref (vector-ref rows 0) (sub1 x)))
|
||||
(match-define (list rot _ __) (hash-ref meta (cons v left)))
|
||||
(define rotated (rotaten (hash-ref input v) (match rot
|
||||
[2 0]
|
||||
[3 3]
|
||||
[0 2]
|
||||
[1 1])))
|
||||
(define mt (edge-match? (first (tile->edges (hash-ref corrected left)))
|
||||
(third (tile->edges rotated))))
|
||||
(define flipped (if (symbol=? mt 'match) rotated (flip-vert rotated)))
|
||||
(hash-set! corrected v flipped)
|
||||
; (displayln (tile->string flipped))
|
||||
; (displayln "meow")
|
||||
(void))
|
||||
|
||||
(for* ([y (in-range 1 12)] [x (in-range 0 12)])
|
||||
(define v (vector-ref (vector-ref rows y) x))
|
||||
(define top (vector-ref (vector-ref rows (sub1 y)) x))
|
||||
(match-define (list rot _ __) (hash-ref meta (cons v top)))
|
||||
(define rotated (rotaten (hash-ref input v) (match rot
|
||||
[0 3]
|
||||
[1 2]
|
||||
[2 1]
|
||||
[3 0])))
|
||||
(define mt (edge-match? (second (tile->edges (hash-ref corrected top)))
|
||||
(fourth (tile->edges rotated))))
|
||||
(define flipped (if (symbol=? mt 'match) rotated (flip-horiz rotated)))
|
||||
(hash-set! corrected v flipped)
|
||||
; (displayln (tile->string flipped))
|
||||
; (dispalyln "meow")
|
||||
(void))
|
||||
|
||||
; (for* ([yt (in-range 12)] [yc (in-range 10)])
|
||||
; (when (zero? yc) (printf "\n"))
|
||||
; (displayln (string-join (for/list ([xt (in-range 12)])
|
||||
; (list->string
|
||||
; (vector->list
|
||||
; (vector-ref
|
||||
; (hash-ref corrected
|
||||
; (vector-ref (vector-ref rows yt) xt))
|
||||
; yc))))
|
||||
; " ")))
|
||||
|
||||
(define full-image
|
||||
(for/vector ([y (in-range 96)])
|
||||
(for/vector ([x (in-range 96)])
|
||||
(define yt (quotient y 8))
|
||||
(define xt (quotient x 8))
|
||||
(define yr (remainder y 8))
|
||||
(define xr (remainder x 8))
|
||||
(define tile (hash-ref corrected (vector-ref (vector-ref rows yt) xt)))
|
||||
(vector-ref (vector-ref tile (add1 yr)) (add1 xr)))))
|
||||
|
||||
(define (monster-match? check x y)
|
||||
(define coords (mutable-set))
|
||||
|
||||
(define match?
|
||||
(for*/and ([dy (in-range (vector-length check))]
|
||||
[dx (in-range (vector-length (vector-ref check 0)))])
|
||||
(cond
|
||||
[(char=? #\space (vector-ref (vector-ref check dy) dx)) #t]
|
||||
[(char=? #\# (vector-ref (vector-ref full-image (+ y dy)) (+ x dx)))
|
||||
(set-add! coords (cons (+ x dx) (+ y dy)))
|
||||
#t]
|
||||
[else #f])))
|
||||
(if match? coords #f))
|
||||
|
||||
(define monster-coords (mutable-set))
|
||||
(for* ([func (in-list (list identity flip-vert))]
|
||||
[rotation (in-range 4)])
|
||||
(define check (func (rotaten monster rotation)))
|
||||
(for* ([y (in-range (- 96 (vector-length check)))]
|
||||
[x (in-range (- 96 (vector-length (vector-ref check 0))))])
|
||||
(define match? (monster-match? check x y))
|
||||
(when match?
|
||||
(set-union! monster-coords match?))))
|
||||
|
||||
(define hashcount (for*/sum ([y (in-range 96)] [x (in-range 96)]
|
||||
#:when (char=? (vector-ref (vector-ref full-image y) x) #\#))
|
||||
1))
|
||||
|
||||
|
||||
(- hashcount (set-count monster-coords)))
|
||||
|
||||
;; parse input file
|
||||
(define (parse fname)
|
||||
(define inputs (string-split (file->string fname) "\n\n"))
|
||||
(for/hash ([input (in-list inputs)])
|
||||
(define lines (string-split input "\n"))
|
||||
(define id (string->number (substring (first lines) 5 (sub1 (string-length (first lines))))))
|
||||
(when (false? id) (error "not shonks" (first lines)))
|
||||
(values id (rotate1 (for/vector ([line (in-list (rest lines))])
|
||||
(list->vector (string->list line)))))))
|
||||
|
||||
|
||||
(module+ test
|
||||
(require rackunit)
|
||||
;; tests here
|
||||
(displayln "no tests :("))
|
||||
|
||||
(module+ main
|
||||
(define input (parse "inputs/20"))
|
||||
(answer 20 1 (time (part1 input)))
|
||||
(answer 20 2 (time (part2 input)))
|
||||
(displayln "meow"))
|
Loading…
Reference in New Issue