From 1626bd0be9a232fe8af8abfed51b41d36a6065d0 Mon Sep 17 00:00:00 2001 From: efim Date: Sun, 10 Dec 2023 12:03:57 +0000 Subject: [PATCH] day10, example1 --- day10/dayTen.go | 148 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 115 insertions(+), 33 deletions(-) diff --git a/day10/dayTen.go b/day10/dayTen.go index 34cf6ef..8de7688 100644 --- a/day10/dayTen.go +++ b/day10/dayTen.go @@ -3,7 +3,9 @@ package day10 import ( "errors" "fmt" + "log" "os" + "slices" "strings" ) @@ -13,8 +15,26 @@ func Run() int { filename := "day10/example1" fieldMap := Read(filename) 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 ? @@ -33,6 +53,7 @@ func Run() int { type Cell struct { Coord Coord Tile rune + Neighbords []Coord } func (c *Cell)String() string { switch c.Tile { @@ -47,6 +68,31 @@ func (c *Cell)String() string { type Coord struct { 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 { Cells map[Coord]Cell @@ -65,6 +111,40 @@ func (m *Map)String() string { 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 { result := Map{} bytes, err := os.ReadFile(filename) @@ -82,62 +162,64 @@ func Read(filename string) Map { if symb == 'S' { result.BeastCoord = coord } - result.Cells[coord] = Cell{ + cell := Cell{ Coord: coord, Tile: symb, } + cell.Neighbords = cell.GetNeighbors() + result.Cells[coord] = cell } } 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 // 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) { - 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)) + if len(c.Neighbords) != 2 { + return Coord{}, errors.New(fmt.Sprintf("not 2 neighbors: cannot get next from %v through %c", from, 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 -func (c *Cell) Directions() map[Coord]Coord { - x, y := c.Coord.X, c.Coord.Y +func (c *Cell) OutDirections() []Direction { switch c.Tile { case '|': - return map[Coord]Coord{ - {x, y + 1}: {x, y - 1}, - {x, y - 1}: {x, y + 1}, - } + return []Direction{UP, DOWN} case '-': - return map[Coord]Coord{ - {x - 1, y}: {x + 1, y}, - {x + 1, y}: {x - 1, y}, - } + return []Direction{LEFT, RIGHT} case 'L': - return map[Coord]Coord{ - {x, y + 1}: {x + 1, y}, - {x + 1, y}: {x, y + 1}, - } + return []Direction{UP, RIGHT} case 'J': - return map[Coord]Coord{ - {x, y + 1}: {x - 1, y}, - {x - 1, y}: {x, y + 1}, - } + return []Direction{UP, LEFT} case 'F': - return map[Coord]Coord{ - {x + 1, y}: {x, y + 1}, - {x, y + 1}: {x + 1, y}, - } + return []Direction{RIGHT, DOWN} case '7': - return map[Coord]Coord{ - {x - 1, y}: {x, y + 1}, - {x, y + 1}: {x - 1, y}, - } + return []Direction{LEFT, DOWN} + case 'S': // all + return []Direction{UP, DOWN, LEFT, RIGHT} default: - return map[Coord]Coord{} + return []Direction{} } }