Files
advent-of-code-go/day10/part1/main.go
T
2020-02-01 21:48:32 -05:00

133 lines
3.7 KiB
Go

package main
import (
"bufio"
"fmt"
"log"
"os"
"path/filepath"
"strings"
)
func main() {
// need to read the input.txt file (one folder up)
// it will be a 2D slice coming from readInputFile now
stringSlice := readInputFile("../input.txt")
// fmt.Println(stringSlice, len(stringSlice))
gridSlice := make([][]string, len(stringSlice))
for i, str := range stringSlice {
gridSlice[i] = strings.Split(str, "")
}
// fmt.Println(gridSlice, len(gridSlice))
// will be the final result value
var result int
var finalCoords [2]int
// iterate through entire slice, for each asteroid found, call a helper function
for rowIndex, rowSlice := range gridSlice {
for colIndex, element := range rowSlice {
if element == "#" {
// # are "asteroids", . are empty space
// helper function will return how many asteroids are "findable" from the current asteroid
visibleFromElement := visibleFromAsteroid(gridSlice, rowIndex, colIndex)
// fmt.Println("visible:", visibleFromElement)
// take max of return of helper function at end of each loop
if result < visibleFromElement {
result = visibleFromElement
finalCoords[0], finalCoords[1] = rowIndex, colIndex
}
}
}
}
// print out the max found
fmt.Println("result: ", result)
fmt.Println("best asteroid for the station is at row, col", finalCoords) // [13, 11]
fmt.Println("from 13, 11 (y, x)", visibleFromAsteroid(gridSlice, 13, 11))
}
func readInputFile(path string) []string {
// var pixelString string
pixelSlice := make([]string, 0)
absPath, _ := filepath.Abs(path)
file, err := os.Open(absPath)
if err != nil {
log.Fatal(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
// pixelString = line
pixelSlice = append(pixelSlice, line)
}
// return pixelString
return pixelSlice
}
// helper function will take, x and y coordinates, and the 2D slices?
// will create a two maps of floats to booleans (one map to cover left side of asteroid, one map to cover right side of asteroid)
// so that anything that is blocked will not be double counted
// will need edge case handling for planets vertically above or below the current asteroid
func visibleFromAsteroid(grid [][]string, row, col int) (result int) {
// fmt.Println(grid)
// make the two maps
leftMap, rightMap := make(map[float64]bool), make(map[float64]bool)
// make the two booleans for up and down. nil value is false
var upBool, downBool bool
// iterate through every element of the grid slices
for rowIndex, rowSlice := range grid {
for colIndex, element := range rowSlice {
// ensure element is an asteroid & not the asteroid that the helper function is being run on
if element == "#" && !(row == rowIndex && col == colIndex) {
rise := rowIndex - row
run := colIndex - col
// fmt.Println("avoid zero division")
// handle if the found asteroid is directly above the inputted row/col asteroid
if run == 0 {
if rise < 0 {
// check down
// note that up and down are semantically "flipped" due to the 2 row being "above" the 0 row
if !downBool {
downBool = true
result++
}
} else {
if !upBool {
upBool = true
result++
}
}
} else {
slope := float64(rise) / float64(run)
// fmt.Println(slope)
// handle left or right map
if run < 0 {
// leftMap
if _, inLeftMap := leftMap[slope]; !inLeftMap {
leftMap[slope] = true
result++
}
} else {
// rightMap
if _, inRightMap := rightMap[slope]; !inRightMap {
rightMap[slope] = true
result++
}
}
}
}
}
}
// fmt.Println(leftMap, rightMap, upBool, downBool)
return result
}