import shared
from scanf import scanf
from dataclasses import dataclass

@dataclass
class Probe:
    x: int
    y: int
    x_vel: int
    y_vel: int


@dataclass
class Box:
    x1: int
    x2: int
    y1: int
    y2: int

    @property
    def max_x(self):
        return max(self.x1, self.x2)

    @property
    def min_y(self):
        return min(self.y1, self.y2)


class TrickShot:
    def __init__(self, target, x_vel, y_vel):
        self.target = target
        self.probe = Probe(0, 0, x_vel, y_vel)
        self.y_max = -9999

    def step(self):
        self.probe.x += self.probe.x_vel
        self.probe.y += self.probe.y_vel
        if self.probe.y > self.y_max:
            self.y_max = self.probe.y
        self.probe.x_vel += towards_zero(self.probe.x_vel)
        self.probe.y_vel -= 1

    def check_in_target(self):
        return (
            self.target.x1 <= self.probe.x <= self.target.x2
            and self.target.y1 <= self.probe.y <= self.target.y2
        )

    def check_out_of_bounds(self):
        return self.probe.y < self.target.min_y or self.probe.x > self.target.max_x


def towards_zero(value):
    if value > 0:
        return -1
    elif value == 0:
        return 0
    else:
        return 1


def main():
    with open(shared.get_fname(17), "r") as f:
        target = Box(*scanf("target area: x=%d..%d, y=%d..%d", f.read()))

    hits = []
    for x in range(target.max_x + 1):
        for y in range(target.min_y, -target.min_y):
            t = TrickShot(target, x, y)
            while True:
                t.step()
                if t.check_in_target():
                    hits.append((x, y, t.y_max))
                    break
                elif t.check_out_of_bounds():
                    break

    hits = sorted(hits, key=lambda x: x[-1])
    highest = hits[-1][-1]
    print("highest", highest)
    print("hits", len(hits))


if __name__ == "__main__":
    main()
