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) EndCoord() Coord { return Coord{Row: f.MaxRow, Col: f.EndCol} } 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 }