"""Lab to Code — Where does equilibrium land? Solve it with bisection.

A + B <=> C, K = 4, start with [A] = [B] = 1 M and no C.
Let x = mol/L of C formed. At equilibrium: x / (1 - x)**2 = K.
Rewrite as f(x) = x - K * (1 - x)**2 = 0 and find the root between 0 and 1.
"""


def f(x, K=4):
    return x - K * (1 - x) ** 2


def bisection(f, low, high, tol=1e-6):
    steps = 0
    while high - low > tol:
        mid = (low + high) / 2
        if f(low) * f(mid) <= 0:   # sign change on the left half
            high = mid
        else:                      # otherwise it's in the right half
            low = mid
        steps += 1
    return (low + high) / 2, steps


x, steps = bisection(f, 0, 1)
print(f"x = {x:.4f} M ({steps} steps)")
print(f"[A] = [B] = {1 - x:.3f} M, [C] = {x:.3f} M")
print(f"check K: {x / (1 - x) ** 2:.3f}")
