1-- The derangement numbers 1, 0, 1, 2, 9, 44, …: the recurrence2-- d(n + 2) = (n + 1)(d(n + 1) + d(n)), the one-step recurrences3-- d(2n + 1) + 1 = (2n + 1) d(2n) and d(2n + 2) = (2n + 2) d(2n + 1) + 1,4-- positivity, monotonicity, and the comparison with n!5-- Part of Cumulus, the Grace17 mathematics library.6-- Copyright (c) 2026 Grant Passmore.7-- Released under the Apache License 2.0. See LICENSE in the repository root.8-- Authors: Grant Passmore910module Grace.Cumulus.Combinatorics.Derangements11import FallingBounds1213-- derangementAux(n, i, a, b) is the term n places after index i of a14-- sequence t with t(i) = a, t(i + 1) = b, and15-- t(k + 2) = (k + 1)(t(k + 1) + t(k)).16def derangementAux (n i a b : Nat) →Nat17| zero, i, a, b => a18| succ(k), i, a, b => derangementAux(k, i +1, b, (i +1) * (a + b))19descends n2021def derangement (n : Nat) : Nat:= derangementAux(n, 0, 1, 0)2223theorem derangementAux.zero (i a b : Nat)24shows derangementAux(0, i, a, b) = a25proof26simp [derangementAux]2728theorem derangementAux.succ (k i a b : Nat)29shows derangementAux(k +1, i, a, b) =30 derangementAux(k, i +1, b, (i +1) * (a + b))31proof32have one : k +1= succ(k) := add.right_one with*33rw one34simp [derangementAux]3536theorem derangementAux.one (i a b : Nat)37shows derangementAux(1, i, a, b) = b38proof39simp [derangementAux]4041theorem derangementAux.two (i a b : Nat)42shows derangementAux(2, i, a, b) = (i +1) * (a + b)43proof44simp [derangementAux]4546theorem derangementAux.closed (n : Nat)47shows∀ i, Nat(i) →∀ a, Nat(a) →∀ b, Nat(b) →48Nat(derangementAux(n, i, a, b))49proof50induction n51| zero =>52intros i iNat a aNat b bNat53rw derangementAux.zero54exact aNat55| k +1using ih =>56intros i iNat a aNat b bNat57rw derangementAux.succ58have nextNat : Nat(i +1) bytypecheck59have productNat : Nat((i +1) * (a + b)) bytypecheck60exact ih with i +1, nextNat, b, bNat, (i +1) * (a + b), productNat6162-- Every such sequence obeys the derangement recurrence.63theorem derangementAux.shift (n : Nat)64shows∀ i, Nat(i) →∀ a, Nat(a) →∀ b, Nat(b) →65 derangementAux(n +2, i, a, b) =66 (i + n +1) * (derangementAux(n +1, i, a, b) + derangementAux(n, i, a, b))67proof68induction n69| zero =>70intros i iNat a aNat b bNat71have two : 0+2=2bycompute72have one : 0+1=1bycompute73rw [two, one, derangementAux.two, derangementAux.one, derangementAux.zero]74have shape : i +0+1= i +1byring75rw shape76ring77| k +1using ih =>78intros i iNat a aNat b bNat79have shape : k +1+2= (k +2) +1byring80have shape2 : k +1+1= k +2byring81rw [shape, shape2]82have top := derangementAux.succ at k +2, i, a, b83have middle := derangementAux.succ at k +1, i, a, b84have last := derangementAux.succ at k, i, a, b85rw shape2 at middle86rw [top, middle, last]87have iNat1 : Nat(i +1) bytypecheck88have cNat : Nat((i +1) * (a + b)) bytypecheck89have inner := ih with i +1, iNat1, b, bNat, (i +1) * (a + b), cNat90rw inner91have aux1 := derangementAux.closed at k +192have bNat1 := aux1 with i +1, iNat1, b, bNat, (i +1) * (a + b), cNat93have aux0 := derangementAux.closed at k94have bNat0 := aux0 with i +1, iNat1, b, bNat, (i +1) * (a + b), cNat95ring9697theorem derangement.zero98shows derangement(0) =199proof100compute101102theorem derangement.one103shows derangement(1) =0104proof105compute106107theorem derangement.two108shows derangement(2) =1109proof110compute111112theorem derangement.three113shows derangement(3) =2114proof115compute116117theorem derangement.four118shows derangement(4) =9119proof120compute121122theorem derangement.five123shows derangement(5) =44124proof125compute126127theorem derangement.natural (n : Nat)128showsNat(derangement(n))129proof130unfold derangement131have zeroNat : Nat(0) bytypecheck132have oneNat : Nat(1) bytypecheck133exact derangementAux.closed at n with0, zeroNat, 1, oneNat, 0, zeroNat134135theorem derangement.recurrence (n : Nat)136shows derangement(n +2) = (n +1) * (derangement(n +1) + derangement(n))137proof138unfold derangement139have zeroNat : Nat(0) bytypecheck140have oneNat : Nat(1) bytypecheck141have shift := derangementAux.shift at n with0, zeroNat, 1, oneNat, 0, zeroNat142have shape : 0+ n +1= n +1byring143rw shape at shift144exact shift145146-- The one-step recurrences d(n + 1) = (n + 1) d(n) + (−1)^(n + 1), split by147-- the parity of n so that both sides stay natural.148theorem derangement.alternating_pair (n : Nat)149shows derangement(2* n +1) +1= (2* n +1) * derangement(2* n) ∧150 derangement(2* n +2) = (2* n +2) * derangement(2* n +1) +1151proof152induction n153| zero =>154constructor155 . compute156 . compute157| k +1using ih =>158have odd := ih.left159have even := ih.right160have shapeA : 2* (k +1) +1=2* k +3byring161have shapeB : 2* (k +1) =2* k +2byring162have shapeC : 2* (k +1) +2=2* k +4byring163rw [shapeA, shapeC, shapeB]164have natA := derangement.natural at2* k165have natB := derangement.natural at2* k +1166have natC := derangement.natural at2* k +2167have natD := derangement.natural at2* k +3168have stepOdd : derangement(2* k +3) +1=169 (2* k +3) * derangement(2* k +2)170have step := derangement.recurrence at2* k +1171have three : 2* k +1+2=2* k +3byring172have two : 2* k +1+1=2* k +2byring173rw [three, two] at step174rw [step, even]175ring176constructor177 . exact stepOdd178 . have step := derangement.recurrence at2* k +2179have four : 2* k +2+2=2* k +4byring180have three : 2* k +2+1=2* k +3byring181rw [four, three] at step182rw step183have reversed : (2* k +3) * derangement(2* k +2) =184 derangement(2* k +3) +1185 symm186exact stepOdd187ring [reversed]188189theorem derangement.odd_succ (n : Nat)190shows derangement(2* n +1) +1= (2* n +1) * derangement(2* n)191proof192have pair := derangement.alternating_pair at n193exact pair.left194195theorem derangement.even_succ (n : Nat)196shows derangement(2* n +2) = (2* n +2) * derangement(2* n +1) +1197proof198have pair := derangement.alternating_pair at n199exact pair.right200201-- d(n + 1) ≤ (n + 1) d(n) + 1 and (n + 1) d(n) ≤ d(n + 1) + 1 for every n.202theorem derangement.succ_le (n : Nat)203shows derangement(n +1) ≤ (n +1) * derangement(n) +1204proof205have alternatives := parity.exhaustive at n206cases alternatives with even | odd207 . have iff := Even.iff_two_mul at n208obtain⟨k, kNat, shape⟩:= iff.forward with even209rw shape210have step := derangement.odd_succ at k211have natA := derangement.natural at2* k212have natB := derangement.natural at2* k +1213arith214 . have iff := Odd.iff_two_mul_add_one at n215obtain⟨k, kNat, shape⟩:= iff.forward with odd216rw shape217have step := derangement.even_succ at k218have two : 2* k +1+1=2* k +2byring219rw two220have natB := derangement.natural at2* k +1221have natC := derangement.natural at2* k +2222arith223224theorem derangement.succ_ge (n : Nat)225shows (n +1) * derangement(n) ≤ derangement(n +1) +1226proof227have alternatives := parity.exhaustive at n228cases alternatives with even | odd229 . have iff := Even.iff_two_mul at n230obtain⟨k, kNat, shape⟩:= iff.forward with even231rw shape232have step := derangement.odd_succ at k233have natA := derangement.natural at2* k234have natB := derangement.natural at2* k +1235arith236 . have iff := Odd.iff_two_mul_add_one at n237obtain⟨k, kNat, shape⟩:= iff.forward with odd238rw shape239have step := derangement.even_succ at k240have two : 2* k +1+1=2* k +2byring241rw two242have natB := derangement.natural at2* k +1243have natC := derangement.natural at2* k +2244arith245246theorem derangement.positive (n : Nat)247shows0 < derangement(n +2)248proof249induction n250| zero =>251have two : 0+2=2bycompute252rw [two, derangement.two]253arith254| k +1using ih =>255rw derangement.recurrence256have shape : k +1+1= k +2byring257rw shape258have natA := derangement.natural at k +1259have natC := derangement.natural at k +2260have coefficient : 0 < k +2byarith261have sum : 0 < derangement(k +2) + derangement(k +1) byarith262exact Less.mul_positive with coefficient, sum263264theorem derangement.ge_one (n : Nat)265shows1≤ derangement(n +2)266proof267have positive := derangement.positive at n268have natural := derangement.natural at n +2269arith270271theorem derangement.monotone (n : Nat)272shows derangement(n +2) ≤ derangement(n +3)273proof274have step := derangement.recurrence at n +1275have shape : n +1+2= n +3byring276have shape2 : n +1+1= n +2byring277rw [shape, shape2] at step278rw step279have natA := derangement.natural at n +1280have natB := derangement.natural at n +2281have expand : (n +2) * (derangement(n +2) + derangement(n +1)) =282 derangement(n +2) + (n +1) * derangement(n +2) +283 (n +2) * derangement(n +1)284ring285rw expand286have productA : Nat((n +1) * derangement(n +2)) bytypecheck287have productB : Nat((n +2) * derangement(n +1)) bytypecheck288arith289290-- d(n) ≤ n!, proved together with its successor.291theorem derangement.le_factorial_pair (n : Nat)292shows derangement(n) ≤ n! ∧ derangement(n +1) ≤ (n +1)!293proof294induction n295| zero =>296have one : 0+1=1bycompute297have zeroFactorial : 0! =1bycompute298rw [one, derangement.zero, derangement.one, zeroFactorial, factorial.one]299constructor300 . arith301 . arith302| k +1using ih =>303have first := ih.left304have second := ih.right305constructor306 . exact second307 . have shape : k +1+1= k +2byring308rw [shape, derangement.recurrence]309have natA := derangement.natural at k310have natB := derangement.natural at k +1311have closedK := factorial.closed at k312have closedK1 := factorial.closed at k +1313have sum := LessEqual.add with second, first314have scaled := LessEqual.mul_left at derangement(k +1) + derangement(k),315 (k +1)! + k!, k +1with sum316have expand : (k +2)! = (k +1) * ((k +1)! + k!)317have shape2 : k +2= k +1+1byring318rw [shape2, factorial.succ, factorial.succ]319ring320rw expand321exact scaled322323theorem derangement.le_factorial (n : Nat)324shows derangement(n) ≤ n!325proof326have pair := derangement.le_factorial_pair at n327exact pair.left328329-- d(n + 1) < (n + 1)!, proved together with its successor.330theorem derangement.lt_factorial_pair (n : Nat)331shows derangement(n +1) < (n +1)! ∧ derangement(n +2) < (n +2)!332proof333induction n334| zero =>335have one : 0+1=1bycompute336have two : 0+2=2bycompute337rw [one, two, derangement.one, derangement.two]338rw [factorial.one, factorial.two]339constructor340 . arith341 . arith342| k +1using ih =>343have first := ih.left344have second := ih.right345have shape : k +1+1= k +2byring346rw shape347constructor348 . exact second349 . have step := derangement.recurrence at k +1350have shape2 : k +1+2= k +3byring351rw [shape2, shape] at step352rw [shape2, step]353have natA := derangement.natural at k +1354have natB := derangement.natural at k +2355have closedK1 := factorial.closed at k +1356have closedK2 := factorial.closed at k +2357have firstLe := derangement.le_factorial at k +1358have sum := Less.add_LessEqual with second, firstLe359have coefficient : 0 < k +2byarith360have nonzero := Less.ne_zero_of_positive with coefficient361have scaled := Less.mul_left at derangement(k +2) + derangement(k +1),362 (k +2)! + (k +1)!, k +2with nonzero, sum363have expand : (k +3)! = (k +2) * ((k +2)! + (k +1)!)364have shape3 : k +3= k +2+1byring365rw [shape3, factorial.succ]366have inner := factorial.succ at k +1367rw shape at inner368rw inner369ring370rw expand371exact scaled372373theorem derangement.lt_factorial (n : Nat)374shows derangement(n +1) < (n +1)!375proof376have pair := derangement.lt_factorial_pair at n377exact pair.left378