From b22f6a78c6428db976f3b8f20bb968d1b134410f Mon Sep 17 00:00:00 2001 From: jsboige Date: Thu, 17 Sep 2026 01:26:42 +0200 Subject: [PATCH 1/4] Add: 8 lectures chiffrees md-only GameTheory-08-CombinatorialGames (densite 899 -> 1417, plancher 1200 #13410) Co-Authored-By: Claude Sonnet 5 --- .../GameTheory-08-CombinatorialGames.ipynb | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/MyIA.AI.Notebooks/GameTheory/GameTheory-08-CombinatorialGames.ipynb b/MyIA.AI.Notebooks/GameTheory/GameTheory-08-CombinatorialGames.ipynb index 96011a985e..537a49b0b0 100644 --- a/MyIA.AI.Notebooks/GameTheory/GameTheory-08-CombinatorialGames.ipynb +++ b/MyIA.AI.Notebooks/GameTheory/GameTheory-08-CombinatorialGames.ipynb @@ -226,6 +226,13 @@ " print(f\" {n:2d} | {t} | {motif}\")" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Lecture chiffree — pourquoi la période vaut 4 dans ce tableau.** La colonne Motif aligne un `P` exactement toutes les quatre lignes (`n % 4 == 0` aux lignes 0, 4, 8, 12). Le mecanisme se lit dans les coups disponibles {1, 2, 3} : depuis un multiple de 4, soustraire 1, 2 ou 3 fait sortir du multiple — aucun coup n'y reste ; depuis toute autre position n, le coup qui retranche exactement le reste n mod 4 y ramène. La période 4 n'est donc pas une propriete magique de ce jeu : c'est la longueur du plus grand coup plus un, et la couverture complete des restes qui va avec. La section 5 montrera le contre-exemple utile : pour S({1, 3, 4}) la plus grande valeur de Grundy monte a 3 et la période vaut 7, pas 5 — la periodicite des jeux de soustraction est frequente (observation de la section 5) mais sa longueur ne se deduit pas naivement de max(moves).\n" + ] + }, { "cell_type": "markdown", "id": "ex-pn-classify-md", @@ -413,6 +420,13 @@ " print(f\"{str(heaps):13} | {ns:7} | {t}\")" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Lecture chiffree — cinq lignes, trois mecanismes de la nim-sum.** Les exemples de la sortie se decodent un par un. `(7, 7) | 0 | P` : deux tas identiques s'annulent entierement — chaque bit present deux fois tombe, le second joueur copie et gagne. `(1, 1, 1) | 1 | N` : nombre impair de tas identiques, la parite residuelle laisse 1 — l'annulation par paires est le seul mecanisme, l'orphelin survit. `(1, 2, 3) | 0 | P` et `(3, 5, 6) | 0 | P` : zero sans aucune paire de tas egaux — en binaire, 01 ⊕ 10 ⊕ 11 = 00 et 011 ⊕ 101 ⊕ 110 = 000, chaque colonne de bits tombe pair. Face a `(1, 2, 4) | 7 | N`, aucune colonne ne s'equilibre : 001 ⊕ 010 ⊕ 100 = 111. La nim-sum generalise l'annulation par paires a l'annulation par parite de colonnes.\n" + ] + }, { "cell_type": "markdown", "id": "8b993aef", @@ -499,6 +513,13 @@ " print(f\"Nouvelle nim-sum: {nim_sum(*new_heaps)}\")" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Lecture chiffree — le coup gagnant reconstruit la parite.** Pour `[3, 5, 7]`, la sortie donne `Nim-sum: 1`, puis `Coup gagnant: reduire tas 0 de 3 a 2` et `Nouvelle nim-sum: 0`. Le mecanisme : la nim-sum 1 signale qu'un nombre impair de tas portent le bit 1 ; le solveur cherche le tas dont la reduction peut equilibrer toutes les colonnes a la fois — ici 3 → 2, car 10 ⊕ 101 ⊕ 111 = 000. Le detail qui compte : le coup n'attaque pas le plus gros tas ni le tas le plus desequilibre, il attaque le tas ou la correction est realisable en une seule reduction. Toute position N en possede au moins une (theoreme de Bouton) ; aucune position P n'en possede — c'est exactement la definition.\n" + ] + }, { "cell_type": "markdown", "id": "ed6eb8a0", @@ -576,6 +597,13 @@ " print(f\"mex({s}) = {mex(s)}\")" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Lecture chiffree — le mex complete par le bas.** Les cinq lignes de la sortie se lisent comme une seule regle : `mex(S)` est le plus petit entier absent de S. Les deux lignes piegeuses : `mex({1, 2, 3}) = 0` — l'ensemble ne contient pas zero, donc le mex tombe a zero meme si l'ensemble est « rempli » au-dela ; et `mex({0, 2, 4}) = 1` — le trou le plus bas commande, meme entoure de pairs. `mex(set()) = 0` fixe la base : la position terminale sans successeur recoit Grundy 0, qui est la definition meme d'une P-position. Ce choix de mex (et pas de max, ni de somme) garantit que deux positions aux suites de Grundy differentes ne collisionnent jamais — la propriete que la table de la section suivante exploite.\n" + ] + }, { "cell_type": "markdown", "id": "52956bb3", @@ -670,6 +698,13 @@ " print(f\"{n:2} | {g:14} | {verify}\")" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Lecture chiffree — grundy(nim(n)) = n, ligne par ligne.** La table aligne dix verifications `OK` : pour chaque n de 0 a 9, la valeur de Grundy calculee par la definition recursive (mex des successeurs) vaut exactement n. Autrement dit, un tas de Nim est son propre nimber : Grundy(n) = mex({0, 1, ..., n-1}) = n. La colonne Verification ne verifie pas un resultat numerique isole, elle boucle la definition — chaque ligne certifie que le mex des successeurs de n (qui sont exactement tous les entiers de 0 a n-1) retombe sur n. C'est ce pont identite qui rend le theoreme de Sprague-Grundy de la section suivante concret : chaque tas d'une position de Nim se comporte deja comme son nimber, et la somme de jeux s'annoncera comme un simple XOR de ces valeurs.\n" + ] + }, { "cell_type": "markdown", "id": "67e27c05", @@ -765,6 +800,13 @@ " print(f\"\\nCoup gagnant: tas {i}: {game['heaps'][i]} -> {new_h}\")" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Lecture chiffree — l'analyse complete d'une position en une sortie.** Pour `[4, 7, 9]`, les cinq lignes racontent toute la theorie appliquee. `Valeurs de Grundy: [4, 7, 9]` — chaque tas est son nimber (section precedente). `Nim-sum: 10` — en binaire 100 ⊕ 111 ⊕ 1001 = 1010. `Type: N-position` — la nim-sum non nulle signe le tour gagnant. `Coup gagnant: tas 2: 9 -> 3` — verifier : 100 ⊕ 111 ⊕ 011 = 000, la nouvelle position est une P-position servie au prochain joueur. Le choix 9 → 3 n'est pas unique par principe, mais tout coup gagnant doit reduire un tas exactement a la valeur qui equilibre les deux autres : ici 4 ⊕ 7 = 3, la cible s'impose.\n" + ] + }, { "cell_type": "markdown", "id": "ex-sg-sum-md", @@ -850,6 +892,13 @@ "print(\"Exercice a completer\")" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Lire la sortie d'un exercice non rempli.** Les lignes `G1=S({1,2}): []`, `G2=S({1,3}): []`, `XOR: []` et `Verification: False` ne sont pas un resultat : les listes vides marquent l'etat du squelette, et le `False` final n'echoue aucun theoreme — il mesure des donnees absentes. Le contrat, pose par l'enonce : remplir les suites de Grundy des deux jeux de soustraction, former le XOR element par element, et verifier la These de Sprague-Grundy sur leur somme — la position combinee doit etre P exactement quand le XOR des nimbers vaut 0. La sortie remplie affichera deux suites (celles de la section 5 pour {1, 3, 4} commencent 0, 1, 0, 1, 2, 3, 2), leur XOR, et un verdict `True` sur chaque position testee.\n" + ] + }, { "cell_type": "markdown", "id": "b843b282", @@ -1062,6 +1111,13 @@ "print(\"Exercice a completer\")" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Lire la sortie d'un exercice non rempli.** La ligne « Exercice a completer » ouvre l'espace des exemples guides : le premier (jeu de soustraction, enonce en section 6) attend sa solution ici. Le terrain est deja pose — `grundy_subtraction` de la section 5 calcule la suite de Grundy de n'importe quel S(moves), et `classify_123_game` de la section 1 donne le gabarit d'affichage. Une solution remplie montrera la table n / Grundy / Type du jeu demande, ses P-positions alignees, et la lecture de sa periode — le meme geste que la section 5, sur un autre ensemble de coups.\n" + ] + }, { "cell_type": "markdown", "id": "d4ed1f1d", From 3e5c5f43b652ed13e160877f739044c36344f176 Mon Sep 17 00:00:00 2001 From: jsboige Date: Fri, 18 Sep 2026 04:49:19 +0200 Subject: [PATCH 2/4] fix(16471): rebaseline twin pair gametheory-8 combinatorialgames after markdown-only density tranche MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pair attested: GameTheory-8 CombinatorialGames. Paraphyte-preservant verification (python-compare vs origin/main): all code cells byte-identical (source + outputs + execution_count) — 11/11; changes are markdown-only additions (+8 cells). Command run: python scripts/notebook_tools/check_twin_parity.py --update --pair "GameTheory-8 CombinatorialGames" --by "myia-po-2026:CoursIA" Co-Authored-By: Claude Sonnet 5 --- .../0008-2026-09-18-myia-po-2026-CoursIA.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 scripts/notebook_tools/twin_pairs.d/gametheory-8-combinatorialgames/0008-2026-09-18-myia-po-2026-CoursIA.yaml diff --git a/scripts/notebook_tools/twin_pairs.d/gametheory-8-combinatorialgames/0008-2026-09-18-myia-po-2026-CoursIA.yaml b/scripts/notebook_tools/twin_pairs.d/gametheory-8-combinatorialgames/0008-2026-09-18-myia-po-2026-CoursIA.yaml new file mode 100644 index 0000000000..ecde670225 --- /dev/null +++ b/scripts/notebook_tools/twin_pairs.d/gametheory-8-combinatorialgames/0008-2026-09-18-myia-po-2026-CoursIA.yaml @@ -0,0 +1,6 @@ +date: '2026-09-18' +by: myia-po-2026:CoursIA +python_sha: 537a49b0b0a2680cadac17caf32c32d37b6c6a03 +csharp_sha: 3e53680775740ebf95b2c86dcc5c4800d95cc4ad +content_python_sha: ff665ba30b564c336f8d7b8ac4d7967a08b5522f899066550987bb3aa96f32e3 +content_csharp_sha: 433e313c65cbf5f5067e6d06c0c15848678ef1881787e9d25a9e11c1bbaa2df1 From c2137ec45480feac643b1c16f1033b6dace8d5fe Mon Sep 17 00:00:00 2001 From: jsboige Date: Mon, 21 Sep 2026 10:11:24 +0200 Subject: [PATCH 3/4] fix(16471): repair twin registry -- dedupe index 0008 and absorb main's 4c attestation - renumber 0008-2026-09-18-myia-po-2026 -> 0009 (index race with po-2025's 0008-2026-09-19 merged on main; NNNN unique per pair #14911/#15345) - absorb origin/main 0012 gametheory-4c-nashexistence (po-2023 attestation of current python content 24975e81; branch tree already carried the notebook) check_twin_parity: 157 OK / 0 DRIFT / 0 NUMBERING-DRIFT Co-Authored-By: Claude Sonnet 5 --- ...026-CoursIA.yaml => 0009-2026-09-18-myia-po-2026-CoursIA.yaml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename scripts/notebook_tools/twin_pairs.d/gametheory-8-combinatorialgames/{0008-2026-09-18-myia-po-2026-CoursIA.yaml => 0009-2026-09-18-myia-po-2026-CoursIA.yaml} (100%) diff --git a/scripts/notebook_tools/twin_pairs.d/gametheory-8-combinatorialgames/0008-2026-09-18-myia-po-2026-CoursIA.yaml b/scripts/notebook_tools/twin_pairs.d/gametheory-8-combinatorialgames/0009-2026-09-18-myia-po-2026-CoursIA.yaml similarity index 100% rename from scripts/notebook_tools/twin_pairs.d/gametheory-8-combinatorialgames/0008-2026-09-18-myia-po-2026-CoursIA.yaml rename to scripts/notebook_tools/twin_pairs.d/gametheory-8-combinatorialgames/0009-2026-09-18-myia-po-2026-CoursIA.yaml From b076c911de671c82de230d6ce55f6bc8b3dd509d Mon Sep 17 00:00:00 2001 From: jsboige Date: Mon, 21 Sep 2026 10:16:01 +0200 Subject: [PATCH 4/4] fix(16471): fresh twin attestation for gametheory-8 after index race repair Neither prior entry attests the branch state (mine 0009: current python, stale C#; po-2025 0008: current C#, main's python). Append canonical --update entry attesting the merged final state (density python + main C#). check_twin_parity: 157 OK / 0 DRIFT / 0 NUMBERING-DRIFT test_twin_registry_integrity: 46 passed Co-Authored-By: Claude Sonnet 5 --- .../0010-2026-09-21-myia-po-2026-CoursIA.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 scripts/notebook_tools/twin_pairs.d/gametheory-8-combinatorialgames/0010-2026-09-21-myia-po-2026-CoursIA.yaml diff --git a/scripts/notebook_tools/twin_pairs.d/gametheory-8-combinatorialgames/0010-2026-09-21-myia-po-2026-CoursIA.yaml b/scripts/notebook_tools/twin_pairs.d/gametheory-8-combinatorialgames/0010-2026-09-21-myia-po-2026-CoursIA.yaml new file mode 100644 index 0000000000..90ab056c21 --- /dev/null +++ b/scripts/notebook_tools/twin_pairs.d/gametheory-8-combinatorialgames/0010-2026-09-21-myia-po-2026-CoursIA.yaml @@ -0,0 +1,6 @@ +date: '2026-09-21' +by: myia-po-2026:CoursIA +python_sha: 537a49b0b0a2680cadac17caf32c32d37b6c6a03 +csharp_sha: 10d07dbd15e15ac65c442c6165e417bcddaf15ca +content_python_sha: ff665ba30b564c336f8d7b8ac4d7967a08b5522f899066550987bb3aa96f32e3 +content_csharp_sha: 980e0230311ad62d97f5a6f37f35a62133414f1299f8135a937db50b5088459c