day10, All Is Broken
This commit is contained in:
		
							parent
							
								
									0b6c521b5b
								
							
						
					
					
						commit
						e4afe55a1f
					
				
							
								
								
									
										210
									
								
								day10/dayTen.go
									
									
									
									
									
								
							
							
						
						
									
										210
									
								
								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) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -58,52 +61,72 @@ func Run() int { | |||||||
| // cell would map 'from' to 'to' | // cell would map 'from' to 'to' | ||||||
| 
 | 
 | ||||||
| type Cell struct { | type Cell struct { | ||||||
| 	Coord Coord | 	Coord        Coord | ||||||
| 	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 | ||||||
|  | |||||||
							
								
								
									
										7
									
								
								day10/example5
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								day10/example5
									
									
									
									
									
										Normal file
									
								
							| @ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user