package day_06 import ( "strings" ) type Direction int const ( UP Direction = iota RIGHT Direction = iota DOWN Direction = iota LEFT Direction = iota ) const ( VISITED = 'X' OCCUPIED = '#' FREE = '.' ) var toDirections = map[rune]Direction{ '^': UP, '>': RIGHT, 'v': DOWN, '<': LEFT, } var fromDirections = map[Direction]rune{ UP: '^', RIGHT: '>', DOWN: 'v', LEFT: '<', } // task:https://adventofcode.com/2024/day/5 // short summary - count visited steps func SolveBasic(input string) int { grid := visitationGrid(input) sum := 0 for _, row := range grid { for _, value := range row { if value == VISITED { sum++ } } } return sum } // task:https://adventofcode.com/2024/day/5#part2 // short summary - find all position that will create an infinite loop func SolveComplex(input string) int { grid := visitationGrid(input) dirGrid := loadGrid(input) startX, startY, startDir := findPlayer(dirGrid) dirGrid[startY][startX] = FREE positions := 0 for y, row := range grid { for x, value := range row { if value == VISITED && dirGrid[y][x] == FREE { dirGrid[y][x] = OCCUPIED curX := startX curY := startY curDir := startDir for inGrid(dirGrid, curX, curY) { if dirGrid[curY][curX] == fromDirections[curDir] { // we visited a same point second time in the same direction // which means we are in an infinite list positions++ break } dirGrid[curY][curX] = fromDirections[curDir] curX, curY, curDir = nextSpot(dirGrid, curX, curY, curDir) } dirGrid[y][x] = FREE clearDirGrid(dirGrid) } } } return positions } func clearDirGrid(grid [][]rune) { for y, row := range grid { for x, value := range row { if value != OCCUPIED { grid[y][x] = FREE } } } } func nextSpot(grid [][]rune, x int, y int, dir Direction) (int, int, Direction) { for { nx, ny := calculateNext(x, y, dir) if !inGrid(grid, nx, ny) { return nx, ny, dir } else if grid[ny][nx] != OCCUPIED { return nx, ny, dir } else { dir = (dir + 1) % 4 } } } func calculateNext(x int, y int, dir Direction) (int, int) { switch dir { case UP: return x, y - 1 case RIGHT: return x + 1, y case DOWN: return x, y + 1 case LEFT: return x - 1, y } panic("unknown direction") } func inGrid(grid [][]rune, x int, y int) bool { return x >= 0 && y >= 0 && x < len(grid[0]) && y < len(grid) } func findPlayer(grid [][]rune) (int, int, Direction) { for y, row := range grid { for x, value := range row { if dir, present := toDirections[value]; present { return x, y, dir } } } panic("Couldn't find player") } func loadGrid(input string) [][]rune { substrings := strings.Split(input, "\n") var grid [][]rune for _, line := range substrings { grid = append(grid, []rune(line)) } return grid } func visitationGrid(input string) [][]rune { grid := loadGrid(input) x, y, dir := findPlayer(grid) for inGrid(grid, x, y) { grid[y][x] = VISITED x, y, dir = nextSpot(grid, x, y, dir) } return grid }