AoC2021/src/day17/day17.go
2021-12-17 18:24:42 +01:00

139 lines
3.5 KiB
Go

package main
import (
"AOC2021/src/helper"
"fmt"
"os"
"strings"
)
type checkHitFunc func(int, [2]int) (bool, int)
type targetArea struct {
xValues [2]int
yValues [2]int
}
func main() {
args := os.Args[1:]
input, err := helper.GetInput(args[0])
if err != nil {
fmt.Println(err)
}
coordinateString := strings.Split(input[0], ": ")[1]
coordinateString = helper.RemoveCharactersFromString(coordinateString, "yx=")
coordinateStringSplit := strings.Split(coordinateString, ", ")
xValues, _ := helper.MapToNumber(strings.Split(coordinateStringSplit[0], ".."))
yValues, _ := helper.MapToNumber(strings.Split(coordinateStringSplit[1], ".."))
area := targetArea{xValues: [2]int{xValues[0], xValues[1]}, yValues: [2]int{yValues[0], yValues[1]}}
fmt.Println(area)
hitFunctionUpward := getcheckHitFunction(changeVelocityUpward, true)
hitFunctionForward := getcheckHitFunction(changeVelocityForward, false)
//Part 1
highestY, maxHeight := getHighestPossibleVelocityWhichStillHits(area.yValues, hitFunctionUpward)
fmt.Printf("Highest Y: %d Max Height: %d \n", highestY, maxHeight)
testPointsString, err := helper.GetInput("day17TestPart2Points.txt")
var testPoints [][2]int
for _, pointString := range testPointsString {
testPointIntArray, _ := helper.MapToNumber(strings.Split(pointString,","))
testPoints = append(testPoints, [2]int{testPointIntArray[0],testPointIntArray[1]})
}
//Part 2
possibleYs := getAllPossibleVelocitiesWhichStillHits(area.yValues, hitFunctionUpward, highestY, yValues[0])
possibleXs := getAllPossibleVelocitiesWhichStillHits(area.xValues, hitFunctionForward, xValues[1], 1)
fmt.Println(possibleXs)
fmt.Println(possibleYs)
sum := 0
for _, possibleY := range possibleYs {
for _, possibleX := range possibleXs {
if checkHitXAndY(possibleX,possibleY, &area){
sum +=1
}
}
}
fmt.Println(sum)
}
func getHighestPossibleVelocityWhichStillHits(target [2]int, checkHitFunc checkHitFunc) (int, int) {
hit := true
max := 0
n := 1000
for {
hit, max = checkHitFunc(n, target)
if hit {
return n, max
}
n--
}
}
func getAllPossibleVelocitiesWhichStillHits(target [2]int, checkHitFunc checkHitFunc, highestVelocity int, lowestVelocity int) (hits []int) {
n := highestVelocity
for n >= lowestVelocity {
hit, _ := checkHitFunc(n, target)
if hit {
hits = append(hits, n)
}
n--
}
return hits
}
func getcheckHitFunction(velocityChangeFunction func(*int), lowBorder bool) checkHitFunc {
var whileFunc func(int, [2]int, int) bool
if lowBorder {
whileFunc = func(n int,target [2]int, velcoity int) bool{
return n > target[0]
}
}else {
whileFunc = func(n int,target [2]int, velocity int) bool{
return n < target[1] && velocity != 0
}
}
return func(velocity int, target [2]int) (bool, int) {
n := 0
max := 0
for whileFunc(n,target,velocity) {
n += velocity
if n > max {
max = n
}
velocityChangeFunction(&velocity)
if n >= target[0] && n <= target[1] {
return true, max
}
}
return false, max
}
}
func changeVelocityUpward(velocity *int) {
*velocity -= 1
}
func changeVelocityForward(velocity *int) {
if *velocity > 0 {
*velocity -= 1
}
if *velocity < 0 {
*velocity += 1
}
}
func checkHitXAndY(forward int, upward int, area *targetArea) bool {
x := 0
y := 0
for x <= area.xValues[1] && y >= area.yValues[0] {
x += forward
y += upward
changeVelocityUpward(&upward)
changeVelocityForward(&forward)
if x <= area.xValues[1] && y >= area.yValues[0] && x >= area.xValues[0] && y <= area.yValues[1] {
return true
}
}
return false
}