Skip to content

Commit c2aaeab

Browse files
authored
55 (#241)
This PR solves problem 55.
1 parent 8d3ea6b commit c2aaeab

File tree

1 file changed

+99
-3
lines changed

1 file changed

+99
-3
lines changed

HumanEvalLean/HumanEval55.lean

Lines changed: 99 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,103 @@
11
module
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

Comments
 (0)