package day21 import ( "fmt" "log" "os" "strings" ) func Run() int { fmt.Print("hello day21") filename := "day21/example" field := ReadField(filename) log.Print(field) reachableBySixtyFour := field.ReachableBySteps(64, map[Coord]any{ Coord{Row: field.RowStart, Col: field.ColStart}: struct{}{}, }) fmt.Println(field.PrintCoord(reachableBySixtyFour)) return len(reachableBySixtyFour) } // let's do dijkstra? // i would need lots of space for edges? // let's use a map with minimal distances? // OR. just breath first traversal type Field struct { RowStart, ColStart int symbols [][]rune } type Coord struct { Row, Col int } func (f Field) ReachableBySteps(n int, startingAt map[Coord]any) map[Coord]any { if n == 0 { return startingAt } // else collect directly available oneStepExpanded := make(map[Coord]any) for cur := range startingAt { for _, neighbor := range f.Neighbors(cur) { oneStepExpanded[neighbor] = struct{}{} } } return f.ReachableBySteps(n-1, oneStepExpanded) } func (f Field) Neighbors(c Coord) (resut []Coord) { closeCoords := []Coord{ {Row: c.Row + 1, Col: c.Col}, {Row: c.Row - 1, Col: c.Col}, {Row: c.Row, Col: c.Col + 1}, {Row: c.Row, Col: c.Col - 1}, } for _, close := range closeCoords { if f.ValidCoord(close.Row, close.Col) { symb := f.symbols[close.Row][close.Col] if symb == '.' || symb == 'S' { resut = append(resut, close) } } } // log.Print("getting neighbors for ", c, resut) return } func (f Field) ValidCoord(row, col int) bool { // log.Print("check valid ", row, col, row >= 0 && row < len(f.symbols) && col >= 0 && col < len(f.symbols[0])) return row >= 0 && row < len(f.symbols) && col >= 0 && col < len(f.symbols[0]) } func (f Field) String() (result string) { result += "\n" for _, line := range f.symbols { result += string(line) result += "\n" } return } func ReadField(filename string) (result Field) { bytes, err := os.ReadFile(filename) if err != nil { panic(err) } text := strings.TrimSpace(string(bytes)) lines := strings.Split(text, "\n") rows := make([][]rune, len(lines)) for rowNum, line := range lines { rows[rowNum] = []rune(line) for colNum, symb := range line { if symb == 'S' { result.RowStart = rowNum result.ColStart = colNum } } } result.symbols = rows return } func (f Field) PrintCoord(coords map[Coord]any) string { result := "" for rowNum, row := range f.symbols { for colNum, col := range row { _, marked := coords[Coord{Row: rowNum, Col: colNum}] if marked { result += "O" } else { result += string(col) } } result += "\n" } return result }