[ADD] Added day 18 solution
This commit is contained in:
parent
ff3010e617
commit
9bde8dea96
3 changed files with 3705 additions and 0 deletions
3450
18/input.txt
Normal file
3450
18/input.txt
Normal file
File diff suppressed because it is too large
Load diff
230
18/main.go
Normal file
230
18/main.go
Normal file
|
|
@ -0,0 +1,230 @@
|
||||||
|
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)
|
||||||
|
}
|
||||||
25
18/sample.txt
Normal file
25
18/sample.txt
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
5,4
|
||||||
|
4,2
|
||||||
|
4,5
|
||||||
|
3,0
|
||||||
|
2,1
|
||||||
|
6,3
|
||||||
|
2,4
|
||||||
|
1,5
|
||||||
|
0,6
|
||||||
|
3,3
|
||||||
|
2,6
|
||||||
|
5,1
|
||||||
|
1,2
|
||||||
|
5,5
|
||||||
|
2,5
|
||||||
|
6,5
|
||||||
|
1,4
|
||||||
|
0,4
|
||||||
|
6,4
|
||||||
|
1,1
|
||||||
|
6,1
|
||||||
|
1,0
|
||||||
|
0,5
|
||||||
|
1,6
|
||||||
|
2,0
|
||||||
Loading…
Reference in a new issue