day10, example1

This commit is contained in:
efim 2023-12-10 12:03:57 +00:00
parent c2091b49fd
commit 1626bd0be9
1 changed files with 115 additions and 33 deletions

View File

@ -3,7 +3,9 @@ package day10
import ( import (
"errors" "errors"
"fmt" "fmt"
"log"
"os" "os"
"slices"
"strings" "strings"
) )
@ -13,8 +15,26 @@ func Run() int {
filename := "day10/example1" filename := "day10/example1"
fieldMap := Read(filename) fieldMap := Read(filename)
fmt.Println(fieldMap.String()) fmt.Println(fieldMap.String())
fmt.Printf("%+v\n", fieldMap.Cells)
return 0 // log.Printf(">> does Equals work? {1,2} == {1,2} is %t\n", (Coord{1,2} == Coord{1,2}))
// log.Printf(">> does Index work? {1,2} in [{2,2}, {1,2}] is %d \n", slices.Index([]Coord{{2,2}, {1,2}}, Coord{1,2}))
// fieldMap.checkDirectionFromBeast(Coord{1,2})
beastNeighborCoords := fieldMap.Cells[fieldMap.BeastCoord].Neighbords
len := 0
for _, coord := range beastNeighborCoords {
log.Printf("checking neighbor %v\n", coord)
isCycle, curLen := fieldMap.checkDirectionFromBeast(coord)
if isCycle {
log.Printf("found cycle through %v\n", coord)
len = curLen
break
}
}
return (len / 2) + (len % 2)
} }
// so do i work with just [][]rune ? // so do i work with just [][]rune ?
@ -33,6 +53,7 @@ func Run() int {
type Cell struct { type Cell struct {
Coord Coord Coord Coord
Tile rune Tile rune
Neighbords []Coord
} }
func (c *Cell)String() string { func (c *Cell)String() string {
switch c.Tile { switch c.Tile {
@ -47,6 +68,31 @@ func (c *Cell)String() string {
type Coord struct { type Coord struct {
X, Y int X, Y int
} }
func (c Coord)Equal(other Coord) bool {
return c.X == other.X && c.Y == other.Y
}
type Direction int
const (UP Direction = iota
DOWN
LEFT
RIGHT)
func (c Coord)Shift(d Direction) Coord {
x, y := c.X, c.Y
result := Coord{}
switch d {
case UP:
result = Coord{x, y-1}
case DOWN:
result = Coord{x, y+1}
case LEFT:
result = Coord{x-1, y}
case RIGHT:
result = Coord{x+1, y}
}
return result
}
type Map struct { type Map struct {
Cells map[Coord]Cell Cells map[Coord]Cell
@ -65,6 +111,40 @@ func (m *Map)String() string {
return result return result
} }
// call for each direction from beast.
// will run the path until it loops back at best, or terminates
func (m *Map)checkDirectionFromBeast(through Coord) (isCycle bool, len int) {
defer log.Printf("about to return check from beast %v, isCycle : %t. len is %d", through, isCycle, len)
len = 1
previous := m.Cells[m.BeastCoord]
currentCell, found := m.Cells[through]
log.Printf("check direction init for %+v\n", currentCell)
for found && currentCell.Tile != 'S' {
log.Printf("check direction loop for %+v (%s)\n", currentCell, currentCell.String())
len += 1
nextCoord, err := currentCell.Next(previous.Coord)
log.Printf("next coord will be %v %s\n", nextCoord, err)
if err != nil {
return
}
previous = currentCell
currentCell, found = m.Cells[nextCoord]
}
if currentCell.Tile == 'S' {
log.Printf("found cycle, len is %d\n", len)
isCycle = true
}
return
}
func (m *Map)isValidCoord(c Coord) bool {
if c.X < 0 || c.Y < 0 || c.X >= m.Height || c.Y >= m.Width {
return false
}
return true
}
func Read(filename string) Map { func Read(filename string) Map {
result := Map{} result := Map{}
bytes, err := os.ReadFile(filename) bytes, err := os.ReadFile(filename)
@ -82,62 +162,64 @@ func Read(filename string) Map {
if symb == 'S' { if symb == 'S' {
result.BeastCoord = coord result.BeastCoord = coord
} }
result.Cells[coord] = Cell{ cell := Cell{
Coord: coord, Coord: coord,
Tile: symb, Tile: symb,
} }
cell.Neighbords = cell.GetNeighbors()
result.Cells[coord] = cell
} }
} }
return result return result
} }
func (c *Cell) GetNeighbors() []Coord {
result := make([]Coord, 0)
for _, direction := range c.OutDirections() {
result = append(result, c.Coord.Shift(direction))
}
return result
}
// doesn't check whether 'from' has exit into c // doesn't check whether 'from' has exit into c
// only whether c can accept conntion from that direction // only whether c can accept conntion from that direction
// - check if 'from' is in neighbors
// if it is - then take another neighbor
// wouldn't work for 'S' but we don't need it to
func (c *Cell) Next(from Coord) (to Coord, err error) { func (c *Cell) Next(from Coord) (to Coord, err error) {
nextCoord, found := c.Directions()[from] if len(c.Neighbords) != 2 {
if !found { return Coord{}, errors.New(fmt.Sprintf("not 2 neighbors: cannot get next from %v through %c", from, c))
return Coord{}, errors.New(fmt.Sprintf("no direction from %+v to %+v through %+v\n", from, to, c))
} }
return nextCoord, nil i := slices.Index(c.Neighbords, from)
if i == -1 {
return Coord{}, errors.New(fmt.Sprintf("cannot find next from %v through %+v", from, c))
}
otherIndex := 1 - i
return c.Neighbords[otherIndex], nil
} }
// x from left to right; y from top to bottom // x from left to right; y from top to bottom
func (c *Cell) Directions() map[Coord]Coord { func (c *Cell) OutDirections() []Direction {
x, y := c.Coord.X, c.Coord.Y
switch c.Tile { switch c.Tile {
case '|': case '|':
return map[Coord]Coord{ return []Direction{UP, DOWN}
{x, y + 1}: {x, y - 1},
{x, y - 1}: {x, y + 1},
}
case '-': case '-':
return map[Coord]Coord{ return []Direction{LEFT, RIGHT}
{x - 1, y}: {x + 1, y},
{x + 1, y}: {x - 1, y},
}
case 'L': case 'L':
return map[Coord]Coord{ return []Direction{UP, RIGHT}
{x, y + 1}: {x + 1, y},
{x + 1, y}: {x, y + 1},
}
case 'J': case 'J':
return map[Coord]Coord{ return []Direction{UP, LEFT}
{x, y + 1}: {x - 1, y},
{x - 1, y}: {x, y + 1},
}
case 'F': case 'F':
return map[Coord]Coord{ return []Direction{RIGHT, DOWN}
{x + 1, y}: {x, y + 1},
{x, y + 1}: {x + 1, y},
}
case '7': case '7':
return map[Coord]Coord{ return []Direction{LEFT, DOWN}
{x - 1, y}: {x, y + 1}, case 'S': // all
{x, y + 1}: {x - 1, y}, return []Direction{UP, DOWN, LEFT, RIGHT}
}
default: default:
return map[Coord]Coord{} return []Direction{}
} }
} }