11module
22
3- def fib4 : Unit :=
4- ()
3+ public import Std
4+ open Std Std.Do
5+
6+ set_option mvcgen.warning false
7+
8+ /-! ## Implementation -/
9+
10+ def fib4 (n : Nat) : Nat := Id.run do
11+ let mut lastFour : Vector Nat 4 := #v[0 , 0 , 2 , 0 ]
12+ for i in *...(n - 3 ) do
13+ lastFour := lastFour.set (i % 4 ) (lastFour[0 ] + lastFour[1 ] + lastFour[2 ] + lastFour[3 ])
14+ return lastFour[n % 4 ]
15+
16+ /-! ## Tests -/
17+
18+ example : fib4 5 = 4 := by native_decide
19+ example : fib4 8 = 28 := by native_decide
20+ example : fib4 10 = 104 := by native_decide
21+ example : fib4 12 = 386 := by native_decide
22+
23+ /-! ## Missing API -/
24+
25+ theorem eq_getElem_append_cons {pref suff : List α} {cur : α} :
26+ (pref ++ cur :: suff)[pref.length]? = cur := by
27+ simp
28+
29+ grind_pattern eq_getElem_append_cons => pref ++ cur :: suff
30+ attribute [grind =] Nat.getElem?_toList_rio
31+ attribute [grind =] Nat.length_toList_rio
32+
33+ /-! ## Verification -/
34+
35+ def fib4Reference : Nat → Nat
36+ | 0 => 0
37+ | 1 => 0
38+ | 2 => 2
39+ | 3 => 0
40+ | (k + 4 ) =>
41+ fib4Reference (k + 4 - 1 ) + fib4Reference (k + 4 - 2 ) + fib4Reference (k + 4 - 3 ) + fib4Reference (k + 4 - 4 )
42+
43+ theorem sum_mod_eq_sum {vec : Vector Nat 4 } :
44+ ∀ i, vec[i % 4 ] + vec[(i + 1 ) % 4 ] + vec[(i + 2 ) % 4 ] + vec[(i + 3 ) % 4 ] =
45+ vec[0 ] + vec[1 ] + vec[2 ] + vec[3 ]
46+ | 0 | 1 | 2 | 3 => by grind
47+ | i + 4 => by
48+ have := sum_mod_eq_sum (vec := vec) (i := i)
49+ have : ∀ j, j < 4 → (i + 4 + j) % 4 = (i + j) % 4 := by grind
50+ simp only [Nat.add_mod_right, Nat.reduceLT, this, Nat.lt_add_one]
51+ grind
52+
53+ theorem fib4_eq_fib4Reference :
54+ fib4 n = fib4Reference n := by
55+ generalize hwp : fib4 n = wp
56+ apply Id.of_wp_run_eq hwp
57+ mvcgen
58+ invariants
59+ · ⇓⟨cur, lastFour⟩ => ⌜∀ i, i < 4 → lastFour[(cur.pos + i) % 4 ] = fib4Reference (cur.pos + i)⌝
60+ case vc1 pref cur suff heq _ _ h =>
61+ simp_all only [List.Cursor.pos_mk, List.length_append, List.length_cons, List.length_nil]
62+ intro i hi
63+ by_cases i = 3
64+ · rename_i hi'
65+ rw [hi', fib4Reference]
66+ simp only [show (pref.length + 1 + 3 ) % 4 = cur % 4 by grind]
67+ grind [sum_mod_eq_sum, h 0 (by grind), h 1 (by grind), h 2 (by grind), h 3 (by grind),
68+ Vector.getElem_set_self]
69+ · specialize h (i + 1 ) (by grind)
70+ grind
71+ case vc2 =>
72+ simp only [List.Cursor.pos_mk, Vector.getElem_eq_iff]
73+ decide
74+ case vc3 h =>
75+ by_cases hn : n < 4
76+ · grind
77+ · specialize h 3
78+ grind
579
680/-!
781## Prompt
@@ -55,4 +129,4 @@ def check(candidate):
55129 assert candidate(12) == 386
56130
57131```
58- -/
132+ -/
0 commit comments