142 lines
2.9 KiB
Go
142 lines
2.9 KiB
Go
package day23
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
type Coord struct {
|
|
Row, Col int
|
|
}
|
|
|
|
type CellType rune
|
|
|
|
const (
|
|
Path CellType = '.'
|
|
Tree CellType = '#'
|
|
SlideDown CellType = 'v'
|
|
SlideUp CellType = '^'
|
|
SlideLeft CellType = '<'
|
|
SlideRight CellType = '>'
|
|
)
|
|
|
|
type Field struct {
|
|
MaxRow, MaxCol int
|
|
Cells map[Coord]CellType
|
|
StartCol, EndCol int
|
|
}
|
|
|
|
func (f *Field) NeighborsPart2(c Coord) (neighbors []Coord) {
|
|
symb, exists := f.Cells[c]
|
|
if !exists {
|
|
panic(fmt.Sprintf("coord %+v not found in field", c))
|
|
}
|
|
|
|
var coords []Coord
|
|
switch symb {
|
|
case Tree:
|
|
panic(fmt.Sprintf("attempting to get neighbors of a tree at %+v", c))
|
|
default:
|
|
coords = []Coord{
|
|
{Row: c.Row + 1, Col: c.Col},
|
|
{Row: c.Row - 1, Col: c.Col},
|
|
{Row: c.Row, Col: c.Col + 1},
|
|
{Row: c.Row, Col: c.Col - 1},
|
|
}
|
|
}
|
|
|
|
for _, coord := range coords {
|
|
neighborSymb, found := f.Cells[coord]
|
|
if !found || neighborSymb == Tree {
|
|
continue
|
|
}
|
|
neighbors = append(neighbors, coord)
|
|
}
|
|
return
|
|
}
|
|
|
|
func (f *Field) Neighbors(c Coord) (neighbors []Coord) {
|
|
symb, exists := f.Cells[c]
|
|
if !exists {
|
|
panic(fmt.Sprintf("coord %+v not found in field", c))
|
|
}
|
|
|
|
var coords []Coord
|
|
switch symb {
|
|
case Path:
|
|
coords = []Coord{
|
|
{Row: c.Row + 1, Col: c.Col},
|
|
{Row: c.Row - 1, Col: c.Col},
|
|
{Row: c.Row, Col: c.Col + 1},
|
|
{Row: c.Row, Col: c.Col - 1},
|
|
}
|
|
case Tree:
|
|
panic(fmt.Sprintf("attempting to get neighbors of a tree at %+v", c))
|
|
case SlideDown:
|
|
coords = []Coord{{Row: c.Row + 1, Col: c.Col}}
|
|
case SlideUp:
|
|
coords = []Coord{{Row: c.Row - 1, Col: c.Col}}
|
|
case SlideLeft:
|
|
coords = []Coord{{Row: c.Row, Col: c.Col - 1}}
|
|
case SlideRight:
|
|
coords = []Coord{{Row: c.Row, Col: c.Col + 1}}
|
|
}
|
|
|
|
for _, coord := range coords {
|
|
neighborSymb, found := f.Cells[coord]
|
|
if !found || neighborSymb == Tree {
|
|
continue
|
|
}
|
|
neighbors = append(neighbors, coord)
|
|
}
|
|
return
|
|
}
|
|
|
|
func (f *Field) String() (result string) {
|
|
result += "\n"
|
|
for row := 0; row <= f.MaxRow; row++ {
|
|
for col := 0; col <= f.MaxCol; col++ {
|
|
if row == 0 && col == f.StartCol {
|
|
result += "S"
|
|
continue
|
|
}
|
|
if row == f.MaxRow && col == f.EndCol {
|
|
result += "E"
|
|
continue
|
|
}
|
|
|
|
symb := f.Cells[Coord{Row: row, Col: col}]
|
|
result += string(symb)
|
|
}
|
|
result += "\n"
|
|
}
|
|
return
|
|
}
|
|
|
|
func ReadField(filename string) (result Field) {
|
|
bytes, err := os.ReadFile(filename)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
lines := strings.Split(strings.TrimSpace(string(bytes)), "\n")
|
|
result.MaxRow = len(lines) - 1
|
|
result.MaxCol = len(lines[0]) - 1
|
|
rows := make(map[Coord]CellType)
|
|
|
|
for rowNum, row := range lines {
|
|
for colNum, symb := range row {
|
|
rows[Coord{Row: rowNum, Col: colNum}] = CellType(symb)
|
|
if rowNum == 0 && symb == rune(Path) {
|
|
result.StartCol = colNum
|
|
}
|
|
if rowNum == result.MaxRow && symb == rune(Path) {
|
|
result.EndCol = colNum
|
|
}
|
|
}
|
|
}
|
|
result.Cells = rows
|
|
|
|
return
|
|
}
|