11module
22
3- def fib : Unit :=
4- ()
3+ public import Std
4+ open Std
5+
6+ -- public section -- #12482
7+
8+ /-!
9+ ## Implementation
10+
11+ Iterator-based Fibonacci implementation.
12+
13+ The Fibonacci sequence is computed using an iterator that maintains a state `(fₙ, fₙ₊₁)`.
14+ Each step transforms the state to `(fₙ₊₁, fₙ + fₙ₊₁)`, starting from `(0, 1)`.
15+ -/
16+
17+ @[inline]
18+ def fibonacciIterator.step : Nat × Nat → Nat × Nat
19+ | (x₁, x₂) => (x₂, x₁ + x₂)
20+
21+ @[inline]
22+ def fibonacciIterator.states := Iter.repeat (init := (0 , 1 )) fibonacciIterator.step
23+
24+ def fibonacciIterator := fibonacciIterator.states.map (fun (current, _) => current)
25+
26+ def fib (n : Nat) : Nat :=
27+ fibonacciIterator.atIdxSlow? n |>.get!
28+
29+ /-! ## Tests -/
30+
31+ example : fib 10 = 55 := by native_decide
32+ example : fib 1 = 1 := by native_decide
33+ example : fib 8 = 21 := by native_decide
34+ example : fib 11 = 89 := by native_decide
35+ example : fib 12 = 144 := by native_decide
36+
37+ /-! ## Missing API -/
38+
39+ theorem Nat.eq_add_of_toList_rcc_eq_append_cons {a b : Nat} {pref cur suff}
40+ (h : (a...=b).toList = pref ++ cur :: suff) :
41+ cur = a + pref.length := by
42+ have := Rcc.eq_succMany?_of_toList_eq_append_cons h
43+ grind [PRange.Nat.succMany?_eq]
44+
45+ @ [grind =]
46+ theorem Std.Iter.atIdxSlow?_map [Iterator α Id β] [Iterators.Productive α Id]
47+ {it : Iter (α := α) β} {f : β → γ} :
48+ (it.map f).atIdxSlow? n = (it.atIdxSlow? n).map f := by
49+ induction n, it using atIdxSlow?.induct_unfolding
50+ all_goals
51+ rw [atIdxSlow?_eq_match, step_map]
52+ simp [*]
53+
54+ attribute [grind =] Iter.atIdxSlow?_repeat
55+
56+ theorem Std.Iter.length_take_repeat {f : α → α} {init} :
57+ (Iter.repeat (init := init) f |>.take n).length = n := by
58+ induction n generalizing init <;>
59+ grind [=_ Iter.length_toList_eq_length, Iter.toList_take_zero, Iter.toList_take_repeat_succ]
60+
61+ theorem Std.Iter.toList_take_map [Iterator α Id β] [Iterators.Productive α Id]
62+ {it : Iter (α := α) β} {f : β → γ} :
63+ (it.map f |>.take n).toList = (it.take n).toList.map f := by
64+ apply List.ext_getElem?
65+ grind [Iter.getElem?_toList_eq_atIdxSlow?, Iter.atIdxSlow?_take]
66+
67+ attribute [grind =] Iter.atIdxSlow?_take Iter.toList_take_map Iter.length_map
68+ Iter.length_toList_eq_length Iter.length_take_repeat
69+
70+ /-! ## Verification of `tri` -/
71+
72+ def fibState (n : Nat) :=
73+ (fibonacciIterator.states.atIdxSlow? n).get (by grind [fibonacciIterator.states])
74+
75+ theorem fib_eq_fst_fibState :
76+ fib n = (fibState n).1 := by
77+ grind [fib, fibState, fibonacciIterator, fibonacciIterator.states]
78+
79+ theorem fibState_spec :
80+ fibState n =
81+ if n = 0 then
82+ (0 , 1 )
83+ else if n = 1 then
84+ (1 , 1 )
85+ else
86+ (fib (n - 2 ) + fib (n - 1 ), fib (n + 1 )) := by
87+ simp only [fib, fibState, fibonacciIterator, fibonacciIterator.states]
88+ induction n using Nat.strongRecOn with | ind n ih
89+ match n with
90+ | 0 | 1 | n + 2 => grind [Nat.repeat, fibonacciIterator.step]
91+
92+ theorem fib_spec :
93+ fib n =
94+ if n = 0 then
95+ 0
96+ else if n = 1 then
97+ 1
98+ else
99+ fib (n - 2 ) + fib (n - 1 ) := by
100+ grind [fibState_spec, fib_eq_fst_fibState]
5101
6102/-!
7103## Prompt
@@ -46,4 +142,4 @@ def check(candidate):
46142 assert candidate(12) == 144
47143
48144```
49- -/
145+ -/
0 commit comments