1- def special_factorial : Unit :=
2- ()
1+ -- from Mathlib
2+ def Nat.factorial : Nat → Nat
3+ | 0 => 1
4+ | .succ n => Nat.succ n * factorial n
5+
6+ notation :10000 n "!" => Nat.factorial n
7+
8+ @[simp] theorem Nat.factorial_zero : 0 ! = 1 :=
9+ rfl
10+
11+ theorem Nat.factorial_succ (n : Nat) : (n + 1 )! = (n + 1 ) * n ! :=
12+ rfl
13+
14+ def Nat.brazilianFactorial : Nat → Nat
15+ | .zero => 1
16+ | .succ n => (Nat.succ n)! * brazilianFactorial n
17+
18+ @[simp] theorem Nat.brazilianFactorial_zero : brazilianFactorial 0 = 1 :=
19+ rfl
20+
21+ theorem Nat.brazilianFactorial_succ (n : Nat) : brazilianFactorial (n + 1 ) = (n + 1 )! * (brazilianFactorial n) :=
22+ rfl
23+
24+ def special_factorial (n : Nat) : Nat :=
25+ special_factorial.go n 1 1 0
26+ where
27+ go (n fact brazilFact curr : Nat) : Nat :=
28+ if _h: curr >= n
29+ then brazilFact
30+ else
31+ let fact' := (curr + 1 ) * fact
32+ let brazilFact' := fact' * brazilFact
33+ special_factorial.go n fact' brazilFact' (Nat.succ curr)
34+ termination_by n - curr
35+
36+ theorem special_factorial_func_correct {n : Nat} :
37+ special_factorial n = n.brazilianFactorial := by
38+ simp [special_factorial]
39+ suffices ∀ (curr fact brazilFact : Nat), fact = curr ! → brazilFact = curr.brazilianFactorial →
40+ curr ≤ n → special_factorial.go n fact brazilFact curr = n.brazilianFactorial by
41+ apply this
42+ · simp [Nat.factorial]
43+ · simp [Nat.brazilianFactorial]
44+ · simp
45+ intro curr fact brazil_fact h₁ h₂ h₃
46+ fun_induction special_factorial.go with
47+ | case1 fact brazil_fact curr h =>
48+ rw [h₂]
49+ unfold special_factorial.go
50+ simp [h]
51+ have : curr = n := by omega
52+ rw [this]
53+ | case2 fact brazilFact curr h fact' brazilFact' ih =>
54+ simp only [ge_iff_le, Nat.not_le] at h
55+ simp only [h₁, Nat.succ_eq_add_one, Nat.factorial_succ, h₂, Nat.brazilianFactorial_succ,
56+ Nat.succ_le_of_lt h, forall_const, fact', brazilFact'] at ih
57+ have : ¬ curr >= n := by omega
58+ unfold special_factorial.go
59+ simp [this, h₁, h₂, ih]
60+
61+ theorem test1 : special_factorial 4 = 288 := by native_decide
62+ theorem test2 : special_factorial 5 = 34560 := by native_decide
63+ theorem test3 : special_factorial 7 = 125411328000 := by native_decide
64+ theorem test4 : special_factorial 1 = 1 := by native_decide
365
466/-!
567## Prompt
@@ -45,4 +107,4 @@ def check(candidate):
45107 assert candidate(1) == 1, "Test 1"
46108
47109```
48- -/
110+ -/
0 commit comments