day10, All Is Broken
This commit is contained in:
parent
0b6c521b5b
commit
e4afe55a1f
174
day10/dayTen.go
174
day10/dayTen.go
|
@ -12,7 +12,7 @@ import (
|
|||
func Run() int {
|
||||
fmt.Println("hello day 10")
|
||||
// filename := "day10/example2noisy"
|
||||
filename := "day10/input"
|
||||
filename := "day10/example5"
|
||||
fieldMap := Read(filename)
|
||||
fmt.Println(fieldMap.BeastCoord)
|
||||
// fmt.Println(fieldMap.String())
|
||||
|
@ -35,12 +35,15 @@ func Run() int {
|
|||
}
|
||||
}
|
||||
|
||||
fmt.Println("beore marking:")
|
||||
// fmt.Println("beore marking:")
|
||||
fieldMap.markMainLoop()
|
||||
fmt.Println("after marking:")
|
||||
fmt.Println(fieldMap.String())
|
||||
// fmt.Println("after marking loop:")
|
||||
// fmt.Println(fieldMap.String())
|
||||
fmt.Println("beore marking closest Outer:")
|
||||
// now main loop is closed with regards to 'S' neighbors
|
||||
|
||||
fieldMap.initialMarkOuter()
|
||||
fmt.Println("after marking closest Outer:")
|
||||
fmt.Println(fieldMap.String())
|
||||
return (len / 2) + (len % 2)
|
||||
}
|
||||
|
||||
|
@ -62,35 +65,55 @@ type Cell struct {
|
|||
Tile rune
|
||||
Neighbords []Coord
|
||||
IsOnMainPath bool
|
||||
IsOuter bool
|
||||
}
|
||||
|
||||
func (c *Cell) String() string {
|
||||
if c.Tile == 'S' {
|
||||
return "S"
|
||||
}
|
||||
if c.IsOuter {
|
||||
return "O"
|
||||
}
|
||||
if !c.IsOnMainPath {
|
||||
return " "
|
||||
}
|
||||
switch c.Tile {
|
||||
case '7': return "⌝"
|
||||
case 'J': return "⌟"
|
||||
case 'F': return "⌜"
|
||||
case 'L': return "⌞"
|
||||
case '.': return " "
|
||||
default: return string(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
|
||||
}
|
||||
|
||||
func (c Coord) Equal(other Coord) bool {
|
||||
return c.X == other.X && c.Y == other.Y
|
||||
}
|
||||
|
||||
type Direction int
|
||||
const (UP Direction = iota
|
||||
|
||||
const (
|
||||
UP Direction = iota
|
||||
DOWN
|
||||
LEFT
|
||||
RIGHT)
|
||||
RIGHT
|
||||
)
|
||||
func (d Direction)String() string {
|
||||
names := []string{"UP", "DOWN", "LEFT", "RIGHT"}
|
||||
return names[d]
|
||||
}
|
||||
|
||||
func (c Coord) Shift(d Direction) Coord {
|
||||
x, y := c.X, c.Y
|
||||
|
@ -113,6 +136,7 @@ type Map struct {
|
|||
Height, Width int
|
||||
BeastCoord Coord
|
||||
}
|
||||
|
||||
func (m *Map) String() string {
|
||||
result := ""
|
||||
for y := 0; y < m.Height; y++ {
|
||||
|
@ -136,7 +160,7 @@ func (m *Map)markMainLoop() {
|
|||
currentCell.IsOnMainPath = true
|
||||
m.Cells[currentCell.Coord] = currentCell
|
||||
// log.Printf("marking loop on %+v (%s)\n", currentCell, currentCell.String())
|
||||
nextCoord, err := currentCell.Next(previous.Coord)
|
||||
nextCoord, _, err := currentCell.Next(previous.Coord)
|
||||
// log.Printf("next coord will be %v %s\n", nextCoord, err)
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -146,6 +170,111 @@ func (m *Map)markMainLoop() {
|
|||
}
|
||||
}
|
||||
|
||||
func (m *Map) initialMarkOuter() {
|
||||
// for start point let's take my highest on main path and one above
|
||||
// and will have a runner pointer to the cell on the outside
|
||||
|
||||
var outerRunner Cell
|
||||
var pathCunner Cell
|
||||
outer:
|
||||
for y := 0; y < m.Height; y++ {
|
||||
for x := 0; x < m.Width; x++ {
|
||||
if cell := m.Cells[Coord{x, y}]; cell.IsOnMainPath {
|
||||
pathCunner = cell
|
||||
outerRunner = m.Cells[Coord{x, y - 1}]
|
||||
break outer
|
||||
}
|
||||
}
|
||||
}
|
||||
startPoint := pathCunner
|
||||
previous := startPoint
|
||||
firstDirection := startPoint.OutDirections()[0]
|
||||
nextCoord := previous.Coord.Shift(firstDirection)
|
||||
currentCell := m.Cells[nextCoord]
|
||||
var exitingPreviousBy Direction = firstDirection
|
||||
|
||||
stepsToDo := 1
|
||||
for currentCell.Coord != startPoint.Coord {
|
||||
|
||||
// looping once. and need to operae on the outer runner
|
||||
// and i don't have the direction? well, i guess i could use direction
|
||||
|
||||
outerRunner = m.markOuterAndMove(previous, outerRunner, exitingPreviousBy)
|
||||
var err error
|
||||
nextCoord, exitingPreviousBy, err = currentCell.Next(previous.Coord)
|
||||
if err != nil {
|
||||
panic("initial mark cycle can't get next")
|
||||
}
|
||||
previous = currentCell
|
||||
currentCell = m.Cells[nextCoord]
|
||||
|
||||
stepsToDo -= 1
|
||||
if stepsToDo == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Map) markOuter(outerPointerCoord Coord) {
|
||||
if !m.isValidCoord(outerPointerCoord) {
|
||||
return
|
||||
}
|
||||
outerPointer := m.Cells[outerPointerCoord]
|
||||
if outerPointer.IsOnMainPath {
|
||||
return
|
||||
}
|
||||
outerPointer.IsOuter = true
|
||||
m.Cells[outerPointer.Coord] = outerPointer
|
||||
}
|
||||
|
||||
// move both inner path Cell and OuterCell through direction from inner path cell
|
||||
// and i need to know direction from which we came into 'pathPointer'
|
||||
func (m *Map) markOuterAndMove(pathPointer Cell, outerPointer Cell, exitingCurrentBy Direction) Cell {
|
||||
// mark &save outer, get moves from pathPointer & direct
|
||||
// do 1 or 2 moves and on each mark & save
|
||||
m.markOuter(outerPointer.Coord)
|
||||
|
||||
outerPointerMovements := outerPointerMovements[pathPointer.Tile][exitingCurrentBy]
|
||||
log.Printf("moving outer from %s exited via %s with moves %+v\n", pathPointer.String(), exitingCurrentBy.String(), outerPointerMovements)
|
||||
coord := outerPointer.Coord
|
||||
for _, movement := range outerPointerMovements {
|
||||
coord = coord.Shift(movement)
|
||||
m.markOuter(coord)
|
||||
}
|
||||
|
||||
newPointer := m.Cells[coord]
|
||||
return newPointer
|
||||
}
|
||||
|
||||
// yeah, this is not enough. if we move down from | we could be directly up to -
|
||||
// so we need TurnLeft & TurnRight things
|
||||
var outerPointerMovements map[rune]map[Direction][]Direction = map[rune]map[Direction][]Direction{
|
||||
'|': {
|
||||
UP: {UP},
|
||||
DOWN: {DOWN},
|
||||
},
|
||||
'-': {
|
||||
LEFT: {LEFT},
|
||||
RIGHT: {RIGHT},
|
||||
},
|
||||
'L': {
|
||||
DOWN: {DOWN, RIGHT},
|
||||
LEFT: {RIGHT, UP},
|
||||
},
|
||||
'J': {
|
||||
DOWN: {DOWN, LEFT},
|
||||
RIGHT: {RIGHT, UP},
|
||||
},
|
||||
'F': {
|
||||
DOWN: {LEFT, DOWN},
|
||||
RIGHT: {UP, RIGHT},
|
||||
},
|
||||
'7': {
|
||||
RIGHT: {RIGHT, DOWN},
|
||||
UP: {UP, LEFT},
|
||||
},
|
||||
}
|
||||
|
||||
// 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) {
|
||||
|
@ -157,7 +286,7 @@ func (m *Map)checkDirectionFromBeast(through Coord) (isCycle bool, len int) {
|
|||
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)
|
||||
nextCoord, _, err := currentCell.Next(previous.Coord)
|
||||
// log.Printf("next coord will be %v %s\n", nextCoord, err)
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -228,18 +357,25 @@ func (c *Cell) GetNeighbors() []Coord {
|
|||
// - 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, cameFrom Direction, err error) {
|
||||
if len(c.Neighbords) != 2 {
|
||||
return Coord{}, errors.New(fmt.Sprintf("not 2 neighbors: cannot get next from %v through %c", from, c))
|
||||
return Coord{}, 0, errors.New(fmt.Sprintf("not 2 neighbors: cannot get next from %v through %c", from, c))
|
||||
}
|
||||
|
||||
i := slices.Index(c.Neighbords, from)
|
||||
if i == -1 {
|
||||
return Coord{}, errors.New(fmt.Sprintf("cannot find next from %v through %+v", from, c))
|
||||
return Coord{}, 0, errors.New(fmt.Sprintf("cannot find next from %v through %+v", from, c))
|
||||
}
|
||||
|
||||
var nextDirection Direction
|
||||
for _, direction := range c.OutDirections() {
|
||||
if c.Coord.Shift(direction) != from {
|
||||
nextDirection = direction
|
||||
}
|
||||
}
|
||||
|
||||
otherIndex := 1 - i
|
||||
return c.Neighbords[otherIndex], nil
|
||||
return c.Neighbords[otherIndex], nextDirection, nil
|
||||
}
|
||||
|
||||
// x from left to right; y from top to bottom
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
.......
|
||||
...F7..
|
||||
..FJ|..
|
||||
.SJ.L7.
|
||||
.|F--J.
|
||||
.LJ....
|
||||
.......
|
|
@ -18,3 +18,30 @@ but yeah, if i make initial filling in of the I, then i could just fill in all .
|
|||
and count I
|
||||
|
||||
sounds like a plan
|
||||
** allright, i found main path, display all not on main path as ' '
|
||||
and the thing is a mess
|
||||
|
||||
i don't know how to select a point to mark as 'I'
|
||||
|
||||
but! if i select a point to mark as 'O'
|
||||
and then go around the main path, marking things on the side as 'O'
|
||||
then i would be able to fill in all which are neighbors of 'O' as 'O'
|
||||
and that would leave only 'I' to be counted
|
||||
|
||||
so.
|
||||
|
||||
how would i monitor consistent 'side' of the pipe during the walkhrough?
|
||||
if we go down - we color as 'O' one down.
|
||||
if we go angle - color two - one down and one to the right.
|
||||
and only color if it's not already on main path.
|
||||
|
||||
i suppose so
|
||||
** so a new method for initial pass of 'O'
|
||||
well, i'll need access to the direction, in which the neighbor is taken?
|
||||
nooo. not direction, but the symbol. ok, this is easier
|
||||
|
||||
but i'll need to mutate the field
|
||||
|
||||
no, i do need direction.
|
||||
|
||||
ok, let's go lunch maybe, and maybe it will be a place with a power outlet as well
|
||||
|
|
Loading…
Reference in New Issue