NIM paper · interactive edition Interactive edition · paper, explanations and Lean proofs.

Theorem 4.4A NIM position is losing iff its nim-sum is zero; from a nonzero nim-sum there is a move to zero

Checked theorem Lean checks a formal statement corresponding to this claim.

1 Paper text

Theorem 4.4 (Classical NIM characterisation) A NIM position (x1,…,xh)(x_1,\dots,x_h) is losing for the player to move iff nim⁡(x1,…,xh)=0\operatorname{nim}(x_1,\dots,x_h)=0. Moreover, from any winning position (nim-sum ≠0\neq 0) there is a move to a losing position (nim-sum =0=0).

Generated from paper_jmlr.tex, lines 433–436.

2 Explain this

The statement. A position is lost for the player to move exactly when the nim-sum is zero. From any position with nonzero nim-sum there is a move that makes it zero.

Example. (3,5,6)(3,5,6) has nim-sum 00: whatever you do, the opponent can restore zero, and eventually you face the empty board. (3,4,6)(3,4,6) has nim-sum 11: reducing 33 to 22 makes it zero.

Why it matters. Optimal play is "always move to nim-sum zero". The rule is short and exact, yet it requires the XOR of all heaps, a global parity computation.

How to find the move. Let s≠0s\ne0 be the nim-sum and kk its highest set bit. Some heap xx has bit kk set; then x⊕s<xx\oplus s<x, and replacing xx by x⊕sx\oplus s makes the nim-sum 00.

3 How this is formalised

Semantics. Game.Win and Game.Lose are defined together, by induction, as the normal-play notions for the player to move: a position is winning if some move reaches a losing position; it is losing if every move reaches a winning position (so a terminal position is losing).

Checked statements.

The theorem is the classical one; Lean checks it in exactly the paper's form, for any number of heaps.

Coverage record
Paper anchorthm:nim-win (manuscript label)
Displayed asTheorem 4.4
ClaimA NIM position is losing iff its nim-sum is zero; from a nonzero nim-sum there is a move to zero
Coverage categoryChecked theorem
Statement sourcepaper_jmlr.tex lines 433–436; SHA-256 of the normalised block source b7a02420951e1b1e…
Lean declarations
Assumptions and domain

Finite normal-play NIM; heap sizes are natural numbers; any number of heaps.

Audited correspondence rowsthm:nim-win
Explanationsexplain/thm:nim-win, formal/thm:nim-win
Build evidencefresh isolated rebuild, audit report

4 Lean statement and source

Principal declarations

theorem Game.lose_iff

Module NimGame (lean/phase2/NimGame.lean, lines 108–115) · file SHA-256 23df6bb87ecfd344… Axioms reported by the fresh build: propext, Quot.sound

CLASSICAL CHARACTERISATION (paper Theorem nim-win).

Statement as elaborated and printed by Lean 4.26.0

∀ (p : List ℕ), NimAudit.Game.Lose p ↔ NimAudit.nimSum p = 0
Exact source text, lines 108–115
108/-- CLASSICAL CHARACTERISATION (paper Theorem nim-win). -/109theorem lose_iff (p : List Nat) : Lose p ↔ nimSum p = 0 := by110  constructor111  · intro hl112    by_cases h : nimSum p = 0113    · exact h114    · exact (not_win_and_lose p ((lose_of_zero_win_of_ne p).2 h) hl).elim115  · exact (lose_of_zero_win_of_ne p).1

Project declarations in the statement: Game.Lose, nimSum

Project declarations used by the proof or definition body

Game.Lose, Game.Win, Game.lose_of_zero_win_of_ne, Game.not_win_and_lose, nimSum

theorem Game.win_iff

Module NimGame (lean/phase2/NimGame.lean, lines 117–121) · file SHA-256 23df6bb87ecfd344… Axioms reported by the fresh build: propext, Quot.sound

Statement as elaborated and printed by Lean 4.26.0

∀ (p : List ℕ), NimAudit.Game.Win p ↔ NimAudit.nimSum p ≠ 0
Exact source text, lines 117–121
117theorem win_iff (p : List Nat) : Win p ↔ nimSum p ≠ 0 := by118  constructor119  · intro hw h120    exact not_win_and_lose p hw ((lose_of_zero_win_of_ne p).1 h)121  · exact (lose_of_zero_win_of_ne p).2

Project declarations in the statement: Game.Win, nimSum

Project declarations used by the proof or definition body

Game.Lose, Game.Win, Game.lose_of_zero_win_of_ne, Game.not_win_and_lose, nimSum

theorem Game.exists_move_to_zero

Module NimGame (lean/phase2/NimGame.lean, lines 80–84) · file SHA-256 23df6bb87ecfd344… Axioms reported by the fresh build: propext, Quot.sound

From a nonzero nim-sum there is a legal move to nim-sum zero (from NimRollout).

Statement as elaborated and printed by Lean 4.26.0

∀ {p : List ℕ}, NimAudit.nimSum p ≠ 0 → ∃ q, NimAudit.Game.Move p q ∧ NimAudit.nimSum q = 0
Exact source text, lines 80–84
80/-- From a nonzero nim-sum there is a legal move to nim-sum zero (from NimRollout). -/81theorem exists_move_to_zero {p : List Nat} (h : nimSum p ≠ 0) :82    ∃ q, Move p q ∧ nimSum q = 0 := by83  obtain ⟨pre, x, post, rfl, hlt, hz⟩ := exists_decreasing_heap p h84  exact ⟨_, ⟨pre, x, post, _, rfl, rfl, hlt⟩, hz⟩

Project declarations in the statement: Game.Move, nimSum

Project declarations used by the proof or definition body

Game.Move, Rollout.exists_decreasing_heap, nimSum

theorem Game.move_from_zero

Module NimGame (lean/phase2/NimGame.lean, lines 71–78) · file SHA-256 23df6bb87ecfd344… Axioms reported by the fresh build: propext, Quot.sound

Every legal move from a zero-nim-sum board reaches a nonzero nim-sum.

Statement as elaborated and printed by Lean 4.26.0

∀ {p q : List ℕ}, NimAudit.Game.Move p q → NimAudit.nimSum p = 0 → NimAudit.nimSum q ≠ 0
Exact source text, lines 71–78
71/-- Every legal move from a zero-nim-sum board reaches a nonzero nim-sum. -/72theorem move_from_zero {p q : List Nat} (hm : Move p q) (h0 : nimSum p = 0) :73    nimSum q ≠ 0 := by74  obtain ⟨pre, x, post, y, rfl, rfl, hlt⟩ := hm75  rw [nimSum_move, h0, Nat.zero_xor]76  intro h77  have := xor_eq_zero_imp h78  omega

Project declarations in the statement: Game.Move, nimSum

Project declarations used by the proof or definition body

Game.Move, Game.nimSum_move, Game.xor_eq_zero_imp, nimSum

Definitions these statements use

inductive Game.Win

Module NimGame (lean/phase2/NimGame.lean, lines 37–38) · file SHA-256 23df6bb87ecfd344…

Statement as elaborated and printed by Lean 4.26.0

List ℕ → Prop
Exact source text, lines 37–38
37inductive Win : List Nat → Prop38  | intro (p q : List Nat) : Move p q → Lose q → Win p

Project declarations in the statement: none

Project declarations used by the proof or definition body

Game.Lose, Game.Move

inductive Game.Lose

Module NimGame (lean/phase2/NimGame.lean, lines 39–40) · file SHA-256 23df6bb87ecfd344…

Statement as elaborated and printed by Lean 4.26.0

List ℕ → Prop
Exact source text, lines 39–40
39inductive Lose : List Nat → Prop40  | intro (p : List Nat) : (∀ q, Move p q → Win q) → Lose p

Project declarations in the statement: none

Project declarations used by the proof or definition body

Game.Move, Game.Win

def nimSum

Module NimCore (lean/NimCore.lean, lines 7–9) · file SHA-256 b07db6c505210d5a…

Statement as elaborated and printed by Lean 4.26.0

List ℕ → ℕ
Exact source text, lines 7–9
7def nimSum : List Nat → Nat8  | [] => 09  | h :: t => h ^^^ nimSum t

Project declarations in the statement: none

Project declarations used by the proof or definition body

none

def Game.Move

Module NimGame (lean/phase2/NimGame.lean, lines 24–26) · file SHA-256 23df6bb87ecfd344…

An ordinary legal Nim move: exactly one heap strictly decreases.

Statement as elaborated and printed by Lean 4.26.0

List ℕ → List ℕ → Prop
Exact source text, lines 24–26
24/-- An ordinary legal Nim move: exactly one heap strictly decreases. -/25def Move (p q : List Nat) : Prop :=26  ∃ pre x post y, p = pre ++ x :: post ∧ q = pre ++ y :: post ∧ y < x

Project declarations in the statement: none

Project declarations used by the proof or definition body

none

Full modules

ModuleFileLinesImports
NimCorelean/NimCore.lean139Std
NimGamelean/phase2/NimGame.lean634NimRollout

Build evidence: fresh isolated rebuild of all 38 bundled modules with Lean (version 4.26.0, started 2026-10-10T15:21:56Z, finished 2026-10-10T15:27:00Z: 38/38 modules compiled, 1588 axiom reports, no errors. See Build for the commands and the independent audit of 2026-10-10 (dated evidence).