codex/divisor-count-prime-exponents.py

divisor-count-prime-exponents.py
"""Show all exponent choices for the divisors of 12; write basename PNG to cwd.

Tested with Python 3.14.4, NumPy 2.3.5, and Matplotlib 3.10.7.
Reproduce from the repository root: make _media/divisor-count-prime-exponents.png
"""

from pathlib import Path

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
import numpy as np


def main():
    exponents_two = np.arange(3)
    exponents_three = np.arange(2)
    divisors = 2 ** exponents_two[None, :] * 3 ** exponents_three[:, None]
    assert sorted(divisors.ravel().tolist()) == [1, 2, 3, 4, 6, 12]
    assert divisors.size == (2 + 1) * (1 + 1) == 6

    fig, ax = plt.subplots(figsize=(7.5, 4.5), dpi=140, facecolor="white")
    blue, ink = "#176997", "#243746"
    for j in exponents_three:
        for i in exponents_two:
            ax.add_patch(Rectangle((i - 0.5, j - 0.5), 1, 1,
                                   facecolor="#edf5fa" if j == 0 else "#fff1e4",
                                   edgecolor="white", linewidth=3))
            ax.text(i, j + 0.11, rf"$2^{i}\,3^{j}={divisors[j, i]}$",
                    fontsize=18, ha="center", va="center", color=ink)
            ax.text(i, j - 0.21, f"divisor {divisors[j, i]}",
                    fontsize=11, ha="center", va="center", color=blue)
    ax.set(xlim=(-0.5, 2.5), ylim=(-0.5, 1.5))
    ax.set_xticks(exponents_two, [f"i = {i}" for i in exponents_two])
    ax.set_yticks(exponents_three, [f"j = {j}" for j in exponents_three])
    ax.tick_params(axis="both", length=0, labelsize=12, pad=9)
    ax.set_xlabel("Choose the exponent of 2: three possibilities", fontsize=12, labelpad=11)
    ax.set_ylabel("Exponent of 3: two possibilities", fontsize=12, labelpad=12)
    for spine in ax.spines.values():
        spine.set_visible(False)
    ax.set_title(r"Each cell is one positive divisor: $d=2^i3^j$", fontsize=14, pad=17)
    fig.suptitle(r"$12=2^2\cdot3^1$: independent exponent choices", fontsize=17, y=0.96)
    fig.text(0.52, 0.04, r"$\tau(12)=(2+1)(1+1)=3\cdot2=6$",
             ha="center", fontsize=17, color=blue)
    fig.subplots_adjust(left=0.16, right=0.96, bottom=0.27, top=0.74)
    fig.savefig(Path.cwd() / Path(__file__).with_suffix(".png").name,
                facecolor="white", transparent=False)
    plt.close(fig)


if __name__ == "__main__":
    main()