diff options
author | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2024-12-20 15:33:32 +0100 |
---|---|---|
committer | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2024-12-20 15:33:32 +0100 |
commit | be164866553a91878487bfac8f63033de80a0494 (patch) | |
tree | ea92d6797c08efafaa9cb79cd90933b337597557 /day20/main.go | |
parent | fac8626030e19a50bf652b1f665d5836a3b79616 (diff) |
Day 20
Diffstat (limited to 'day20/main.go')
-rw-r--r-- | day20/main.go | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/day20/main.go b/day20/main.go new file mode 100644 index 0000000..3c5921e --- /dev/null +++ b/day20/main.go @@ -0,0 +1,111 @@ +package main + +import ( + "bufio" + "fmt" + "math" + "os" + "slices" + "strings" +) + +func main() { + fmt.Println(part1(readData("example.txt"))) + fmt.Println(1358) + fmt.Println(part1(readData("data.txt"))) +} + +func IntAbs(x int) int { + if x >= 0 { + return x + } else { + return -x + } +} + +func part1(maze [][]byte) (score1, score2 int) { + startX, startY := findInMaze(maze, 'S') + endX, endY := findInMaze(maze, 'E') + distMap := buildDistMap(maze, startX, startY, endX, endY) + + dirs := [][2]int{} + for dy := -20; dy <= 20; dy++ { + for dx := -20; dx <= 20; dx++ { + d := IntAbs(dx) + IntAbs(dy) + if d >= 1 && d <= 20 { + dirs = append(dirs, [2]int{dx, dy}) + } + } + } + + x, y := startX, startY + for x != endX || y != endY { + distNow := distMap[y][x] + xNext, yNext := x, y + for _, dir := range dirs { + x2, y2 := x+dir[0], y+dir[1] + dist := IntAbs(dir[0]) + IntAbs(dir[1]) + + if dist == 1 && maze[y2][x2] != '#' && distMap[y2][x2] > distNow { + xNext, yNext = x2, y2 + } + + if dist > 1 && x2 >= 0 && y2 >= 0 && y2 < len(maze) && x2 < len(maze[y2]) && distMap[y2][x2] > distNow && maze[y2][x2] != '#' { + saved := distMap[y2][x2] - distNow - dist + if dist == 2 && saved >= 100 { + score1++ + } + if saved >= 100 { + score2++ + } + } + } + x, y = xNext, yNext + } + + return +} + +func buildDistMap(maze [][]byte, x, y int, endX, endY int) (distMap [][]int) { + distMap = make([][]int, len(maze)) + for y, _ := range distMap { + distMap[y] = make([]int, len(maze[0])) + for x := range distMap[y] { + distMap[y][x] = math.MaxInt + } + } + + distMap[y][x] = 0 + var dirs = [4][2]int{{1, 0}, {-1, 0}, {0, 1}, {0, -1}} + + for x != endX || y != endY { + for _, dir := range dirs { + x2, y2 := x+dir[0], y+dir[1] + if maze[y2][x2] != '#' && distMap[y2][x2] == math.MaxInt { + distMap[y2][x2] = distMap[y][x] + 1 + x, y = x2, y2 + break + } + } + } + + return +} + +func findInMaze(maze [][]byte, needle byte) (x, y int) { + for y, line := range maze { + if x := slices.Index(line, needle); x >= 0 { + return x, y + } + } + panic("not found") +} + +func readData(fileName string) (maze [][]byte) { + fp, _ := os.Open(fileName) + scanner := bufio.NewScanner(fp) + for scanner.Scan() { + maze = append(maze, []byte(strings.TrimSpace(scanner.Text()))) + } + return +} |