Day 20: Part 1 and 2
Signed-off-by: James Griffin <james@unsupervised.ca>
This commit is contained in:
10
main.go
10
main.go
@@ -3,7 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/thatguygriff/aoc2020/nineteen"
|
"github.com/thatguygriff/aoc2020/twenty"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -80,6 +80,10 @@ func main() {
|
|||||||
// fmt.Println(eighteen.PartTwo())
|
// fmt.Println(eighteen.PartTwo())
|
||||||
|
|
||||||
// Day 19
|
// Day 19
|
||||||
fmt.Println(nineteen.PartOne())
|
// fmt.Println(nineteen.PartOne())
|
||||||
fmt.Println(nineteen.PartTwo())
|
// fmt.Println(nineteen.PartTwo())
|
||||||
|
|
||||||
|
// Day 20
|
||||||
|
fmt.Println(twenty.PartOne())
|
||||||
|
fmt.Println(twenty.PartTwo())
|
||||||
}
|
}
|
||||||
|
599
twenty/day_twenty.go
Normal file
599
twenty/day_twenty.go
Normal file
@@ -0,0 +1,599 @@
|
|||||||
|
package twenty
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type tile struct {
|
||||||
|
id int
|
||||||
|
something [][]bool
|
||||||
|
|
||||||
|
edges []string
|
||||||
|
matches map[int]bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type message struct {
|
||||||
|
tiles []tile
|
||||||
|
grid [][]*tile
|
||||||
|
|
||||||
|
image [][]bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *tile) edge(side string) string {
|
||||||
|
border := ""
|
||||||
|
switch side {
|
||||||
|
case "top":
|
||||||
|
for _, c := range t.something[0] {
|
||||||
|
if c {
|
||||||
|
border += "#"
|
||||||
|
} else {
|
||||||
|
border += "."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "bottom":
|
||||||
|
for _, c := range t.something[9] {
|
||||||
|
if c {
|
||||||
|
border += "#"
|
||||||
|
} else {
|
||||||
|
border += "."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "left":
|
||||||
|
for _, row := range t.something {
|
||||||
|
if row[0] {
|
||||||
|
border += "#"
|
||||||
|
} else {
|
||||||
|
border += "."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "right":
|
||||||
|
for _, row := range t.something {
|
||||||
|
if row[9] {
|
||||||
|
border += "#"
|
||||||
|
} else {
|
||||||
|
border += "."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return border
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *tile) flip() {
|
||||||
|
flipped := [][]bool{}
|
||||||
|
flipped = make([][]bool, 10)
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
flipped[i] = make([]bool, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
for y := 0; y < 10; y++ {
|
||||||
|
for x := 0; x < 10; x++ {
|
||||||
|
flipped[y][x] = t.something[9-y][9-x]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t.something = flipped
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *tile) flipY() {
|
||||||
|
flipped := [][]bool{}
|
||||||
|
flipped = make([][]bool, 10)
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
flipped[i] = make([]bool, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
for y := 0; y < 10; y++ {
|
||||||
|
for x := 0; x < 10; x++ {
|
||||||
|
flipped[y][x] = t.something[9-y][x]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t.something = flipped
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *tile) rotate() {
|
||||||
|
rotated := [][]bool{}
|
||||||
|
rotated = make([][]bool, 10)
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
rotated[i] = make([]bool, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
for y := 0; y < 10; y++ {
|
||||||
|
for x := 0; x < 10; x++ {
|
||||||
|
rotated[x][9-y] = t.something[y][x]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t.something = rotated
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *message) load(filename string) error {
|
||||||
|
file, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
m.tiles = []tile{}
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(file)
|
||||||
|
var t *tile
|
||||||
|
for scanner.Scan() {
|
||||||
|
if strings.Contains(scanner.Text(), "Tile") {
|
||||||
|
t = &tile{}
|
||||||
|
count, err := fmt.Sscanf(scanner.Text(), "Tile %4d:", &t.id)
|
||||||
|
|
||||||
|
if count != 1 || err != nil {
|
||||||
|
return fmt.Errorf("Unable to parse %s", scanner.Text())
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if scanner.Text() == "" {
|
||||||
|
m.tiles = append(m.tiles, *t)
|
||||||
|
t = nil
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if t != nil {
|
||||||
|
row := []bool{}
|
||||||
|
for _, c := range scanner.Text() {
|
||||||
|
switch string(c) {
|
||||||
|
case ".":
|
||||||
|
row = append(row, false)
|
||||||
|
case "#":
|
||||||
|
row = append(row, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t.something = append(t.something, row)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if t != nil {
|
||||||
|
m.tiles = append(m.tiles, *t)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(m.tiles); i++ {
|
||||||
|
m.tiles[i].matches = map[int]bool{}
|
||||||
|
m.tiles[i].edges = []string{}
|
||||||
|
m.tiles[i].edges = append(m.tiles[i].edges, m.tiles[i].edge("top"))
|
||||||
|
m.tiles[i].edges = append(m.tiles[i].edges, m.tiles[i].edge("bottom"))
|
||||||
|
m.tiles[i].edges = append(m.tiles[i].edges, m.tiles[i].edge("left"))
|
||||||
|
m.tiles[i].edges = append(m.tiles[i].edges, m.tiles[i].edge("right"))
|
||||||
|
m.tiles[i].flip()
|
||||||
|
m.tiles[i].edges = append(m.tiles[i].edges, m.tiles[i].edge("top"))
|
||||||
|
m.tiles[i].edges = append(m.tiles[i].edges, m.tiles[i].edge("bottom"))
|
||||||
|
m.tiles[i].edges = append(m.tiles[i].edges, m.tiles[i].edge("left"))
|
||||||
|
m.tiles[i].edges = append(m.tiles[i].edges, m.tiles[i].edge("right"))
|
||||||
|
m.tiles[i].flip()
|
||||||
|
}
|
||||||
|
|
||||||
|
gridSize := int(math.Sqrt(float64(len(m.tiles))))
|
||||||
|
m.grid = make([][]*tile, gridSize)
|
||||||
|
for i := 0; i < gridSize; i++ {
|
||||||
|
m.grid[i] = make([]*tile, gridSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
m.image = make([][]bool, gridSize*8)
|
||||||
|
for i := 0; i < gridSize*8; i++ {
|
||||||
|
m.image[i] = make([]bool, gridSize*8)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *message) findCorners() []tile {
|
||||||
|
// Compute neighbours
|
||||||
|
for i := 0; i < len(m.tiles); i++ {
|
||||||
|
for j := 0; j < len(m.tiles); j++ {
|
||||||
|
if i == j {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, iEdge := range m.tiles[i].edges {
|
||||||
|
for _, jEdge := range m.tiles[j].edges {
|
||||||
|
if iEdge == jEdge {
|
||||||
|
m.tiles[i].matches[m.tiles[j].id] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
corners := []tile{}
|
||||||
|
// Find neighbours with only 2 matches
|
||||||
|
for i := 0; i < len(m.tiles); i++ {
|
||||||
|
if len(m.tiles[i].matches) == 2 {
|
||||||
|
corners = append(corners, m.tiles[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return corners
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *message) getTile(id int) *tile {
|
||||||
|
for _, t := range m.tiles {
|
||||||
|
if t.id == id {
|
||||||
|
return &t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *message) inGrid(id int) bool {
|
||||||
|
for y := 0; y < len(m.grid); y++ {
|
||||||
|
for x := 0; x < len(m.grid); x++ {
|
||||||
|
if m.grid[y][x] != nil {
|
||||||
|
if id == m.grid[y][x].id {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *message) layout() bool {
|
||||||
|
corners := m.findCorners()
|
||||||
|
for i := range corners {
|
||||||
|
m.grid[0][0] = &corners[i]
|
||||||
|
if m.placeNeighbours(0, 0) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
m.grid[0][0] = &corners[i]
|
||||||
|
m.grid[0][0].rotate()
|
||||||
|
if m.placeNeighbours(0, 0) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
m.grid[0][0] = &corners[i]
|
||||||
|
m.grid[0][0].rotate()
|
||||||
|
if m.placeNeighbours(0, 0) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
m.grid[0][0] = &corners[i]
|
||||||
|
m.grid[0][0].rotate()
|
||||||
|
if m.placeNeighbours(0, 0) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
m.grid[0][0] = &corners[i]
|
||||||
|
m.grid[0][0].rotate()
|
||||||
|
m.grid[0][0].flip()
|
||||||
|
if m.placeNeighbours(0, 0) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
m.grid[0][0] = &corners[i]
|
||||||
|
m.grid[0][0].rotate()
|
||||||
|
if m.placeNeighbours(0, 0) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
m.grid[0][0] = &corners[i]
|
||||||
|
m.grid[0][0].rotate()
|
||||||
|
if m.placeNeighbours(0, 0) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
m.grid[0][0] = &corners[i]
|
||||||
|
m.grid[0][0].rotate()
|
||||||
|
if m.placeNeighbours(0, 0) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *message) placeNeighbours(x, y int) bool {
|
||||||
|
allGood := true
|
||||||
|
|
||||||
|
if x+1 >= len(m.grid) && y+1 >= len(m.grid) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
possibleTiles := []tile{}
|
||||||
|
for id := range m.grid[y][x].matches {
|
||||||
|
if !m.inGrid(id) {
|
||||||
|
possibleTiles = append(possibleTiles, *m.getTile(id))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if x+1 < len(m.grid) {
|
||||||
|
if m.grid[y][x+1] == nil {
|
||||||
|
right := m.grid[y][x].edge("right")
|
||||||
|
found := false
|
||||||
|
for _, p := range possibleTiles {
|
||||||
|
for _, match := range p.edges {
|
||||||
|
if match == right {
|
||||||
|
found = true
|
||||||
|
rfound := false
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
if right == p.edge("left") {
|
||||||
|
found = true
|
||||||
|
rfound = true
|
||||||
|
m.grid[y][x+1] = &p
|
||||||
|
allGood = m.placeNeighbours(x+1, y)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
p.rotate()
|
||||||
|
}
|
||||||
|
if rfound {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
p.flipY()
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
if right == p.edge("left") {
|
||||||
|
found = true
|
||||||
|
m.grid[y][x+1] = &p
|
||||||
|
allGood = m.placeNeighbours(x+1, y)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
p.rotate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if found {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
allGood = found
|
||||||
|
} else {
|
||||||
|
allGood = m.grid[y][x].edge("right") == m.grid[y][x+1].edge("left")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if y+1 < len(m.grid) {
|
||||||
|
bottom := m.grid[y][x].edge("bottom")
|
||||||
|
found := false
|
||||||
|
for _, p := range possibleTiles {
|
||||||
|
for _, match := range p.edges {
|
||||||
|
if match == bottom {
|
||||||
|
found = true
|
||||||
|
rfound := false
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
if bottom == p.edge("top") {
|
||||||
|
found = true
|
||||||
|
rfound = true
|
||||||
|
m.grid[y+1][x] = &p
|
||||||
|
allGood = m.placeNeighbours(x, y+1)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
p.rotate()
|
||||||
|
}
|
||||||
|
if rfound {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
p.flipY()
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
if bottom == p.edge("top") {
|
||||||
|
found = true
|
||||||
|
m.grid[y+1][x] = &p
|
||||||
|
allGood = m.placeNeighbours(x, y+1)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
p.rotate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if found {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
allGood = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !allGood {
|
||||||
|
m.grid[y][x] = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return allGood
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *message) combineTiles() bool {
|
||||||
|
for y := 0; y < len(m.grid); y++ {
|
||||||
|
for x := 0; x < len(m.grid); x++ {
|
||||||
|
if m.grid[y][x] == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for y := 0; y < len(m.grid); y++ {
|
||||||
|
for x := 0; x < len(m.grid); x++ {
|
||||||
|
for tY := 1; tY < len(m.grid[y][x].something)-1; tY++ {
|
||||||
|
for tX := 1; tX < len(m.grid[y][x].something[tY])-1; tX++ {
|
||||||
|
imageY := (y * (len(m.grid[y][x].something) - 2)) + (tY - 1)
|
||||||
|
imageX := (x * (len(m.grid[y][x].something[tY]) - 2)) + (tX - 1)
|
||||||
|
m.image[imageY][imageX] = m.grid[y][x].something[tY][tX]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *message) rotateImage() {
|
||||||
|
rotated := [][]bool{}
|
||||||
|
rotated = make([][]bool, len(m.image))
|
||||||
|
for i := 0; i < len(m.image); i++ {
|
||||||
|
rotated[i] = make([]bool, len(m.image))
|
||||||
|
}
|
||||||
|
|
||||||
|
for y := 0; y < 10; y++ {
|
||||||
|
for x := 0; x < 10; x++ {
|
||||||
|
rotated[x][9-y] = m.image[y][x]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m.image = rotated
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *message) flipImage() {
|
||||||
|
flipped := [][]bool{}
|
||||||
|
flipped = make([][]bool, len(m.image))
|
||||||
|
for i := 0; i < len(m.image); i++ {
|
||||||
|
flipped[i] = make([]bool, len(m.image))
|
||||||
|
}
|
||||||
|
|
||||||
|
for y := 0; y < 10; y++ {
|
||||||
|
for x := 0; x < 10; x++ {
|
||||||
|
flipped[y][x] = m.image[9-y][x]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m.image = flipped
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *message) printGrid() {
|
||||||
|
output := ""
|
||||||
|
for y := 0; y < len(m.grid); y++ {
|
||||||
|
for tY := 0; tY < 10; tY++ {
|
||||||
|
for x := 0; x < len(m.grid[y]); x++ {
|
||||||
|
for tX := 0; tX < 10; tX++ {
|
||||||
|
if m.grid[y][x].something[tY][tX] {
|
||||||
|
output += "#"
|
||||||
|
} else {
|
||||||
|
output += "."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output += "\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf(output)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *message) printImage() {
|
||||||
|
output := ""
|
||||||
|
for _, row := range m.image {
|
||||||
|
for _, val := range row {
|
||||||
|
if val {
|
||||||
|
output += "#"
|
||||||
|
} else {
|
||||||
|
output += "."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output += "\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf(output)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *message) alignMonsters() bool {
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
count := m.seaMonsters()
|
||||||
|
if count > 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
m.rotateImage()
|
||||||
|
}
|
||||||
|
m.flipImage()
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
count := m.seaMonsters()
|
||||||
|
if count > 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
m.rotateImage()
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *message) cornerProduct() int {
|
||||||
|
corners := m.findCorners()
|
||||||
|
if len(corners) != 4 {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
product := 1
|
||||||
|
|
||||||
|
for _, tile := range corners {
|
||||||
|
product *= tile.id
|
||||||
|
}
|
||||||
|
|
||||||
|
return product
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *message) seaMonsters() int {
|
||||||
|
monsters := 0
|
||||||
|
for y := 0; y < len(m.image)-2; y++ {
|
||||||
|
for x := 0; x < len(m.image[0])-19; x++ {
|
||||||
|
// Check if this is a valid seamonster
|
||||||
|
if m.image[y][x+18] &&
|
||||||
|
m.image[y+1][x] &&
|
||||||
|
m.image[y+1][x+5] &&
|
||||||
|
m.image[y+1][x+6] &&
|
||||||
|
m.image[y+1][x+11] &&
|
||||||
|
m.image[y+1][x+12] &&
|
||||||
|
m.image[y+1][x+17] &&
|
||||||
|
m.image[y+1][x+18] &&
|
||||||
|
m.image[y+1][x+19] &&
|
||||||
|
m.image[y+2][x+1] &&
|
||||||
|
m.image[y+2][x+4] &&
|
||||||
|
m.image[y+2][x+7] &&
|
||||||
|
m.image[y+2][x+10] &&
|
||||||
|
m.image[y+2][x+13] &&
|
||||||
|
m.image[y+2][x+16] {
|
||||||
|
monsters++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return monsters
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *message) countRoughness() int {
|
||||||
|
monsters := m.seaMonsters() * 15
|
||||||
|
total := 0
|
||||||
|
for y := 0; y < len(m.image); y++ {
|
||||||
|
for x := 0; x < len(m.image[0]); x++ {
|
||||||
|
if m.image[y][x] {
|
||||||
|
total++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return total - monsters
|
||||||
|
}
|
||||||
|
|
||||||
|
// PartOne Find the product of the ids of the four corners
|
||||||
|
func PartOne() string {
|
||||||
|
m := message{}
|
||||||
|
if err := m.load("twenty/input.txt"); err != nil {
|
||||||
|
return err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("The product of the four corners is %d", m.cornerProduct())
|
||||||
|
}
|
||||||
|
|
||||||
|
// PartTwo How many # are not seamonsters.
|
||||||
|
func PartTwo() string {
|
||||||
|
m := message{}
|
||||||
|
if err := m.load("twenty/input.txt"); err != nil {
|
||||||
|
return err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
m.layout()
|
||||||
|
m.combineTiles()
|
||||||
|
m.alignMonsters()
|
||||||
|
|
||||||
|
return fmt.Sprintf("There are %d # that are not seamonsters", m.countRoughness())
|
||||||
|
}
|
75
twenty/day_twenty_test.go
Normal file
75
twenty/day_twenty_test.go
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
package twenty
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func Test_tile_load(t *testing.T) {
|
||||||
|
m := message{}
|
||||||
|
m.load("sample.txt")
|
||||||
|
|
||||||
|
if len(m.tiles) != 9 {
|
||||||
|
t.Logf("Expected 9 tiles to be loaded, got %d", len(m.tiles))
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(m.grid) != 3 && len(m.grid[0]) != 3 {
|
||||||
|
t.Logf("Expected a 3x3 grid, got %dx%d", len(m.grid), len(m.grid[0]))
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_arrange_tile(t *testing.T) {
|
||||||
|
m := message{}
|
||||||
|
m.load("sample.txt")
|
||||||
|
|
||||||
|
result := m.cornerProduct()
|
||||||
|
if result != 20899048083289 {
|
||||||
|
t.Logf("Expected a result of 20899048083289, got %d", result)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_arrange_input(t *testing.T) {
|
||||||
|
m := message{}
|
||||||
|
m.load("input.txt")
|
||||||
|
|
||||||
|
result := m.cornerProduct()
|
||||||
|
if result == -1 {
|
||||||
|
t.Logf("Expected a result other than -1, got %d", result)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_count_monsters(t *testing.T) {
|
||||||
|
m := message{}
|
||||||
|
m.load("sample.txt")
|
||||||
|
|
||||||
|
grid := m.layout()
|
||||||
|
if !grid {
|
||||||
|
t.Log("Expected a grid")
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
m.combineTiles()
|
||||||
|
m.alignMonsters()
|
||||||
|
|
||||||
|
result := m.seaMonsters()
|
||||||
|
if result != 2 {
|
||||||
|
t.Logf("Expected 2 monsters, found %d", result)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_count_roughness(t *testing.T) {
|
||||||
|
m := message{}
|
||||||
|
m.load("sample.txt")
|
||||||
|
|
||||||
|
m.layout()
|
||||||
|
m.combineTiles()
|
||||||
|
m.alignMonsters()
|
||||||
|
|
||||||
|
result := m.countRoughness()
|
||||||
|
if result != 273 {
|
||||||
|
t.Logf("Expected 273 # not part of a monster, found %d", result)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
1727
twenty/input.txt
Normal file
1727
twenty/input.txt
Normal file
File diff suppressed because it is too large
Load Diff
3
twenty/monster.txt
Normal file
3
twenty/monster.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
#
|
||||||
|
# ## ## ###
|
||||||
|
# # # # # #
|
107
twenty/sample.txt
Normal file
107
twenty/sample.txt
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
Tile 2311:
|
||||||
|
..##.#..#.
|
||||||
|
##..#.....
|
||||||
|
#...##..#.
|
||||||
|
####.#...#
|
||||||
|
##.##.###.
|
||||||
|
##...#.###
|
||||||
|
.#.#.#..##
|
||||||
|
..#....#..
|
||||||
|
###...#.#.
|
||||||
|
..###..###
|
||||||
|
|
||||||
|
Tile 1951:
|
||||||
|
#.##...##.
|
||||||
|
#.####...#
|
||||||
|
.....#..##
|
||||||
|
#...######
|
||||||
|
.##.#....#
|
||||||
|
.###.#####
|
||||||
|
###.##.##.
|
||||||
|
.###....#.
|
||||||
|
..#.#..#.#
|
||||||
|
#...##.#..
|
||||||
|
|
||||||
|
Tile 1171:
|
||||||
|
####...##.
|
||||||
|
#..##.#..#
|
||||||
|
##.#..#.#.
|
||||||
|
.###.####.
|
||||||
|
..###.####
|
||||||
|
.##....##.
|
||||||
|
.#...####.
|
||||||
|
#.##.####.
|
||||||
|
####..#...
|
||||||
|
.....##...
|
||||||
|
|
||||||
|
Tile 1427:
|
||||||
|
###.##.#..
|
||||||
|
.#..#.##..
|
||||||
|
.#.##.#..#
|
||||||
|
#.#.#.##.#
|
||||||
|
....#...##
|
||||||
|
...##..##.
|
||||||
|
...#.#####
|
||||||
|
.#.####.#.
|
||||||
|
..#..###.#
|
||||||
|
..##.#..#.
|
||||||
|
|
||||||
|
Tile 1489:
|
||||||
|
##.#.#....
|
||||||
|
..##...#..
|
||||||
|
.##..##...
|
||||||
|
..#...#...
|
||||||
|
#####...#.
|
||||||
|
#..#.#.#.#
|
||||||
|
...#.#.#..
|
||||||
|
##.#...##.
|
||||||
|
..##.##.##
|
||||||
|
###.##.#..
|
||||||
|
|
||||||
|
Tile 2473:
|
||||||
|
#....####.
|
||||||
|
#..#.##...
|
||||||
|
#.##..#...
|
||||||
|
######.#.#
|
||||||
|
.#...#.#.#
|
||||||
|
.#########
|
||||||
|
.###.#..#.
|
||||||
|
########.#
|
||||||
|
##...##.#.
|
||||||
|
..###.#.#.
|
||||||
|
|
||||||
|
Tile 2971:
|
||||||
|
..#.#....#
|
||||||
|
#...###...
|
||||||
|
#.#.###...
|
||||||
|
##.##..#..
|
||||||
|
.#####..##
|
||||||
|
.#..####.#
|
||||||
|
#..#.#..#.
|
||||||
|
..####.###
|
||||||
|
..#.#.###.
|
||||||
|
...#.#.#.#
|
||||||
|
|
||||||
|
Tile 2729:
|
||||||
|
...#.#.#.#
|
||||||
|
####.#....
|
||||||
|
..#.#.....
|
||||||
|
....#..#.#
|
||||||
|
.##..##.#.
|
||||||
|
.#.####...
|
||||||
|
####.#.#..
|
||||||
|
##.####...
|
||||||
|
##..#.##..
|
||||||
|
#.##...##.
|
||||||
|
|
||||||
|
Tile 3079:
|
||||||
|
#.#.#####.
|
||||||
|
.#..######
|
||||||
|
..#.......
|
||||||
|
######....
|
||||||
|
####.#..#.
|
||||||
|
.#...#.##.
|
||||||
|
#.#####.##
|
||||||
|
..#.###...
|
||||||
|
..#.......
|
||||||
|
..#.###...
|
Reference in New Issue
Block a user