"""
--- Day 24: Never Tell Me The Odds ---
https://adventofcode.com/2023/day/24
"""
import itertools as it
from dataclasses import dataclass

import z3
from aocd import data
from aocd import extra


@dataclass
class Hailstone:
    x: int
    y: int
    z: int
    dx: int
    dy: int
    dz: int

    @classmethod
    def fromline(cls, line):
        return cls(*map(int, line.replace("@", ",").split(",")))


def intersect2d(h0, h1):
    denom = h0.dx * h1.dy - h0.dy * h1.dx
    if denom == 0:
        return float("inf"), float("inf")
    f = h0.y * h0.dx - h0.x * h0.dy
    g = h1.x * h1.dy - h1.y * h1.dx
    px = (f * h1.dx + g * h0.dx) / denom
    py = (f * h1.dy + g * h0.dy) / denom
    return px, py


test_area_min = extra.get("test_area_min", 200_000_000_000_000)
test_area_max = extra.get("test_area_max", 400_000_000_000_000)
a = 0
hailstones = [Hailstone.fromline(line) for line in data.splitlines()]
for h0, h1 in it.combinations(hailstones, 2):
    px, py = intersect2d(h0, h1)
    if test_area_min <= px <= test_area_max and test_area_min <= py <= test_area_max:
        if (px > h0.x and h0.dx > 0) or (px < h0.x and h0.dx < 0):
            if (px > h1.x and h1.dx > 0) or (px < h1.x and h1.dx < 0):
                a += 1
print("answer_a:", a)


# https://www.reddit.com/r/adventofcode/comments/18pnycy/comment/kepu26z/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button ?
x, y, z, dx, dy, dz = z3.Ints("x y z dx dy dz")
ts = z3.Ints("t0 t1 t2")
s = z3.Solver()
for t, h in zip(ts, hailstones):
    s.add(t >= 0)
    s.add(h.x + t * h.dx == x + t * dx)
    s.add(h.y + t * h.dy == y + t * dy)
    s.add(h.z + t * h.dz == z + t * dz)
s.check()
m = s.model()
b = m[x].as_long() + m[y].as_long() + m[z].as_long()
print("answer_b:", b)
