# /// script
# requires-python = ">=3.10"
# dependencies = ["numpy"]
# ///
# Copyright (c) 2026 Aayush Sharma · SPDX-License-Identifier: MIT
# https://thedataengineering.com/lab-code/LICENSE.txt
"""Find the square-root interval by simulation.

A table whose extra read cost grows by r per hour for every hour since the
last compaction, and a compaction that costs C. Simulates 1,000 hours for
intervals T from 1 to 500 hours, finds the cheapest, and compares with
√(2C/r); then quadruples r.
"""
import argparse, json
import numpy as np

p = argparse.ArgumentParser(description=__doc__.splitlines()[0])
p.add_argument("--c", type=float, default=1800, help="Compaction cost C.")
p.add_argument("--r", type=float, default=0.25, help="Read-cost growth per hour r.")
p.add_argument("--hours", type=int, default=1000, help="Simulated hours.")
p.add_argument("--json", help="Also write the results to this JSON file.")
args = p.parse_args()

def simulate(C, r):
    out = []
    for T in range(1, 500):
        cost, age = 0.0, 0
        for h in range(args.hours):
            cost += r * age; age += 1                                          # the read penalty grows with age
            if age == T: cost += C; age = 0                                    # compact
        out.append({"T": T, "cost_per_hour": cost / args.hours, "formula": C / T + r * T / 2})
    return out
rows = []
for r in (args.r, 4 * args.r):
    sim = simulate(args.c, r); best = min(sim, key=lambda x: x["cost_per_hour"])
    rows.append({"r": r, "best_T": best["T"], "formula_T": (2 * args.c / r) ** 0.5, "best_cost": best["cost_per_hour"]})
    if r == args.r: curve = [x for x in sim if x["T"] % 5 == 0 or x["T"] < 5]
for x in rows: print(f"r = {x['r']}: best T = {x['best_T']} h (formula √(2C/r) = {x['formula_T']:.0f} h), cost {x['best_cost']:.1f} per hour")

if args.json:
    with open(args.json, "w") as f:
        json.dump({"tables": {"best": rows, "curve": curve}}, f)
