mirror of
				https://github.com/onyx-and-iris/aoc2024.git
				synced 2025-10-30 20:41:45 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			97 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			97 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package two
 | |
| 
 | |
| import (
 | |
| 	"slices"
 | |
| 	"strings"
 | |
| 
 | |
| 	"github.com/onyx-and-iris/aoc2024/day-18/internal/point"
 | |
| 	"github.com/onyx-and-iris/aoc2024/day-18/internal/queue"
 | |
| 	log "github.com/sirupsen/logrus"
 | |
| )
 | |
| 
 | |
| type graph struct {
 | |
| 	start point.Point
 | |
| 	end   point.Point
 | |
| 	data  []string
 | |
| }
 | |
| 
 | |
| func newGraph(width, height, numCorruptions int, corruptedCoords [][]int) *graph {
 | |
| 	var data []string
 | |
| 	var sb strings.Builder
 | |
| 	for range height {
 | |
| 		for range width {
 | |
| 			sb.WriteRune('.')
 | |
| 		}
 | |
| 		data = append(data, sb.String())
 | |
| 		sb.Reset()
 | |
| 	}
 | |
| 
 | |
| 	for _, coords := range corruptedCoords[:numCorruptions] {
 | |
| 		data[coords[1]] = replaceAtIndex(data[coords[1]], '#', coords[0])
 | |
| 	}
 | |
| 
 | |
| 	return &graph{point.Point{X: 0, Y: 0}, point.Point{X: len(data[0]) - 1, Y: len(data) - 1}, data}
 | |
| }
 | |
| 
 | |
| func (g *graph) String() string {
 | |
| 	return strings.Join(g.data, "\n")
 | |
| }
 | |
| 
 | |
| func (g *graph) isOutOfBounds(p point.Point) bool {
 | |
| 	return p.X < 0 || p.Y < 0 || p.Y >= len(g.data) || p.X >= len(g.data[p.Y])
 | |
| }
 | |
| 
 | |
| func (g *graph) valueAt(p point.Point) rune {
 | |
| 	return rune(g.data[p.Y][p.X])
 | |
| }
 | |
| 
 | |
| func (g *graph) addCorruption(p point.Point) {
 | |
| 	g.data[p.Y] = replaceAtIndex(g.data[p.Y], '#', p.X)
 | |
| }
 | |
| 
 | |
| func (g *graph) bfs() bool {
 | |
| 	queue := queue.New[point.Point]()
 | |
| 	queue.Enqueue(g.start)
 | |
| 	visited := make(map[point.Point]struct{})
 | |
| 
 | |
| 	for !queue.IsEmpty() {
 | |
| 		current := queue.Dequeue()
 | |
| 
 | |
| 		if current == g.end {
 | |
| 			return true
 | |
| 		}
 | |
| 
 | |
| 		_, ok := visited[current]
 | |
| 		if ok {
 | |
| 			continue
 | |
| 		}
 | |
| 		visited[current] = struct{}{}
 | |
| 
 | |
| 		for _, n := range neighbours(current) {
 | |
| 			if g.isOutOfBounds(n) {
 | |
| 				continue
 | |
| 			}
 | |
| 
 | |
| 			if g.valueAt(n) == '#' {
 | |
| 				continue
 | |
| 			}
 | |
| 
 | |
| 			queue.Enqueue(n)
 | |
| 		}
 | |
| 	}
 | |
| 	log.Debugf("\n%s\n", g.debug(visited))
 | |
| 
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| func (g *graph) debug(visited map[point.Point]struct{}) string {
 | |
| 	temp := slices.Clone(g.data)
 | |
| 	for p := range visited {
 | |
| 		if g.valueAt(p) == '#' {
 | |
| 			continue
 | |
| 		}
 | |
| 		temp[p.Y] = replaceAtIndex(temp[p.Y], 'O', p.X)
 | |
| 	}
 | |
| 	return strings.Join(temp, "\n")
 | |
| }
 |