package main import ( "bufio" "fmt" "os" "strconv" "strings" "time" ) const FILE_PATH = "./input.txt" const SIZE = 71 const BYTES = 1024 //const FILE_PATH = "./sample.txt" //const SIZE = 7 //const BYTES = 12 func LoadInput(filename string) ([]string, error) { file, err := os.Open(filename) if err != nil { return nil, err } defer file.Close() var lines []string scanner := bufio.NewScanner(file) for scanner.Scan() { lines = append(lines, scanner.Text()) } if err := scanner.Err(); err != nil { return nil, err } return lines, nil } type Vector2 struct { x int y int } type structuredInput = []Vector2 func TransformInput(lines []string) structuredInput { var result = make([]Vector2, len(lines)) var numbs []string var x int var y int for i, line := range lines { numbs = strings.Split(line, ",") x, _ = strconv.Atoi(numbs[0]) y, _ = strconv.Atoi(numbs[1]) result[i] = Vector2{x, y} } return result } const ( EMPTY = iota WALL = iota ) func generateGrid(size int, bytes int, memory []Vector2) [][]int { var result = make([][]int, size) for i := 0; i < size; i++ { result[i] = make([]int, size) for j := 0; j < size; j++ { result[i][j] = EMPTY } } for i := 0; i < bytes; i++ { result[memory[i].y][memory[i].x] = WALL } return result } func printField(field [][]int) { for y := 0; y < len(field); y++ { for x := 0; x < len(field[y]); x++ { if field[y][x] == EMPTY { fmt.Print(".") } else { fmt.Print("#") } } fmt.Println() } } var MOVEMENT = []Vector2{ {1, 0}, {0, 1}, {-1, 0}, {0, -1}, } func add(a Vector2, b Vector2) Vector2 { return Vector2{a.x + b.x, a.y + b.y} } func isInBounds(position Vector2, bounds Vector2) bool { return position.x >= 0 && position.x < bounds.x && position.y >= 0 && position.y < bounds.y } func Part1(input structuredInput) int { var result = 0 var start = Vector2{0, 0} var end = Vector2{SIZE - 1, SIZE - 1} var field = generateGrid(SIZE, BYTES, input) var bounds = Vector2{SIZE, SIZE} var score = make([][]int, SIZE) var poss = []Vector2{start} var point Vector2 var index int var temp Vector2 for i := 0; i < SIZE; i++ { score[i] = make([]int, SIZE) for j := 0; j < SIZE; j++ { score[i][j] = -1 } } score[start.y][start.x] = 0 for len(poss) > 0 { point = poss[0] index = 0 for i := 1; i < len(poss); i++ { if score[point.y][point.x] > score[poss[i].y][poss[i].x] { point = poss[i] index = i } } if point == end { result = score[end.y][end.x] break } poss = append(poss[:index], poss[index+1:]...) for i := 0; i < len(MOVEMENT); i++ { temp = add(point, MOVEMENT[i]) if isInBounds(temp, bounds) && score[temp.y][temp.x] == -1 && field[temp.y][temp.x] != WALL { score[temp.y][temp.x] = score[point.y][point.x] + 1 poss = append(poss, temp) } } } return result } func canFinish(field [][]int, start Vector2, finish Vector2, bounds Vector2) bool { var visited = make([][]bool, len(field)) for i := 0; i < len(visited); i++ { visited[i] = make([]bool, len(field[i])) } var poss = []Vector2{start} var point Vector2 var temp Vector2 for len(poss) > 0 { point = poss[0] poss = poss[1:] for i := 0; i < 4; i++ { temp = add(point, MOVEMENT[i]) if isInBounds(temp, bounds) && !visited[temp.y][temp.x] && field[temp.y][temp.x] != WALL { poss = append(poss, temp) visited[temp.y][temp.x] = true if temp == finish { return true } } } } return false } func Part2(input structuredInput) int { var result = 0 var start = Vector2{0, 0} var end = Vector2{SIZE - 1, SIZE - 1} var field = generateGrid(SIZE, BYTES, input) var bounds = Vector2{SIZE, SIZE} i := BYTES for canFinish(field, start, end, bounds) { field[input[i].y][input[i].x] = WALL i++ } i -= 1 fmt.Printf("%d,%d\n", input[i].x, input[i].y) return result } func main() { var start time.Time var elapsed time.Duration = 0 input, err := LoadInput(FILE_PATH) if err != nil { fmt.Println("Error loading input:", err) return } structuredInput := TransformInput(input) fmt.Println("Structured Input:", structuredInput) start = time.Now() fmt.Println("Solution Part 1: ", Part1(structuredInput)) elapsed = time.Since(start) fmt.Printf("Part 1 took %s\n", elapsed) start = time.Now() fmt.Println("Solution Part 2: ", Part2(structuredInput)) elapsed = time.Since(start) fmt.Printf("Part 2 took %s\n", elapsed) }