{
 "nbformat": 4,
 "nbformat_minor": 5,
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3"
  }
 },
 "cells": [
  {
   "cell_type": "code",
   "id": "cell-0",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": "# --- house style (the Press palette: accent/navy/gold/parchment) ---\nimport matplotlib as mpl\nACCENT, NAVY, GOLD, PARCH = '#7a1f1f', '#1f3a5f', '#b8860b', '#f7f2e7'\nmpl.rcParams.update({'figure.facecolor': PARCH, 'axes.facecolor': '#fffdf6',\n                     'axes.edgecolor': '#c9bfa3', 'font.family': 'serif'})\n\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom matplotlib import animation\n\nwA, wB = 11.0, 4.0\nq = int(wA // wB); r = wA - q * wB    # Euclidean division on weights (Thm 6.4)\nprint(f\"{wA}/{wB} = {q} + {r}/{wB}    (quotient {q}, remainder {r})\")\nprint(f\"reciprocal swap (Thm 6.1): {wB}/{wA} = {wB/wA:.4f} = 1/{wA/wB:.4f}\")\n\nfig, ax = plt.subplots(figsize=(8, 2.5))\ndef draw(t):\n    ax.clear()\n    filled = min(t * (q + 1), q + r / wB)   # stack whole copies of B, then the remainder\n    whole = int(filled)\n    for i in range(whole):\n        ax.barh(0, wB, left=i * wB, color=NAVY if i % 2 else ACCENT, edgecolor='k')\n    frac = filled - whole\n    if frac > 1e-9:\n        ax.barh(0, wB * frac, left=whole * wB, color=GOLD, edgecolor='k')\n    ax.barh(0, wA, fill=False, edgecolor='k', lw=2)\n    ax.set(xlim=(-0.2, wA + 0.5), yticks=[],\n           title=f\"how many B's fit in A?  {filled:.2f}  ->  {q} + {r:g}/{wB:g}  (Thm 6.4)\")\n\nani = animation.FuncAnimation(fig, draw, frames=np.linspace(0, 1, 60), interval=60)\n# Colab:  from IPython.display import HTML; HTML(ani.to_jshtml())\n# Web:    ani.save('py09_quotitive.gif', writer='pillow', fps=15)\nplt.show()\n"
  }
 ]
}