Day 22
This commit is contained in:
333
day22/common/forcefield.go
Normal file
333
day22/common/forcefield.go
Normal file
@@ -0,0 +1,333 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
type Tile byte
|
||||||
|
|
||||||
|
const (
|
||||||
|
None Tile = iota
|
||||||
|
Empty
|
||||||
|
Wall
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
type Direction byte
|
||||||
|
|
||||||
|
const (
|
||||||
|
East Direction = iota
|
||||||
|
West
|
||||||
|
North
|
||||||
|
South
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
type Traveler struct {
|
||||||
|
facing Direction
|
||||||
|
x int
|
||||||
|
y int
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type Map struct {
|
||||||
|
tiles [][]Tile
|
||||||
|
traveler Traveler
|
||||||
|
isCubic bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tileMap *Map) GetNextTile() (int, int, Direction) {
|
||||||
|
nextX := tileMap.traveler.x
|
||||||
|
nextY := tileMap.traveler.y
|
||||||
|
nextDirection := tileMap.traveler.facing
|
||||||
|
|
||||||
|
switch nextDirection {
|
||||||
|
case East:
|
||||||
|
if nextX + 1 < len(tileMap.tiles[nextY]) && tileMap.tiles[nextY][nextX+1] == Empty {
|
||||||
|
nextX++
|
||||||
|
} else if nextX + 1 == len(tileMap.tiles[nextY]) || tileMap.tiles[nextY][nextX+1] == None {
|
||||||
|
if tileMap.isCubic {
|
||||||
|
if nextX == 149 {
|
||||||
|
if tileMap.tiles[149-nextY][99] == Empty {
|
||||||
|
nextX = 99
|
||||||
|
nextY = 149 - nextY
|
||||||
|
nextDirection = West
|
||||||
|
}
|
||||||
|
} else if nextX == 99 && nextY < 100 {
|
||||||
|
if tileMap.tiles[49][nextY+50] == Empty {
|
||||||
|
nextX = nextY + 50
|
||||||
|
nextY = 49
|
||||||
|
nextDirection = North
|
||||||
|
}
|
||||||
|
} else if nextX == 99 {
|
||||||
|
if tileMap.tiles[149-nextY][149] == Empty {
|
||||||
|
nextX = 149
|
||||||
|
nextY = 149 - nextY
|
||||||
|
nextDirection = West
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if tileMap.tiles[149][nextY-100] == Empty {
|
||||||
|
nextX = nextY - 100
|
||||||
|
nextY = 149
|
||||||
|
nextDirection = North
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for i := 0; i < len(tileMap.tiles[nextY]); i++ {
|
||||||
|
if tileMap.tiles[nextY][i] != None {
|
||||||
|
if tileMap.tiles[nextY][i] == Empty {
|
||||||
|
nextX = i
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case West:
|
||||||
|
if nextX - 1 >= 0 && tileMap.tiles[nextY][nextX-1] == Empty {
|
||||||
|
nextX--
|
||||||
|
} else if nextX - 1 < 0 || tileMap.tiles[nextY][nextX-1] == None {
|
||||||
|
if tileMap.isCubic {
|
||||||
|
if nextX == 50 && nextY < 50 {
|
||||||
|
if tileMap.tiles[149-nextY][0] == Empty {
|
||||||
|
nextX = 0
|
||||||
|
nextY = 149 - nextY
|
||||||
|
nextDirection = East
|
||||||
|
}
|
||||||
|
} else if nextX == 50 {
|
||||||
|
if tileMap.tiles[100][nextY-50] == Empty {
|
||||||
|
nextX = nextY - 50
|
||||||
|
nextY = 100
|
||||||
|
nextDirection = South
|
||||||
|
}
|
||||||
|
} else if nextY < 150 {
|
||||||
|
if tileMap.tiles[149-nextY][50] == Empty {
|
||||||
|
nextX = 50
|
||||||
|
nextY = 149 - nextY
|
||||||
|
nextDirection = East
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if tileMap.tiles[0][nextY-100] == Empty {
|
||||||
|
nextX = nextY - 100
|
||||||
|
nextY = 0
|
||||||
|
nextDirection = South
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for i := len(tileMap.tiles[nextY]) - 1; i >= 0; i-- {
|
||||||
|
if tileMap.tiles[nextY][i] != None {
|
||||||
|
if tileMap.tiles[nextY][i] == Empty {
|
||||||
|
nextX = i
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case North:
|
||||||
|
if nextY - 1 >= 0 && tileMap.tiles[nextY-1][nextX] == Empty {
|
||||||
|
nextY--
|
||||||
|
} else if nextY - 1 < 0 || tileMap.tiles[nextY-1][nextX] == None {
|
||||||
|
if tileMap.isCubic {
|
||||||
|
if nextX < 50 {
|
||||||
|
if tileMap.tiles[nextX+50][50] == Empty {
|
||||||
|
nextY = nextX + 50
|
||||||
|
nextX = 50
|
||||||
|
nextDirection = East
|
||||||
|
}
|
||||||
|
} else if nextX < 100 {
|
||||||
|
if tileMap.tiles[nextX+100][0] == Empty {
|
||||||
|
nextY = nextX + 100
|
||||||
|
nextX = 0
|
||||||
|
nextDirection = East
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if tileMap.tiles[199][nextX-100] == Empty {
|
||||||
|
nextX = nextX - 100
|
||||||
|
nextY = 199
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for i := len(tileMap.tiles) - 1; i >= 0; i-- {
|
||||||
|
if tileMap.tiles[i][nextX] != None {
|
||||||
|
if tileMap.tiles[i][nextX] == Empty {
|
||||||
|
nextY = i
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case South:
|
||||||
|
if nextY + 1 < len(tileMap.tiles) && tileMap.tiles[nextY+1][nextX] == Empty {
|
||||||
|
nextY++
|
||||||
|
} else if nextY + 1 == len(tileMap.tiles) || tileMap.tiles[nextY+1][nextX] == None {
|
||||||
|
if tileMap.isCubic {
|
||||||
|
if nextX < 50 {
|
||||||
|
if tileMap.tiles[0][nextX+100] == Empty {
|
||||||
|
nextX = nextX + 100
|
||||||
|
nextY = 0
|
||||||
|
}
|
||||||
|
} else if nextX < 100 {
|
||||||
|
if tileMap.tiles[nextX+100][49] == Empty {
|
||||||
|
nextY = nextX + 100
|
||||||
|
nextX = 49
|
||||||
|
nextDirection = West
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if tileMap.tiles[nextX-50][99] == Empty {
|
||||||
|
nextY = nextX - 50
|
||||||
|
nextX = 99
|
||||||
|
nextDirection = West
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for i := 0; i < len(tileMap.tiles); i++ {
|
||||||
|
if tileMap.tiles[i][nextX] != None {
|
||||||
|
if tileMap.tiles[i][nextX] == Empty {
|
||||||
|
nextY = i
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nextX, nextY, nextDirection
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tileMap *Map) GetPassword() int {
|
||||||
|
password := 1000 * (tileMap.traveler.y + 1) + 4 * (tileMap.traveler.x + 1)
|
||||||
|
switch tileMap.traveler.facing {
|
||||||
|
case South:
|
||||||
|
password += 1
|
||||||
|
case West:
|
||||||
|
password += 2
|
||||||
|
case North:
|
||||||
|
password += 3
|
||||||
|
}
|
||||||
|
|
||||||
|
return password
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type Instruction interface {
|
||||||
|
Apply(*Map)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type Move struct {
|
||||||
|
nTiles int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (instruction Move) Apply(tileMap *Map) {
|
||||||
|
for i := 0; i < instruction.nTiles; i++ {
|
||||||
|
nextX, nextY, nextDirection := tileMap.GetNextTile()
|
||||||
|
tileMap.traveler.x = nextX
|
||||||
|
tileMap.traveler.y = nextY
|
||||||
|
tileMap.traveler.facing = nextDirection
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type RotateClockwise struct {}
|
||||||
|
|
||||||
|
func (instruction RotateClockwise) Apply(tileMap *Map) {
|
||||||
|
switch tileMap.traveler.facing {
|
||||||
|
case East:
|
||||||
|
tileMap.traveler.facing = South
|
||||||
|
case South:
|
||||||
|
tileMap.traveler.facing = West
|
||||||
|
case West:
|
||||||
|
tileMap.traveler.facing = North
|
||||||
|
case North:
|
||||||
|
tileMap.traveler.facing = East
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type RotateCounterclockwise struct {}
|
||||||
|
|
||||||
|
func (instruction RotateCounterclockwise) Apply(tileMap *Map) {
|
||||||
|
switch tileMap.traveler.facing {
|
||||||
|
case East:
|
||||||
|
tileMap.traveler.facing = North
|
||||||
|
case South:
|
||||||
|
tileMap.traveler.facing = East
|
||||||
|
case West:
|
||||||
|
tileMap.traveler.facing = South
|
||||||
|
case North:
|
||||||
|
tileMap.traveler.facing = West
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func Parse(scanner bufio.Scanner, isCubic bool) (Map, []Instruction) {
|
||||||
|
tileMap := Map{}
|
||||||
|
instructions := []Instruction{}
|
||||||
|
longestRow := 0
|
||||||
|
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := scanner.Text()
|
||||||
|
|
||||||
|
if line == "" {
|
||||||
|
scanner.Scan()
|
||||||
|
line := scanner.Text()
|
||||||
|
for i := 0; i < len(line); i++ {
|
||||||
|
if line[i] >= '0' && line[i] <= '9' {
|
||||||
|
j := i
|
||||||
|
for j < len(line) && line[j] >= '0' && line[j] <= '9' {
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
nTiles, _ := strconv.Atoi(line[i:j])
|
||||||
|
instructions = append(instructions, Move{nTiles})
|
||||||
|
i = j - 1
|
||||||
|
} else if line[i] == 'L' {
|
||||||
|
instructions = append(instructions, RotateCounterclockwise{})
|
||||||
|
} else if line[i] == 'R' {
|
||||||
|
instructions = append(instructions, RotateClockwise{})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if len(line) > longestRow {
|
||||||
|
longestRow = len(line)
|
||||||
|
}
|
||||||
|
|
||||||
|
tileRow := make([]Tile, len(line))
|
||||||
|
for i := range line {
|
||||||
|
switch line[i] {
|
||||||
|
case ' ':
|
||||||
|
tileRow[i] = None
|
||||||
|
case '.':
|
||||||
|
tileRow[i] = Empty
|
||||||
|
case '#':
|
||||||
|
tileRow[i] = Wall
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tileMap.tiles = append(tileMap.tiles, tileRow)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range tileMap.tiles {
|
||||||
|
for len(tileMap.tiles[i]) < longestRow {
|
||||||
|
tileMap.tiles[i] = append(tileMap.tiles[i], None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range tileMap.tiles[0] {
|
||||||
|
if tileMap.tiles[0][i] == Empty {
|
||||||
|
tileMap.traveler = Traveler{East, i, 0}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tileMap.isCubic = isCubic
|
||||||
|
|
||||||
|
return tileMap, instructions
|
||||||
|
}
|
||||||
18
day22/ex1/main.go
Normal file
18
day22/ex1/main.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"aoc2022/day22/common"
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
tileMap, instructions := common.Parse(*bufio.NewScanner(os.Stdin), false)
|
||||||
|
|
||||||
|
for _, instruction := range instructions {
|
||||||
|
instruction.Apply(&tileMap)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(tileMap.GetPassword())
|
||||||
|
}
|
||||||
18
day22/ex2/main.go
Normal file
18
day22/ex2/main.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"aoc2022/day22/common"
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
tileMap, instructions := common.Parse(*bufio.NewScanner(os.Stdin), true)
|
||||||
|
|
||||||
|
for _, instruction := range instructions {
|
||||||
|
instruction.Apply(&tileMap)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(tileMap.GetPassword())
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user