144 lines
2.9 KiB
Go
144 lines
2.9 KiB
Go
package day10
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
func Run() int {
|
|
fmt.Println("hello day 10")
|
|
// filename := "day10/example2noisy"
|
|
filename := "day10/example1"
|
|
fieldMap := Read(filename)
|
|
fmt.Println(fieldMap.String())
|
|
|
|
return 0
|
|
}
|
|
|
|
// so do i work with just [][]rune ?
|
|
// func Next(from Coord, through Coord) (Coord, error) ?
|
|
// and here check that 'from' has exit into 'through'
|
|
// and check that 'through' has entrance from 'from'
|
|
|
|
// so, i guess i could do 'exit direction' and 'entrance direction'
|
|
// then compare 'exit direction' with what's available on 'from'
|
|
//
|
|
// or i can just have function 'canExit(from, to Coord)' and canEnter(from, to Coord)
|
|
|
|
// i suppose it would be nice to just create Cell(Coord, Type) and
|
|
// cell would map 'from' to 'to'
|
|
|
|
type Cell struct {
|
|
Coord Coord
|
|
Tile rune
|
|
}
|
|
func (c *Cell)String() string {
|
|
switch c.Tile {
|
|
case '7': return "⌝"
|
|
case 'J': return "⌟"
|
|
case 'F': return "⌜"
|
|
case 'L': return "⌞"
|
|
case '.': return " "
|
|
default: return string(c.Tile)
|
|
}
|
|
}
|
|
type Coord struct {
|
|
X, Y int
|
|
}
|
|
|
|
type Map struct {
|
|
Cells map[Coord]Cell
|
|
Height, Width int
|
|
BeastCoord Coord
|
|
}
|
|
func (m *Map)String() string {
|
|
result := ""
|
|
for y := 0; y < m.Height; y++ {
|
|
for x := 0; x < m.Width; x++ {
|
|
cell := m.Cells[Coord{x, y}]
|
|
result += cell.String()
|
|
}
|
|
result += "\n"
|
|
}
|
|
return result
|
|
}
|
|
|
|
func Read(filename string) Map {
|
|
result := Map{}
|
|
bytes, err := os.ReadFile(filename)
|
|
if err != nil {
|
|
panic(fmt.Sprint("cannot read file ", filename))
|
|
}
|
|
lines := strings.Split(string(bytes), "\n")
|
|
result.Height = len(lines)
|
|
result.Width = len(lines[0])
|
|
result.Cells = map[Coord]Cell{}
|
|
|
|
for y, line := range lines {
|
|
for x, symb := range line {
|
|
coord := Coord{X: x, Y: y}
|
|
if symb == 'S' {
|
|
result.BeastCoord = coord
|
|
}
|
|
result.Cells[coord] = Cell{
|
|
Coord: coord,
|
|
Tile: symb,
|
|
}
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// doesn't check whether 'from' has exit into c
|
|
// only whether c can accept conntion from that direction
|
|
func (c *Cell) Next(from Coord) (to Coord, err error) {
|
|
nextCoord, found := c.Directions()[from]
|
|
if !found {
|
|
return Coord{}, errors.New(fmt.Sprintf("no direction from %+v to %+v through %+v\n", from, to, c))
|
|
}
|
|
|
|
return nextCoord, nil
|
|
}
|
|
|
|
// x from left to right; y from top to bottom
|
|
func (c *Cell) Directions() map[Coord]Coord {
|
|
x, y := c.Coord.X, c.Coord.Y
|
|
switch c.Tile {
|
|
case '|':
|
|
return map[Coord]Coord{
|
|
{x, y + 1}: {x, y - 1},
|
|
{x, y - 1}: {x, y + 1},
|
|
}
|
|
case '-':
|
|
return map[Coord]Coord{
|
|
{x - 1, y}: {x + 1, y},
|
|
{x + 1, y}: {x - 1, y},
|
|
}
|
|
case 'L':
|
|
return map[Coord]Coord{
|
|
{x, y + 1}: {x + 1, y},
|
|
{x + 1, y}: {x, y + 1},
|
|
}
|
|
case 'J':
|
|
return map[Coord]Coord{
|
|
{x, y + 1}: {x - 1, y},
|
|
{x - 1, y}: {x, y + 1},
|
|
}
|
|
case 'F':
|
|
return map[Coord]Coord{
|
|
{x + 1, y}: {x, y + 1},
|
|
{x, y + 1}: {x + 1, y},
|
|
}
|
|
case '7':
|
|
return map[Coord]Coord{
|
|
{x - 1, y}: {x, y + 1},
|
|
{x, y + 1}: {x - 1, y},
|
|
}
|
|
default:
|
|
return map[Coord]Coord{}
|
|
}
|
|
}
|