2019/day10/main.go
2019-12-12 18:05:24 +01:00

239 lines
4.3 KiB
Go

package main
import (
"bufio"
"log"
"math"
"os"
)
type Position struct {
X int
Y int
}
func main() {
file, err := os.Open("input.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
t2 := make([]string, 0)
scanner := bufio.NewScanner(file)
for scanner.Scan() {
t2 = append(t2, scanner.Text())
}
field, asteroids := ParseStringSliceToField(t2)
SolvePzl1(field, asteroids)
}
func SolvePzl1(field [][]int, asteroids []Position) {
highestFoundAstros := math.MinInt32
pos := Position{}
for _, astro := range asteroids {
sum := CountAsteroidsFromPosition(field, astro.X, astro.Y)
if highestFoundAstros < sum {
highestFoundAstros = sum
pos = astro
}
}
log.Printf("Part1: Found %d Astros at Position(%d,%d) from %d Astros", highestFoundAstros, pos.X, pos.Y, len(asteroids))
}
func ParseStringSliceToField(view []string) (field [][]int, asteroids []Position) {
field = make([][]int, 0)
asteroids = make([]Position, 0)
x, y := 0, 0
for i, line := range view {
x = 0
field = append(field, make([]int, 0))
for j := 0; j < len(line); j++ {
if "#" == string(line[j]) {
field[i] = append(field[i], 0)
asteroids = append(asteroids, Position{X: x, Y: y})
} else {
field[i] = append(field[i], -1)
}
x++
}
y++
}
return
}
func CountAsteroidsFromPosition(field [][]int, posX, posY int) (sum int) {
duplicate := Copy2DSlice(field)
steps := make(map[int]int, 0)
for y := 0; y < len(duplicate); y++ {
for x := 0; x < len(duplicate[y]); x++ {
if x == posX && y == posY {
continue
}
stepX := x - posX
stepY := y - posY
gcd := GCD(stepY, stepX)
if gcd == 0 {
if stepX > 0 {
stepX = 1
} else if stepX < 0 {
stepX = -1
} else if stepY > 0 {
stepY = 1
} else if stepY < 0 {
stepY = -1
}
} else {
stepX, stepY = stepX/gcd, stepY/gcd
}
if v, ok := steps[stepX]; ok && v == stepY {
continue
}
steps[stepX] = stepY
curX, curY := posX, posY
found := false
for true {
curX += stepX
curY += stepY
if curY < 0 || curX < 0 || curY >= len(duplicate) || curX >= len(duplicate[curY]) {
break
}
if duplicate[curY][curX] >= 0 {
//log.Printf("(%d,%d) from (%d,%d)", curX, curY, stepX, stepY)
if !found {
found = true
sum++
}
duplicate[curY][curX] = -2
}
}
}
}
return
}
func Vaporized(field [][]int, posX, posY int) {
destroyed := make([]Position, 0)
degree := 0.0
// 0 bis 180 Grad positives steps X
// 180 bis 0 Grad negatives steps X
// 90 bis 270 Grad positives steps Y
// 270 bi 90 Grad negatives steps Y
for true {
// Handle fixed Values
if degree == 270 {
currentX := posX
for true {
currentX--
if currentX < 0 {
break
}
if field[posY][currentX] > 0 {
field[posY][currentX] = -1
destroyed = append(destroyed, Position{Y: posY, X: currentX})
break
}
}
degree++
} else if degree == 90 {
currentX := posX
for true {
currentX++
if len(field[posY]) <= currentX {
break
}
if field[posY][currentX] > 0 {
field[posY][currentX] = -1
destroyed = append(destroyed, Position{Y: posY, X: currentX})
break
}
}
degree++
} else if degree == 0 {
currentY := posY
for true {
currentY--
if currentY < 0 {
break
}
if field[currentY][posX] > 0 {
field[currentY][posX] = -1
destroyed = append(destroyed, Position{Y: currentY, X: posX})
break
}
}
degree++
} else if degree == 180 {
currentY := posY
for true {
currentY++
if len(field) <= currentY {
break
}
if field[currentY][posX] > 0 {
field[currentY][posX] = -1
destroyed = append(destroyed, Position{Y: currentY, X: posX})
break
}
}
degree++
}
if degree > 0 && degree < 90 {
currentX := posX
for ; currentX < len(field[0]); currentX++ {
for y := 0; y < len(field)-posY; y++ {
}
}
}
}
}
func Copy2DSlice(matrix [][]int) (duplicate [][]int) {
duplicate = make([][]int, len(matrix))
for i := range matrix {
duplicate[i] = make([]int, len(matrix[i]))
copy(duplicate[i], matrix[i])
}
return
}
// greatest common divisor (GCD) via Euclidean algorithm
func GCD(a, b int) int {
for b != 0 {
t := b
b = a % b
a = t
}
if a < 0 {
a = a * -1
}
return a
}