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