mirror of
https://github.com/Threnklyn/advent-of-code-go.git
synced 2026-05-19 03:23:27 +02:00
day10: some cleanup
This commit is contained in:
@@ -15,3 +15,4 @@ Day | Name | Type of Algo & Notes
|
|||||||
7 | Amplification Circuit | - More Intcode... Piping together multiple Intcode computers 😳😳😳 <br> - Refactored Intcode computer to an OOP approach so a single computer maintains its data <br> - Also requires making __permutations generator__ <br> - Some gymnastics to make this circular, but its easier with this OOP approach and the "objects"/instances of a struct maintaining their own data <br> - Concurrency could be used to sync these Amps together...
|
7 | Amplification Circuit | - More Intcode... Piping together multiple Intcode computers 😳😳😳 <br> - Refactored Intcode computer to an OOP approach so a single computer maintains its data <br> - Also requires making __permutations generator__ <br> - Some gymnastics to make this circular, but its easier with this OOP approach and the "objects"/instances of a struct maintaining their own data <br> - Concurrency could be used to sync these Amps together...
|
||||||
8 | Space Image Format | 3D Array manipulation, pretty straight forward
|
8 | Space Image Format | 3D Array manipulation, pretty straight forward
|
||||||
9 | Sensor Boost | __MORE INTCODE. YAYY__ 🙃 <br> - A new parameter mode and opcode. <br> - __Really feeling the (tech) debt of some earlier design choices here, went back to refactor day07 before jumping into this one__, then it was a small bit of code for the relative param/opcode & resizing computer memory if necessary
|
9 | Sensor Boost | __MORE INTCODE. YAYY__ 🙃 <br> - A new parameter mode and opcode. <br> - __Really feeling the (tech) debt of some earlier design choices here, went back to refactor day07 before jumping into this one__, then it was a small bit of code for the relative param/opcode & resizing computer memory if necessary
|
||||||
|
10 | Monitoring Station | - This (part2) is my favorite algo... Yes I have a favorite algo <br> Fundamentally it's a geometry problem, angles and trig <br> - Part 1: Calculated via slopes <br> - Part 2: Using Arctangent to find angles an asteroid makes against a vertical line from the home base asteroid. Then those angles can be used to determine if Asteroids are covering each other, AND iterating through all of them can find the next angle Asteroid to vaporize
|
||||||
|
|||||||
+14
-44
@@ -1,24 +1,21 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"adventofcode/util"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// need to read the input.txt file (one folder up)
|
// need to read the input.txt file and split each line into a slice
|
||||||
// it will be a 2D slice coming from readInputFile now
|
input := util.ReadFile("../input.txt")
|
||||||
stringSlice := readInputFile("../input.txt")
|
stringSlice := strings.Split(input, "\n")
|
||||||
// fmt.Println(stringSlice, len(stringSlice))
|
|
||||||
|
// split into a 2D grid with each character
|
||||||
gridSlice := make([][]string, len(stringSlice))
|
gridSlice := make([][]string, len(stringSlice))
|
||||||
for i, str := range stringSlice {
|
for i, str := range stringSlice {
|
||||||
gridSlice[i] = strings.Split(str, "")
|
gridSlice[i] = strings.Split(str, "")
|
||||||
}
|
}
|
||||||
// fmt.Println(gridSlice, len(gridSlice))
|
|
||||||
|
|
||||||
// will be the final result value
|
// will be the final result value
|
||||||
var result int
|
var result int
|
||||||
@@ -29,9 +26,7 @@ func main() {
|
|||||||
if element == "#" {
|
if element == "#" {
|
||||||
// # are "asteroids", . are empty space
|
// # are "asteroids", . are empty space
|
||||||
// helper function will return how many asteroids are "findable" from the current asteroid
|
// helper function will return how many asteroids are "findable" from the current asteroid
|
||||||
|
|
||||||
visibleFromElement := visibleFromAsteroid(gridSlice, rowIndex, colIndex)
|
visibleFromElement := visibleFromAsteroid(gridSlice, rowIndex, colIndex)
|
||||||
// fmt.Println("visible:", visibleFromElement)
|
|
||||||
|
|
||||||
// take max of return of helper function at end of each loop
|
// take max of return of helper function at end of each loop
|
||||||
if result < visibleFromElement {
|
if result < visibleFromElement {
|
||||||
@@ -43,53 +38,30 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// print out the max found
|
// print out the max found
|
||||||
fmt.Println("result: ", result)
|
fmt.Printf("best asteroid for the station: row[%v] col[%v]\n", finalCoords[0], finalCoords[1]) // [13, 11]
|
||||||
fmt.Println("best asteroid for the station is at row, col", finalCoords) // [13, 11]
|
fmt.Println("from 13, 11 (y, x)", result)
|
||||||
fmt.Println("from 13, 11 (y, x)", visibleFromAsteroid(gridSlice, 13, 11))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func readInputFile(path string) []string {
|
// helper function will take, x and y coordinates, and the 2D slice
|
||||||
// var pixelString string
|
// will create a two maps of floats to booleans
|
||||||
pixelSlice := make([]string, 0)
|
// (one map to cover left side of asteroid, one map to cover right side of asteroid)
|
||||||
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
|
// 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
|
// and edge case handling for planets vertically above or below the current asteroid
|
||||||
func visibleFromAsteroid(grid [][]string, row, col int) (result int) {
|
func visibleFromAsteroid(grid [][]string, row, col int) (result int) {
|
||||||
// fmt.Println(grid)
|
|
||||||
// make the two maps
|
// make the two maps
|
||||||
leftMap, rightMap := make(map[float64]bool), make(map[float64]bool)
|
leftMap, rightMap := make(map[float64]bool), make(map[float64]bool)
|
||||||
// make the two booleans for up and down. nil value is false
|
// make the two booleans for up and down. zero value is false
|
||||||
var upBool, downBool bool
|
var upBool, downBool bool
|
||||||
|
|
||||||
// iterate through every element of the grid slices
|
// iterate through every element of the grid slices
|
||||||
for rowIndex, rowSlice := range grid {
|
for rowIndex, rowSlice := range grid {
|
||||||
for colIndex, element := range rowSlice {
|
for colIndex, element := range rowSlice {
|
||||||
|
// NOTE this control flow is _GROSS_. Better solution in part2 solution
|
||||||
// ensure element is an asteroid & not the asteroid that the helper function is being run on
|
// ensure element is an asteroid & not the asteroid that the helper function is being run on
|
||||||
if element == "#" && !(row == rowIndex && col == colIndex) {
|
if element == "#" && !(row == rowIndex && col == colIndex) {
|
||||||
rise := rowIndex - row
|
rise := rowIndex - row
|
||||||
run := colIndex - col
|
run := colIndex - col
|
||||||
|
|
||||||
// fmt.Println("avoid zero division")
|
|
||||||
// handle if the found asteroid is directly above the inputted row/col asteroid
|
// handle if the found asteroid is directly above the inputted row/col asteroid
|
||||||
if run == 0 {
|
if run == 0 {
|
||||||
if rise < 0 {
|
if rise < 0 {
|
||||||
@@ -107,7 +79,6 @@ func visibleFromAsteroid(grid [][]string, row, col int) (result int) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
slope := float64(rise) / float64(run)
|
slope := float64(rise) / float64(run)
|
||||||
// fmt.Println(slope)
|
|
||||||
// handle left or right map
|
// handle left or right map
|
||||||
if run < 0 {
|
if run < 0 {
|
||||||
// leftMap
|
// leftMap
|
||||||
@@ -127,6 +98,5 @@ func visibleFromAsteroid(grid [][]string, row, col int) (result int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fmt.Println(leftMap, rightMap, upBool, downBool)
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-20
@@ -10,7 +10,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Overall approach...
|
Overall approach:
|
||||||
- need to make a map of some kind
|
- need to make a map of some kind
|
||||||
make it a slice where each element is a struct
|
make it a slice where each element is a struct
|
||||||
- each struct will contain:
|
- each struct will contain:
|
||||||
@@ -36,8 +36,8 @@ type Asteroid struct {
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// read input.txt file, split it into a slice of lines
|
// read input.txt file, split it into a slice of lines
|
||||||
contents := util.ReadFile("../input.txt") // test/example case @ "./test.txt"
|
input := util.ReadFile("../input.txt")
|
||||||
stringSlice := strings.Split(contents, "\n")
|
stringSlice := strings.Split(input, "\n")
|
||||||
|
|
||||||
// generate 2D grid of each character from stringSlice
|
// generate 2D grid of each character from stringSlice
|
||||||
inputGrid := make([][]string, len(stringSlice))
|
inputGrid := make([][]string, len(stringSlice))
|
||||||
@@ -45,18 +45,7 @@ func main() {
|
|||||||
inputGrid[i] = strings.Split(str, "")
|
inputGrid[i] = strings.Split(str, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
//* tests while building the TangetAndDistance function
|
|
||||||
// fmt.Println(trig.TangentAndDistance(13, 11, 0, 11)) // 0 13
|
|
||||||
// fmt.Println(trig.TangentAndDistance(13, 11, 15, 11)) // 180 2
|
|
||||||
// fmt.Println(trig.TangentAndDistance(13, 11, 13, 16)) // 90 5
|
|
||||||
// fmt.Println(trig.TangentAndDistance(13, 11, 13, 9)) // 270 2
|
|
||||||
// fmt.Println(trig.TangentAndDistance(1, 1, 0, 2)) // 45 some sqrt
|
|
||||||
// fmt.Println(trig.TangentAndDistance(1, 1, 2, 2)) // 135 some sqrt
|
|
||||||
// fmt.Println(trig.TangentAndDistance(1, 1, 2, 0)) // 225 some sqrt
|
|
||||||
// fmt.Println(trig.TangentAndDistance(1, 1, 0, 0)) // 315 some sqrt
|
|
||||||
|
|
||||||
allAsteroids := makeAsteroidsSlice(inputGrid)
|
allAsteroids := makeAsteroidsSlice(inputGrid)
|
||||||
// fmt.Println(allAsteroids)
|
|
||||||
|
|
||||||
// need to start this just to the left of zero to get that as the first input
|
// need to start this just to the left of zero to get that as the first input
|
||||||
lastDegreeUsed := 359.999999
|
lastDegreeUsed := 359.999999
|
||||||
@@ -105,9 +94,6 @@ func main() {
|
|||||||
// if we pass over 360, subtract 360
|
// if we pass over 360, subtract 360
|
||||||
lastDegreeUsed -= 360
|
lastDegreeUsed -= 360
|
||||||
}
|
}
|
||||||
// fmt.Println(minDegDiff)
|
|
||||||
// fmt.Println("lastAsteroid", i, lastAsteroid)
|
|
||||||
// fmt.Println(indexOfAsteroidToDelete, allAsteroids[indexOfAsteroidToDelete])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// print the last used asteroid
|
// print the last used asteroid
|
||||||
@@ -125,13 +111,13 @@ func makeAsteroidsSlice(grid [][]string) []Asteroid {
|
|||||||
// if an asteroid is found...
|
// if an asteroid is found...
|
||||||
if element == "#" && !(rowIndex == 13 && colIndex == 11) {
|
if element == "#" && !(rowIndex == 13 && colIndex == 11) {
|
||||||
// calculate the degree and dist
|
// calculate the degree and dist
|
||||||
degree, dist := trig.TangentAndDistance(13, 11, rowIndex, colIndex)
|
// degree, dist := trig.TangentAndDistance(13, 11, rowIndex, colIndex)
|
||||||
// create an instance of an Asteroid struct and append it to the result slice
|
// create an instance of an Asteroid struct and append it to the result slice
|
||||||
ast := Asteroid{
|
ast := Asteroid{
|
||||||
x: rowIndex,
|
x: rowIndex,
|
||||||
y: colIndex,
|
y: colIndex,
|
||||||
degOffVert: degree,
|
degOffVert: trig.AngleOffVertical(13, 11, rowIndex, colIndex),
|
||||||
distance: dist,
|
distance: trig.Distance(13, 11, rowIndex, colIndex),
|
||||||
}
|
}
|
||||||
result = append(result, ast)
|
result = append(result, ast)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
.#..##.###...#######
|
|
||||||
##.############..##.
|
|
||||||
.#.######.########.#
|
|
||||||
.###.#######.####.#.
|
|
||||||
#####.##.#.##.###.##
|
|
||||||
..#####..#.#########
|
|
||||||
####################
|
|
||||||
#.####....###.#.#.##
|
|
||||||
##.#################
|
|
||||||
#####.##.###..####..
|
|
||||||
..######..##.#######
|
|
||||||
####.##.####...##..#
|
|
||||||
.#####..#.######.###
|
|
||||||
##...#.##########...
|
|
||||||
#.##########.#######
|
|
||||||
.####.#.###.###.#.##
|
|
||||||
....##.##.###..#####
|
|
||||||
.#.#.###########.###
|
|
||||||
#.#.#.#####.####.###
|
|
||||||
###.##.####.##.#..##
|
|
||||||
+29
-51
@@ -1,62 +1,40 @@
|
|||||||
package trig
|
package trig
|
||||||
|
|
||||||
import (
|
import "math"
|
||||||
"math"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TangentAndDistance docz
|
|
||||||
// startX will "always" be 13
|
|
||||||
// startY will "always" be 11
|
|
||||||
// 0 <= angleOffVery < 360
|
|
||||||
func TangentAndDistance(startX, startY, endX, endY int) (angleOffVert, distance float64) {
|
|
||||||
rise, run := float64(endX)-float64(startX), float64(endY)-float64(startY)
|
|
||||||
// fmt.Println(rise, run)
|
|
||||||
|
|
||||||
// edge cases for verticals
|
|
||||||
if run == 0 && rise < 0 {
|
|
||||||
return 0, -1 * rise // endXY is up
|
|
||||||
}
|
|
||||||
if run == 0 && rise > 0 {
|
|
||||||
return 180, rise // endXY is down
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle left or right?
|
|
||||||
if rise == 0 && run < 0 {
|
|
||||||
return 270, -1 * run // left
|
|
||||||
}
|
|
||||||
if rise == 0 && run > 0 {
|
|
||||||
return 90, run // right
|
|
||||||
}
|
|
||||||
|
|
||||||
// not verticals
|
|
||||||
// calculate return distance
|
|
||||||
distance = rise*rise + run*run
|
|
||||||
distance = math.Sqrt(distance)
|
|
||||||
|
|
||||||
// calculate arctangent which will be in radians
|
|
||||||
// determine quadrent
|
|
||||||
if rise < 0 && run > 0 { // top right
|
|
||||||
angleOffVert = -1 * math.Atan(run/rise) * 180 / math.Pi
|
|
||||||
} else if rise > 0 && run > 0 { // bottom right
|
|
||||||
angleOffVert = 90 + math.Atan(rise/run)*180/math.Pi
|
|
||||||
} else if rise > 0 && run < 0 { // bottom left
|
|
||||||
angleOffVert = 180 + -1*math.Atan(run/rise)*180/math.Pi
|
|
||||||
} else if rise < 0 && run < 0 { // top left
|
|
||||||
angleOffVert = 270 + math.Atan(rise/run)*180/math.Pi
|
|
||||||
}
|
|
||||||
|
|
||||||
return angleOffVert, distance
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
AngleOffVertical takes in two 2D points, it calculates the angle
|
AngleOffVertical takes in two 2D points, it calculates the angle
|
||||||
between the line between then and a vertical line. The angle
|
between the line and a vertical line (straight up from origin)
|
||||||
returned is to the right of the vertical, i.e. from the vertical
|
NOTE: "up"/"top" and "down" are lexically flipped b/c of drawing a grid
|
||||||
and through the (mathematical) first quadrant
|
where 0, 0 is the top left corner and higher numbers physically go DOWN
|
||||||
|
but lexically increase/go UP 🤦♂️
|
||||||
*/
|
*/
|
||||||
func AngleOffVertical(startX, startY, endX, endY int) float64 {
|
func AngleOffVertical(startX, startY, endX, endY int) float64 {
|
||||||
|
rise := float64(endX) - float64(startX)
|
||||||
|
run := float64(endY) - float64(startY)
|
||||||
|
|
||||||
return 0
|
var angle float64
|
||||||
|
// basically a big if/elseif/else block
|
||||||
|
switch {
|
||||||
|
case run == 0 && rise < 0: // up
|
||||||
|
angle = 0
|
||||||
|
case run == 0 && rise > 0: // down
|
||||||
|
angle = 180
|
||||||
|
case rise == 0 && run < 0: // left
|
||||||
|
angle = 270
|
||||||
|
case rise == 0 && run > 0: // right
|
||||||
|
angle = 90
|
||||||
|
case rise < 0 && run > 0: // top right
|
||||||
|
angle = -1 * math.Atan(run/rise) * 180 / math.Pi
|
||||||
|
case rise > 0 && run > 0: // bottom right
|
||||||
|
angle = 90 + math.Atan(rise/run)*180/math.Pi
|
||||||
|
case rise > 0 && run < 0: // bottom left
|
||||||
|
angle = 180 + -1*math.Atan(run/rise)*180/math.Pi
|
||||||
|
case rise < 0 && run < 0: // top left
|
||||||
|
angle = 270 + math.Atan(rise/run)*180/math.Pi
|
||||||
|
}
|
||||||
|
|
||||||
|
return angle
|
||||||
}
|
}
|
||||||
|
|
||||||
// Distance calculates the distance between two sets of 2D coordinates via Pythagorean's theorem
|
// Distance calculates the distance between two sets of 2D coordinates via Pythagorean's theorem
|
||||||
|
|||||||
Reference in New Issue
Block a user