110 lines
2.5 KiB
Go
110 lines
2.5 KiB
Go
|
|
package main
|
||
|
|
|
||
|
|
import (
|
||
|
|
"os"
|
||
|
|
"fmt"
|
||
|
|
"strconv"
|
||
|
|
"strings"
|
||
|
|
)
|
||
|
|
|
||
|
|
// data types
|
||
|
|
type Path struct {
|
||
|
|
start_x int
|
||
|
|
start_y int
|
||
|
|
end_x int
|
||
|
|
end_y int
|
||
|
|
}
|
||
|
|
|
||
|
|
// general util
|
||
|
|
func check(e error) {
|
||
|
|
if e != nil { panic(e) }
|
||
|
|
}
|
||
|
|
|
||
|
|
func get_next_steps(field [][]byte, path *Path) []Path {
|
||
|
|
paths := make([]Path, 0, 4)
|
||
|
|
x := path.end_x
|
||
|
|
y := path.end_y
|
||
|
|
val := field[y][x]
|
||
|
|
|
||
|
|
if y < len(field) - 1 {
|
||
|
|
down := field[y + 1][x]
|
||
|
|
if down == val + 1 {
|
||
|
|
paths = append(paths, Path{ start_x: path.start_x, start_y: path.start_y, end_x: x, end_y: y + 1 })
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if y > 0 {
|
||
|
|
up := field[y - 1][x]
|
||
|
|
if up == val + 1 {
|
||
|
|
paths = append(paths, Path{ start_x: path.start_x, start_y: path.start_y, end_x: x, end_y: y - 1 })
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if x < len(field[0]) - 1 {
|
||
|
|
right := field[y][x + 1]
|
||
|
|
if right == val + 1 {
|
||
|
|
paths = append(paths, Path{ start_x: path.start_x, start_y: path.start_y, end_x: x + 1, end_y: y })
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if x > 0 {
|
||
|
|
left := field[y][x - 1]
|
||
|
|
if left == val + 1 {
|
||
|
|
paths = append(paths, Path{ start_x: path.start_x, start_y: path.start_y, end_x: x - 1, end_y: y })
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return paths
|
||
|
|
}
|
||
|
|
|
||
|
|
func get_all_paths(field [][]byte) []Path {
|
||
|
|
paths := make([]Path, 0)
|
||
|
|
|
||
|
|
// init
|
||
|
|
for _y, line := range field {
|
||
|
|
for _x, val := range line {
|
||
|
|
if val == 0 {
|
||
|
|
paths = append(paths, Path{start_x: _x, end_x: _x, start_y: _y, end_y: _y})
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// step by step
|
||
|
|
for i := 0; i < 9; i++ {
|
||
|
|
new_paths := make([]Path, 0, len(paths))
|
||
|
|
for _, path := range paths {
|
||
|
|
new_paths = append(new_paths, get_next_steps(field, &path)...)
|
||
|
|
}
|
||
|
|
paths = new_paths
|
||
|
|
}
|
||
|
|
|
||
|
|
return paths
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
// main loop
|
||
|
|
func main() {
|
||
|
|
|
||
|
|
// read in file
|
||
|
|
dat, err := os.ReadFile("data.txt")
|
||
|
|
check(err)
|
||
|
|
dat_str := strings.TrimSpace(string(dat))
|
||
|
|
|
||
|
|
// contruct input as byte matrix
|
||
|
|
lines := strings.Split(dat_str, "\n")
|
||
|
|
input := make([][]byte, 0, len(lines))
|
||
|
|
for _, line := range lines {
|
||
|
|
matrix_line := make([]byte, 0, len(line))
|
||
|
|
for _, char := range []rune(line) {
|
||
|
|
num, err := strconv.Atoi(string(char))
|
||
|
|
check(err)
|
||
|
|
matrix_line = append(matrix_line, byte(num))
|
||
|
|
}
|
||
|
|
input = append(input, matrix_line)
|
||
|
|
}
|
||
|
|
|
||
|
|
// calc scores
|
||
|
|
m := make(map[Path]bool)
|
||
|
|
for _, path := range get_all_paths(input) {
|
||
|
|
m[path] = true
|
||
|
|
}
|
||
|
|
fmt.Println(len(m))
|
||
|
|
|
||
|
|
}
|