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 }