from math import sqrt from tools.aoc import AOCDay from typing import Any def fire(velX: int, velY: int, minX: int, maxX: int, minY: int, maxY: int) -> (bool, int): highY, posX, posY = 0, velX, velY while not posX > maxX and not posY < minY: if velX > 0: velX -= 1 elif posX < minX: break velY -= 1 posX += velX posY += velY if posY > highY: highY = posY hit = minX <= posX - velX <= maxX and minY <= posY - velY <= maxY return hit, highY if hit else minY class Day(AOCDay): inputs = [ [ (45, "test_input17"), (5151, "input17") ], [ (112, "test_input17"), (968, "input17") ] ] def getBoundaries(self) -> (int, int, int, int): _, xRange, yRange = self.getInput().split("=") minX, maxX = map(int, xRange[:-3].split("..")) minY, maxY = map(int, yRange.split("..")) return minX, maxX, minY, maxY def part1(self) -> Any: minX, maxX, minY, maxY = self.getBoundaries() return max(fire(x, y, minX, maxX, minY, maxY)[1] for x in range(maxX) for y in range(abs(minY))) def part2(self) -> Any: minX, maxX, minY, maxY = self.getBoundaries() hitCounter = 0 for x in range(int(sqrt(maxX)), maxX + 1): for y in range(minY, abs(minY)): hitCounter += fire(x, y, minX, maxX, minY, maxY)[0] return hitCounter if __name__ == '__main__': day = Day(2021, 17) day.run(verbose=True)