"""Experiment 1: add up 1 to n, two ways. O(n) vs O(1).

A loop does one addition per number, so its work grows with n.
The formula n(n+1)/2 does the same few operations whatever n is.
Each version runs 5 times per size; we report the median time.
"""
from common import median, save, time_runs

SIZES = [1_000, 100_000, 10_000_000]


def add_up_loop(n):
    total = 0
    steps = 0
    for i in range(1, n + 1):
        total += i
        steps += 1
    return total, steps


def add_up_formula(n):
    return n * (n + 1) // 2, 1


def main():
    results = []
    print(f"{'n':>12} | {'loop ms (median)':>16} | {'formula ms (median)':>19} | {'loop steps':>12} | {'formula steps':>13} | same answer?")
    for n in SIZES:
        (loop_total, loop_steps), loop_times = time_runs(add_up_loop, n)
        (formula_total, formula_steps), formula_times = time_runs(add_up_formula, n)
        same = loop_total == formula_total
        loop_ms = median(loop_times)
        formula_ms = median(formula_times)
        print(f"{n:>12,} | {loop_ms:>16.3f} | {formula_ms:>19.4f} | {loop_steps:>12,} | {formula_steps:>13} | {same}")
        results.append({
            "n": n,
            "answer": loop_total,
            "loop_ms": round(loop_ms, 3),
            "formula_ms": round(formula_ms, 4),
            "loop_runs_ms": [round(t, 3) for t in loop_times],
            "loop_steps": loop_steps,
            "formula_steps": formula_steps,
            "same_answer": same,
        })

    save("exp1", results)


if __name__ == "__main__":
    main()
