AOC-2024/18/main.go
2024-12-19 01:37:47 +01:00

230 lines
4.4 KiB
Go

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)
}