Skip to content

Commit 3d77f23

Browse files
authored
HumanEval150 using iterators (#195)
* signature * solution * use takeWhile * remove obsolete lemmas * rename isPrime_iff * extract lemma * remarks * remove other lemma
1 parent 2ec346e commit 3d77f23

File tree

1 file changed

+127
-6
lines changed

1 file changed

+127
-6
lines changed

HumanEvalLean/HumanEval150.lean

Lines changed: 127 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,140 @@
1-
def x_or_y : Unit :=
2-
()
1+
import Std.Data.Iterators
2+
import Init.Notation
3+
import Std.Tactic.Do
4+
5+
open Std.Iterators
6+
7+
/-!
8+
## Implementation
9+
-/
10+
11+
def isPrime (n : Nat) : Bool :=
12+
let divisors := (2...<n).iter.takeWhile (fun i => i * i ≤ n) |>.filter (· ∣ n)
13+
2 ≤ n ∧ divisors.fold (init := 0) (fun count _ => count + 1) = 0
14+
15+
def x_or_y (n : Int) (x y : α) : α := Id.run do
16+
let some n := n.toNat? | return y
17+
if isPrime n then
18+
return x
19+
else
20+
return y
21+
22+
/-- info: [2, 3, 5, 7, 11, 13, 17, 19] -/
23+
#guard_msgs in
24+
#eval (1...20).iter.filter isPrime |>.toList
25+
26+
/-!
27+
## Tests
28+
-/
29+
30+
example : x_or_y 15 8 5 = 5 := by native_decide
31+
example : x_or_y 3 33 5212 = 33 := by native_decide
32+
example : x_or_y 1259 3 52 = 3 := by native_decide
33+
example : x_or_y 7919 (-1) 12 = -1 := by native_decide
34+
example : x_or_y 3609 1245 583 = 583 := by native_decide
35+
example : x_or_y 91 56 129 = 129 := by native_decide
36+
example : x_or_y 6 34 1234 = 1234 := by native_decide
37+
example : x_or_y 1 2 0 = 0 := by native_decide
38+
example : x_or_y 2 2 0 = 2 := by native_decide
39+
40+
/-!
41+
## Verification
42+
-/
43+
44+
def IsPrime (n : Nat) : Prop :=
45+
2 ≤ n ∧ ∀ d : Nat, d ∣ n → d = 1 ∨ d = n
46+
47+
theorem isPrime_eq_true_iff {n : Nat} :
48+
isPrime n = true2 ≤ n ∧
49+
(List.filter (· ∣ n) (List.takeWhile (fun i => i * i ≤ n) (2...n).toList)).length = 0 := by
50+
simp [isPrime, ← Iter.foldl_toList]
51+
52+
theorem isPrime_iff_mul_self {n : Nat} :
53+
IsPrime n ↔ (2 ≤ n ∧ ∀ (a : Nat), 2 ≤ a ∧ a < n → a ∣ n → n < a * a) := by
54+
rw [IsPrime]
55+
by_cases hn : 2 ≤ n; rotate_left; grind
56+
apply Iff.intro
57+
· grind
58+
· rintro ⟨hn, h⟩
59+
refine ⟨hn, fun d hd => ?_⟩
60+
· have : 0 < d := Nat.pos_of_dvd_of_pos hd (by grind)
61+
have : d ≤ n := Nat.le_of_dvd (by grind) hd
62+
false_or_by_contra
63+
by_cases hsq : d * d ≤ n
64+
· specialize h d
65+
grind
66+
· replace h := h (n / d) ?_ ?_; rotate_left
67+
· have : d ≥ 2 := by grind
68+
refine ⟨?_, Nat.div_lt_self (n := n) (k := d) (by grind) (by grind)⟩
69+
false_or_by_contra; rename_i hc
70+
have : n / d * d ≤ 1 * d := Nat.mul_le_mul_right d (Nat.le_of_lt_succ (Nat.lt_of_not_ge hc))
71+
grind [Nat.dvd_iff_div_mul_eq]
72+
· exact Nat.div_dvd_of_dvd hd
73+
simp only [Nat.not_le] at hsq
74+
have := Nat.mul_lt_mul_of_lt_of_lt h hsq
75+
replace : n * n < ((n / d) * d) * ((n / d) * d) := by grind
76+
rw [Nat.dvd_iff_div_mul_eq] at hd
77+
grind
78+
79+
theorem ClosedOpen.toList_eq_nil_of_le {m n : Nat} (h : n ≤ m) :
80+
(m...n).toList = [] := by
81+
simp [Std.PRange.toList_eq_nil_iff, Std.PRange.BoundedUpwardEnumerable.init?,
82+
Std.PRange.SupportsUpperBound.IsSatisfied, show n ≤ m by grind]
83+
84+
theorem List.takeWhile_eq_filter {P : α → Bool} {xs : List α}
85+
(h : xs.Pairwise (fun x y => P y → P x)) :
86+
xs.takeWhile P = xs.filter P := by
87+
induction xs with
88+
| nil => simp
89+
| cons x xs ih =>
90+
simp only [takeWhile_cons, filter_cons]
91+
simp only [pairwise_cons] at h
92+
split
93+
· simp [*]
94+
· simpa [*] using h
95+
96+
theorem isPrime_eq_true_iff_isPrime {n : Nat} :
97+
isPrime n ↔ IsPrime n := by
98+
simp only [isPrime_eq_true_iff]
99+
by_cases hn : 2 ≤ n; rotate_left
100+
· rw [ClosedOpen.toList_eq_nil_of_le (by grind)]
101+
grind [IsPrime]
102+
rw [List.takeWhile_eq_filter]; rotate_left
103+
· apply Std.PRange.pairwise_toList_le.imp
104+
intro a b hab hb
105+
have := Nat.mul_self_le_mul_self hab
106+
grind
107+
simp [Std.PRange.mem_toList_iff_mem, Std.PRange.mem_iff_isSatisfied,
108+
Std.PRange.SupportsLowerBound.IsSatisfied, Std.PRange.SupportsUpperBound.IsSatisfied,
109+
isPrime_iff_mul_self]
110+
111+
open Classical in
112+
theorem x_or_y_of_isPrime {n : Int} {x y : α} :
113+
x_or_y n x y = if n ≥ 0 ∧ IsPrime n.toNat then x else y := by
114+
generalize hwp : x_or_y n x y = w
115+
apply Std.Do.Id.of_wp_run_eq hwp
116+
mvcgen
117+
· grind [isPrime_eq_true_iff_isPrime, Int.mem_toNat?]
118+
· grind [isPrime_eq_true_iff_isPrime, Int.mem_toNat?]
119+
· suffices n < 0 by grind
120+
rename_i _ h₁ h₂
121+
specialize h₁ n.toNat
122+
cases h₂
123+
grind [Int.mem_toNat?]
3124

4125
/-!
5126
## Prompt
6127
7128
```python3
8129
9130
def x_or_y(n, x, y):
10-
"""A simple program which should return the value of x if n is
131+
"""A simple program which should return the value of x if n is
11132
a prime number and should return the value of y otherwise.
12133
13134
Examples:
14135
for x_or_y(7, 34, 12) == 34
15136
for x_or_y(15, 8, 5) == 5
16-
137+
17138
"""
18139
```
19140
@@ -44,11 +165,11 @@ def check(candidate):
44165
assert candidate(3609, 1245, 583) == 583
45166
assert candidate(91, 56, 129) == 129
46167
assert candidate(6, 34, 1234) == 1234
47-
168+
48169
49170
# Check some edge cases that are easy to work out by hand.
50171
assert candidate(1, 2, 0) == 0
51172
assert candidate(2, 2, 0) == 2
52173
53174
```
54-
-/
175+
-/

0 commit comments

Comments
 (0)