Day 20, Part 2.

This commit is contained in:
Jonathan Chan 2020-12-20 12:02:02 -08:00
parent aba1e1dbfe
commit 181e53d81a
2 changed files with 252 additions and 22 deletions

96
input/20-image.txt Normal file
View File

@ -0,0 +1,96 @@
..........##.#..##..........#............#...#.....#..#......#.##...#.....#...#.....#..#....#.##
#.....#.###...#..#......#...##..#......#.......#.#.#.#...#.#.....#......#...#................#..
..###.#....#..#........###.....#.#............#.......#..##......#..#...#.#.......#....#.#...#..
..#............#.........##.##.......#....##......###.#.......................##.....#..........
........#.....##..#..............#........#.#..###...#....#..#.....#.......##...#..#.......#....
....##......#..####.#.###..............#..#.#....##..#...#..#.#.....#........##.................
#......#..##.#.........#O#.#.............#........#.............#.........#........#.....#......
....#.O....OO..##OO....OOO....###..........#..................#.......#..#..#.....#........#...#
..#....O..O.#O..O.#O..O..#......................#..##.......................##.....##.....#.....
.#.....###.....#......#..##....#.#............#.....#...#.#......#...#..#.....#..##.##........#.
#.#..#.##.........#.#..................##..#....#........#...##........#.......#.#...##.......##
....#..#.#.......#..#........#..#......#.....#.#...#.......O.#............#...#...#.#...........
..........#.#..###.....##...O.#......#...O.#..OO#...OO..#.OOO##....##..........##..##...........
......#...O##..OO.#.#OO#...OOO.....#.#....O..O#.O.#O..O..O....#.#..............................#
........#..O#.O.#O..O..O.#O.#.......#...#.#..#.......##...............#..#......................
#..##.......#.....#.##....#..#..##.....#..#..............................#.........#...#....#.#.
#................#.......#.#....##..........#....#.#.#..........#.......#.#.....###....#....##..
..#..#.#...#...#....#......##..#....#..........#............#.........#..#..#........#.......#..
.#.......#..#....##.#.......##.##..#.###.....#.#...##..................#..O....#..#.........#.#.
#.......##.....#....#.#.#...#.....#...........#.....#...O...#OO..#.OO....OOO.........####....#.#
.#......#.....#............#.....#.........#..#......##..O..O.#O..O#.O..O#...#...#.##.......#..#
....#.......#........#..........................##....................#...#............#........
......#...#........#......#O.#.....................#.........#....#..##...#........##..#.....#..
.##....#.O..#.OO.#..OO....OOO#.......#.......#...#...#..#......#.......#.#..............#.....##
....#.....O.#O..O..O.#O..O..#.##...#........#.......................#...........#....#.......#..
#..#....#.....##.....#........#..#.....#.#.........#..#.......##.............#.......#..##......
......#..#..........#.#.....##.#..#.........#..............#...##...#...#.......#..###......#.#.
........#........#.#..................................#.##.....#..#.#.#...........#.#...........
.......##.#..#......#.#........##O.#.#..................#..O......#.....#.....##......#.........
.........#..#..O..##OO..##OO....OOO.#....O....OO...#OO....OOO............#...#...##..#.........#
.....#.....#....O##O..O..O..O..O....#..#..O..O..O..O..O..O...................#...##....#.....#..
....###....#..#.#....#.....##..........#.#..##..........##.........#...#.........#..#...........
..........#....#.......#.#..#.#......#......#.#......#.#.#.......#...#.......###..............#.
.#.....#.##.....#....#................#............#...O#............#.........#....#.......#...
...##........#..#...................#O.#..OO#..#OO#...OOO..........##..#.###......#.....#.#.....
..#....#...#...........##..#.#....#...O..O..O..O..O..O#...#....#.......###..#....#.#......#.....
......#........#.#.#....##..#......#........##...#.#...................#..#.#....#..........#...
.......#.........#....#...##.##....#....#.#......#...#..........#.#....#....#...............##..
..........#.....#.........#..........#.#......#...#....##.............#...#.##.#......#.........
.....##.##......##..#.....#.....#....#.......#.#.....##.......##.....#....#.##.#..#.#O.....#..#.
..#.#....#...#..................#.#.............##........#........O....OO....OO#...OOO.........
...#.#...##.......#.........#...O.................#...#....#.#O....#O..O..O..O#.O.#O............
.#..#....#.#.#O....OO..#.OO....OOO.#........O....OO....OO..#.OOO.#....................#......#..
...#.#....#...#O..O.#O.#O..O..O..........#...O..O..O..O#.O..O..#.......#....#...#........#......
....................#............#...#.........###.......#.#.......#..#..#.#..#.#.#.O..#........
#........#...#..#.....................O.........#.......#..#.##...O..#.OO#...OO....OOO....#.....
..###.#...#.#.#..#.#O.#.#OO....OO....OOO#.#.#.....#.#....#.....#...O..O..O..O#.O..O#.....#...###
#..........#....####.O..O#.O..O..O#.O....#......#.#..#...##...#...#.#......##..........#..#.....
#.......#...##.#...............#..................#...#......#.....#.......#....................
........#...#.#......#..#.................#.#.#.............#....##.#.#.#.....#....#........#..#
..#..###..........#........#.#.#...#...#.....#...#..........#..#..#...##...........#............
..#.......#...#....#.............#.......#..........#..........#..#.#..##.#.#..#.......#.###....
........##.......#...#....#.........#..............#.....O#....#.##.#..#.#....#..#.#..#...#.O.#.
..#...#.......#....#.............#...##O#.##OO....OO....OOO......##......#O....OO....OO....OOO..
....................#...#.#.....##......O..O..O..O..O..O..................#O#.O..O#.O..O..O.....
...#.......#.#..........O....#......###....#.#.....#.#.##...........##............#.#...........
#.....O....OO....OO##..OOO..........#.................................##...#...#..##..#....###..
..##...O..O#.O..O..O..O###..#....##..#.....#.##...#..#.#...#..##......#.....#...##........#.....
....#.....#.....#.............##.............#.........#..#....#......O.......#.............#.#.
..#.......#........#.........#...#.#.......#....#...O.##.OO....OO....OOO......##...........#....
..#..#..#.......#..#...#.#......##...#.....#...##..#.O..O..O..O#.O..O..#......#.....#.#.......#.
......#..........#............#....#.#....#.................#.....#...#.....#.##........#..#...#
...##...........#............#..........#.......#.#...##..#...........................#.........
...#.#..............##..#.#.................#.#...........#..#...#.....................#.##..#..
....#...#......................#...##........##..#..#.........#........O........................
...#.#.#..#..............#........#.##...#...........O.#..OO.#..OO...#OOO...............#.#.#...
...#..#....#.........##......##................##.#...O.#O##O..O..O.#O.........#.......#..#..#..
...........#..#.#..........#.............####.##...#........#.#.......#..............#..#.......
....#..#.#....#.....#..#.......#..#.....O..#.....#.....#.#...#.........#.#..#....#........#.#..#
...#..............#...O..#.OO.##.OO....OOO......#...#......###..#...................###......#..
.#.........#.#.........O..O.#O..O#.O..O#........#.#.........#...#...........#......#..#.#..#....
##.#.........................#......##.......#.#.#.#.#......#..#....##......#......#......#.....
...##.#............##....##..##.#...#..............#..#.#......#..#........#........#......##..#
..#..#......#.............O#.#.#........................#.....#......#.....#.#.......#......#...
...#.#..O....OO..#.OO....OOO....#.....#......#....#.......#.#...............#.......O....#..#...
#.#...#..O.#O#.O#.O#.O#.O.......#...#....#.....##....#............O..#.OO#...OO....OOO.###......
..#.....#...#....#..#..#...#.#......#.....#.....#........#......#..O#.O.#O..O.#O..O..#.#...#..##
.#...#.....###...........................#..#..#....##.............#...#....#..#.....#...#......
##.#......#............#....#....#..#.#.#......#.....#..#...#.....##..#..#......................
..##......#...........O...........#..#.##...#O..........#.......#.#...........................#.
..#.O....OO...#OO....OOO...O..#.OO....OO.#.#OOO..#..#....#...##.....#.#.#..##.....#...#.........
.....O..O#.O..O..O..O.......O..O.#O.#O.#O..O##.##..##..........#...#.......#..#.#....#.......#..
#...#.........................#.............#..#....##.....#.#.............#....#.........#.....
.....................#.........#..#....#...#.#..#..#.....##......#..#..##....#..............##..
..#..#.#.......................##.....#......#.....##...........###.......#O....................
....#....#....................#..#..#.......O.##.........O....OO#...OO#..#OOO.#.##.....#....#...
..#...#.......#......##..#O...#OO....OO..#.OOO....#.....#.O..O..O..O..O..O...#...#..............
.#........#.......#........O..O.#O..O..O..O...#.#.......#..............#...#.......#..........#.
..#...#...........#...#..#..#.##.#..#..#..##..............#........#....#.#.............#.#.....
....#......#.....#......#....#...#...#....#.........#.....#..#.......#.####.#....#.........#....
.....#.#...#.#.#....#..##.....#......#.#....#.#.###..#....#.........#........##....#.......#....
#.............#....#....#........#.......#......O.........#..##........................#.....#..
............#..#..........#...O....OO....OO....OOO..#....#..##...#....#..........#..............
.#..........#.#.##.#...........O..O..O..O..O#.O........#.##.....#..#...#..#.......#......#....#.
.............#.....#.....#................###.#....#.......#...##.....#..#......###....#.....#..
.....#...............#....##......#.........#..............#............#....#..#.#......#.#....

View File

@ -4,37 +4,171 @@
(define input (map string-lines (problem-input-grouped 20)))
;; name: number?
;; image: image? = (listof (listof char?))
(struct tile (name image) #:transparent)
(define (parse-tile tile-strings)
(match-let ([`(,name ,rows ...) tile-strings])
(list (string->number (second (regexp-match #px"Tile (\\d+):" name)))
(tile (string->number (second (regexp-match #px"Tile (\\d+):" name)))
(map string->list rows))))
(define tiles
(map parse-tile input))
(define tiles (map parse-tile input))
(define dim (sqrt (length tiles)))
(define size (length (tile-image (first tiles))))
(define (tile-edges tile)
(match-let ([(list name rows) tile])
(list name (list (first rows)
(map last rows)
(reverse (last rows))
(reverse (map first rows))))))
;; Orientations (rotated and flipped)
(define (o1 image) image)
(define (o2 image) (reverse image))
(define (o3 image) (map reverse image))
(define (o4 image) (reverse (map reverse image)))
(define (o5 image) (map #{map (λ~> (list-ref %)) image} (range (length image))))
(define (o6 image) (map #{map (λ~> (list-ref %)) (reverse image)} (range (length image))))
(define (o7 image) (map #{map (λ~> (list-ref %)) image} (reverse (range (length image)))))
(define (o8 image) (map #{map (λ~> (list-ref %)) (reverse image)} (reverse (range (length image)))))
(define tiles-edges
(map tile-edges tiles))
;; Image fits top and left when not false, respectively
;; fit-image: image? (or/c (listof char?) #f) (or/c (listof char?) #f) -> (or/c image? #f)
(define (fit-image image t l)
(define (left image) (map first image))
(or (let ([i (o1 image)]) (and (or (not t) (equal? (first i) t)) (or (not l) (equal? (left i) l)) i))
(let ([i (o2 image)]) (and (or (not t) (equal? (first i) t)) (or (not l) (equal? (left i) l)) i))
(let ([i (o3 image)]) (and (or (not t) (equal? (first i) t)) (or (not l) (equal? (left i) l)) i))
(let ([i (o4 image)]) (and (or (not t) (equal? (first i) t)) (or (not l) (equal? (left i) l)) i))
(let ([i (o5 image)]) (and (or (not t) (equal? (first i) t)) (or (not l) (equal? (left i) l)) i))
(let ([i (o6 image)]) (and (or (not t) (equal? (first i) t)) (or (not l) (equal? (left i) l)) i))
(let ([i (o7 image)]) (and (or (not t) (equal? (first i) t)) (or (not l) (equal? (left i) l)) i))
(let ([i (o8 image)]) (and (or (not t) (equal? (first i) t)) (or (not l) (equal? (left i) l)) i))))
(define (corner? edges tiles)
(let ([tiles (map second tiles)])
(= 2 (count #{for/or ([target tiles])
(or (member % target)
(member (reverse %) target))}
edges))))
;; Tile's image fits top and left when not false, respectively
;; fit-tile: tile? (or/c (listof char?) #f) (or/c (listof char?) #f) -> (or/c tile? #f)
(define (fit-tile t top left)
(let ([image (fit-image (tile-image t) top left)])
(and image (struct-copy tile t [image image]))))
;; Given the 0th to (i-1)th tiles, counting left-to-right then top-to-bottom,
;; find the remaining ith to last tiles that fit in the dim x dim grid
;; build-image: (hashof (list number? number?) tile?) number? -> (hashof (list number? number?) tile?)
(define (build-image image tiles i)
(let* ([r (quotient i dim)]
[c (remainder i dim)]
[top-tile (and (> r 0) (hash-ref image (list (sub1 r) c)))]
[left-tile (and (> c 0) (hash-ref image (list r (sub1 c))))]
[top (and top-tile (last (tile-image top-tile)))]
[left (and left-tile (map last (tile-image left-tile)))])
(for/or ([tile tiles])
(let* ([tile* (fit-tile tile top left)]
[image (hash-set image (list r c) tile*)])
(and tile* (or (and (= (add1 i) (* dim dim)) image)
(build-image image (remove tile tiles) (add1 i))))))))
;; corner?: tile? -> boolean?
(define (corner? tile)
(define (edges tile)
(let ([image (tile-image tile)])
(list (first image) (last image)
(map first image) (map last image))))
(let ([tile-edges (edges tile)])
(= 2 (count #{for/or ([other (remove tile tiles)])
(let ([other-edges (edges other)])
(or (member % other-edges)
(member (reverse %) other-edges)))}
tile-edges))))
;; Find a corner piece
;; corner: tile?
(define corner
(for/first ([tile tiles]
#:when (corner? tile))
tile))
;; A mapping from positions in the layout to the correctly-oriented tile
;; (hashof (list number? number?) tile?)
(define image-hash
(let ([corner (λ (o) (struct-copy tile corner [image (o (tile-image corner))]))]
[tiles (remove corner tiles)])
(or (build-image (hash (list 0 0) (corner o1)) tiles 1)
(build-image (hash (list 0 0) (corner o2)) tiles 1)
(build-image (hash (list 0 0) (corner o3)) tiles 1)
(build-image (hash (list 0 0) (corner o4)) tiles 1))))
;; The full image with borders removed
;; image: (listof (listof char?))
(define image
(for/fold ([image '()]
#:result (o4 image))
([r dim])
(append image
(for/fold ([rows (make-list (- size 2) '())])
([c dim])
(let* ([image (tile-image (hash-ref image-hash (list r c)))]
[image (map #{drop-right (drop % 1) 1} (drop-right (drop image 1) 1))])
(map append rows image))))))
(define dimsize (length image))
(define image-vectors (lists->vectors image))
(define (vector-pos r c) (vector-ref (vector-ref image-vectors r) c))
#| (r, c) = O
#
# ## ## O## <--- friend
# # # # # #
|#
(define (sea-monster-coords r c)
(list `(,(- r 1) ,(+ c 1))
`(,r ,c)
`(,r ,(+ c 1))
`(,r ,(+ c 2))
`(,r ,(- c 5))
`(,r ,(- c 6))
`(,r ,(- c 11))
`(,r ,(- c 12))
`(,r ,(- c 17))
`(,(+ r 1) ,(- c 1))
`(,(+ r 1) ,(- c 4))
`(,(+ r 1) ,(- c 7))
`(,(+ r 1) ,(- c 10))
`(,(+ r 1) ,(- c 13))
`(,(+ r 1) ,(- c 16))))
;; sea-monster?: number? number? -> boolean?
(define (sea-monster? r c)
(define (pound? c) (char=? c #\#))
(andmap #{pound? (vector-pos (first %) (second %))}
(sea-monster-coords r c)))
;; A list of the neck coordinates of sea monsters
;; sea-monsters: (listof (list number? number?))
(define sea-monsters
(for*/list ([r (range 1 (sub1 dimsize))]
[c (range 17 (- dimsize 2))]
#:when (and (andmap #{char=? (vector-pos r %)}
(range c (+ c 3)))
(sea-monster? r c)))
(list r c)))
;; Replace the # of a sea monster with O in image-vectors
(define (reveal-sea-monster! r c)
(for-each #{vector-set! (vector-ref image-vectors (first %)) (second %) #\O}
(sea-monster-coords r c)))
;; Reveal the sea monsters in image-vectors, then write to file
(define (draw-sea-monsters!)
(for-each #{reveal-sea-monster! (first %) (second %)} sea-monsters)
(display-lines-to-file
(map (λ~> vector->list list->string)
(vector->list image-vectors))
"../input/20-image.txt"
#:exists 'replace))
(define part1
(for/product ([tile tiles-edges]
#:when (corner? (second tile)
(remove tile tiles-edges)))
(first tile)))
(* (tile-name (hash-ref image-hash (list 0 0)))
(tile-name (hash-ref image-hash (list 0 (sub1 dim))))
(tile-name (hash-ref image-hash (list (sub1 dim) 0)))
(tile-name (hash-ref image-hash (list (sub1 dim) (sub1 dim))))))
(define part2 #f)
(define part2
(- (count #{char=? % #\#} (apply append image))
(* (length sea-monsters) 15)))
(show-solution part1 part2)