codexleast-common-multiple-periods.py
least-common-multiple-periods.py
"""Plot multiples of 12 and 18 and their shared event times.
Run from _media to save the PNG there. Tested with Python 3.14.4,
NumPy 2.3.5 and Matplotlib 3.10.7; dependencies are in pyproject.toml.
"""
from pathlib import Path
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
def main():
plt.rcParams.update({"font.size": 12})
fig, ax = plt.subplots(figsize=(8, 3.5), dpi=120)
fig.subplots_adjust(left=0.18, right=0.97, bottom=0.26, top=0.78)
common = np.array([0, 36, 72])
for day in common:
ax.axvspan(day - 1.3, day + 1.3, color="#e5f2e9", zorder=0)
for period, row, color in [(12, 1, "#245a81"), (18, 0, "#b45c24")]:
days = np.arange(0, 73, period)
ax.hlines(row, 0, 72, color="#b9b9b9", linewidth=1, zorder=1)
ax.scatter(days, np.full_like(days, row), marker="|", s=460,
linewidths=3, color=color, zorder=3)
ax.scatter(common, np.full_like(common, row), s=115,
facecolors="none", edgecolors="#27764d", linewidths=2,
zorder=4)
ax.annotate("First positive meeting: day 36", xy=(36, 1.15),
xytext=(36, 1.60), ha="center", fontsize=12,
arrowprops={"arrowstyle": "->", "color": "#27764d"})
ax.set(xlim=(-3, 75), ylim=(-0.45, 1.9), xlabel="Days since both events started")
ax.set_xticks(np.arange(0, 73, 6))
ax.set_yticks([1, 0], ["Every 12 days", "Every 18 days"])
ax.tick_params(axis="y", length=0, pad=10)
for spine in ("top", "left", "right"):
ax.spines[spine].set_visible(False)
ax.text(0.5, -0.39, "Shared times: 0, 36, 72, … | lcm(12, 18) = 36",
transform=ax.transAxes, ha="center", color="#27764d", fontsize=12)
fig.suptitle("Two schedules starting together", fontsize=16, y=0.94)
ax.set_facecolor("white")
fig.savefig(Path.cwd() / "least-common-multiple-periods.png",
facecolor="white", transparent=False)
plt.close(fig)
if __name__ == "__main__":
main()