239 lines
4.3 KiB
Go
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
|
|
}
|