day10, All Is Broken
This commit is contained in:
parent
0b6c521b5b
commit
e4afe55a1f
196
day10/dayTen.go
196
day10/dayTen.go
|
@ -12,7 +12,7 @@ import (
|
||||||
func Run() int {
|
func Run() int {
|
||||||
fmt.Println("hello day 10")
|
fmt.Println("hello day 10")
|
||||||
// filename := "day10/example2noisy"
|
// filename := "day10/example2noisy"
|
||||||
filename := "day10/input"
|
filename := "day10/example5"
|
||||||
fieldMap := Read(filename)
|
fieldMap := Read(filename)
|
||||||
fmt.Println(fieldMap.BeastCoord)
|
fmt.Println(fieldMap.BeastCoord)
|
||||||
// fmt.Println(fieldMap.String())
|
// fmt.Println(fieldMap.String())
|
||||||
|
@ -35,12 +35,15 @@ func Run() int {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("beore marking:")
|
// fmt.Println("beore marking:")
|
||||||
fieldMap.markMainLoop()
|
fieldMap.markMainLoop()
|
||||||
fmt.Println("after marking:")
|
// fmt.Println("after marking loop:")
|
||||||
fmt.Println(fieldMap.String())
|
// fmt.Println(fieldMap.String())
|
||||||
|
fmt.Println("beore marking closest Outer:")
|
||||||
// now main loop is closed with regards to 'S' neighbors
|
// 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)
|
return (len / 2) + (len % 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,48 +65,68 @@ type Cell struct {
|
||||||
Tile rune
|
Tile rune
|
||||||
Neighbords []Coord
|
Neighbords []Coord
|
||||||
IsOnMainPath bool
|
IsOnMainPath bool
|
||||||
|
IsOuter bool
|
||||||
}
|
}
|
||||||
func (c *Cell)String() string {
|
|
||||||
|
func (c *Cell) String() string {
|
||||||
if c.Tile == 'S' {
|
if c.Tile == 'S' {
|
||||||
return "S"
|
return "S"
|
||||||
}
|
}
|
||||||
|
if c.IsOuter {
|
||||||
|
return "O"
|
||||||
|
}
|
||||||
if !c.IsOnMainPath {
|
if !c.IsOnMainPath {
|
||||||
return " "
|
return " "
|
||||||
}
|
}
|
||||||
switch c.Tile {
|
switch c.Tile {
|
||||||
case '7': return "⌝"
|
case '7':
|
||||||
case 'J': return "⌟"
|
return "⌝"
|
||||||
case 'F': return "⌜"
|
case 'J':
|
||||||
case 'L': return "⌞"
|
return "⌟"
|
||||||
case '.': return " "
|
case 'F':
|
||||||
default: return string(c.Tile)
|
return "⌜"
|
||||||
|
case 'L':
|
||||||
|
return "⌞"
|
||||||
|
case '.':
|
||||||
|
return " "
|
||||||
|
default:
|
||||||
|
return string(c.Tile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Coord struct {
|
type Coord struct {
|
||||||
X, Y int
|
X, Y int
|
||||||
}
|
}
|
||||||
func (c Coord)Equal(other Coord) bool {
|
|
||||||
|
func (c Coord) Equal(other Coord) bool {
|
||||||
return c.X == other.X && c.Y == other.Y
|
return c.X == other.X && c.Y == other.Y
|
||||||
}
|
}
|
||||||
|
|
||||||
type Direction int
|
type Direction int
|
||||||
const (UP Direction = iota
|
|
||||||
|
const (
|
||||||
|
UP Direction = iota
|
||||||
DOWN
|
DOWN
|
||||||
LEFT
|
LEFT
|
||||||
RIGHT)
|
RIGHT
|
||||||
|
)
|
||||||
|
func (d Direction)String() string {
|
||||||
|
names := []string{"UP", "DOWN", "LEFT", "RIGHT"}
|
||||||
|
return names[d]
|
||||||
|
}
|
||||||
|
|
||||||
func (c Coord)Shift(d Direction) Coord {
|
func (c Coord) Shift(d Direction) Coord {
|
||||||
x, y := c.X, c.Y
|
x, y := c.X, c.Y
|
||||||
result := Coord{}
|
result := Coord{}
|
||||||
switch d {
|
switch d {
|
||||||
case UP:
|
case UP:
|
||||||
result = Coord{x, y-1}
|
result = Coord{x, y - 1}
|
||||||
case DOWN:
|
case DOWN:
|
||||||
result = Coord{x, y+1}
|
result = Coord{x, y + 1}
|
||||||
case LEFT:
|
case LEFT:
|
||||||
result = Coord{x-1, y}
|
result = Coord{x - 1, y}
|
||||||
case RIGHT:
|
case RIGHT:
|
||||||
result = Coord{x+1, y}
|
result = Coord{x + 1, y}
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
@ -113,7 +136,8 @@ type Map struct {
|
||||||
Height, Width int
|
Height, Width int
|
||||||
BeastCoord Coord
|
BeastCoord Coord
|
||||||
}
|
}
|
||||||
func (m *Map)String() string {
|
|
||||||
|
func (m *Map) String() string {
|
||||||
result := ""
|
result := ""
|
||||||
for y := 0; y < m.Height; y++ {
|
for y := 0; y < m.Height; y++ {
|
||||||
for x := 0; x < m.Width; x++ {
|
for x := 0; x < m.Width; x++ {
|
||||||
|
@ -125,7 +149,7 @@ func (m *Map)String() string {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Map)markMainLoop() {
|
func (m *Map) markMainLoop() {
|
||||||
start := m.Cells[m.BeastCoord]
|
start := m.Cells[m.BeastCoord]
|
||||||
start.IsOnMainPath = true
|
start.IsOnMainPath = true
|
||||||
m.Cells[m.BeastCoord] = start
|
m.Cells[m.BeastCoord] = start
|
||||||
|
@ -136,7 +160,7 @@ func (m *Map)markMainLoop() {
|
||||||
currentCell.IsOnMainPath = true
|
currentCell.IsOnMainPath = true
|
||||||
m.Cells[currentCell.Coord] = currentCell
|
m.Cells[currentCell.Coord] = currentCell
|
||||||
// log.Printf("marking loop on %+v (%s)\n", currentCell, currentCell.String())
|
// 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)
|
// log.Printf("next coord will be %v %s\n", nextCoord, err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
@ -146,9 +170,114 @@ 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.
|
// call for each direction from beast.
|
||||||
// will run the path until it loops back at best, or terminates
|
// will run the path until it loops back at best, or terminates
|
||||||
func (m *Map)checkDirectionFromBeast(through Coord) (isCycle bool, len int) {
|
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)
|
// defer log.Printf("about to return check from beast %v, isCycle : %t. len is %d", through, isCycle, len)
|
||||||
len = 1
|
len = 1
|
||||||
previous := m.Cells[m.BeastCoord]
|
previous := m.Cells[m.BeastCoord]
|
||||||
|
@ -157,7 +286,7 @@ func (m *Map)checkDirectionFromBeast(through Coord) (isCycle bool, len int) {
|
||||||
for found && currentCell.Tile != 'S' {
|
for found && currentCell.Tile != 'S' {
|
||||||
// log.Printf("check direction loop for %+v (%s)\n", currentCell, currentCell.String())
|
// log.Printf("check direction loop for %+v (%s)\n", currentCell, currentCell.String())
|
||||||
len += 1
|
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)
|
// log.Printf("next coord will be %v %s\n", nextCoord, err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
@ -178,7 +307,7 @@ func (m *Map)checkDirectionFromBeast(through Coord) (isCycle bool, len int) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Map)isValidCoord(c Coord) bool {
|
func (m *Map) isValidCoord(c Coord) bool {
|
||||||
if c.X < 0 || c.Y < 0 || c.X >= m.Height || c.Y >= m.Width {
|
if c.X < 0 || c.Y < 0 || c.X >= m.Height || c.Y >= m.Width {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -228,18 +357,25 @@ func (c *Cell) GetNeighbors() []Coord {
|
||||||
// - check if 'from' is in neighbors
|
// - check if 'from' is in neighbors
|
||||||
// if it is - then take another neighbor
|
// if it is - then take another neighbor
|
||||||
// wouldn't work for 'S' but we don't need it to
|
// 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 {
|
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)
|
i := slices.Index(c.Neighbords, from)
|
||||||
if i == -1 {
|
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
|
otherIndex := 1 - i
|
||||||
return c.Neighbords[otherIndex], nil
|
return c.Neighbords[otherIndex], nextDirection, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// x from left to right; y from top to bottom
|
// 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
|
and count I
|
||||||
|
|
||||||
sounds like a plan
|
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