forked from leanprover/human-eval-lean
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathHumanEval25.lean
More file actions
211 lines (174 loc) · 6.56 KB
/
HumanEval25.lean
File metadata and controls
211 lines (174 loc) · 6.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
module
public import Std
public import HumanEvalLean.Common.IsPrime
public section
/-! ## Implementation -/
def factorizeAssumingFactorsGE (x : Nat) (bound : Nat) (acc : Array Nat) (h : 2 ≤ bound := by grind) : Array Nat :=
if x < bound * bound then
if 1 < x then acc.push x else acc
else if x % bound = 0 then
factorizeAssumingFactorsGE (x / bound) bound (acc.push bound)
else
factorizeAssumingFactorsGE x (bound + 1) acc
termination_by x + 1 - bound
decreasing_by
· have : bound ≤ bound * bound := Nat.le_mul_self bound
have : x / bound < x := Nat.div_lt_self (by grind) (by grind)
grind
· have : bound ≤ bound * bound := Nat.le_mul_self bound
grind [Nat.mod_self]
def factorize (x : Nat) : Array Nat :=
factorizeAssumingFactorsGE x 2 #[]
/-! ## Tests -/
example : factorize 2 = #[2] := by cbv
example : factorize 4 = #[2, 2] := by cbv
example : factorize 8 = #[2, 2, 2] := by cbv
example : factorize 25 = #[5, 5] := by cbv
example : factorize 70 = #[2, 5, 7] := by cbv
example : factorize 57 = #[3, 19] := by cbv
example : factorize 3249 = #[3, 3, 19, 19] := by cbv
example : factorize 185193 = #[3, 3, 3, 19, 19, 19] := by cbv
example : factorize 20577 = #[3, 19, 19, 19] := by cbv
example : factorize 18 = #[2, 3, 3] := by cbv
/-! ## Verification -/
/-! ### Helper Predicates -/
def AllDivisorsGE (x bound : Nat) : Prop :=
∀ d, 2 ≤ d → d ∣ x → bound ≤ d
def IsSmallestDivisor (d x : Nat) : Prop :=
2 ≤ d ∧ d ∣ x ∧ AllDivisorsGE x d
/--
The smallest divisor (besides `1`) of a number `x` is a prime number.
-/
@[grind →]
theorem IsSmallestDivisor.isPrime (h : IsSmallestDivisor d x) : IsPrime d := by
simp only [IsPrime, IsSmallestDivisor] at h ⊢
refine ⟨h.1, ?_⟩
intro d' hd'
have : d' ∣ x := by grind [Nat.dvd_trans]
have : d' ≤ d := Nat.le_of_dvd (by grind) (by grind)
by_cases 2 ≤ d'
· grind [AllDivisorsGE]
· grind [cases Nat, Nat.zero_dvd]
@[grind .]
theorem AllDivisorsGE.div (h : AllDivisorsGE x bound) (hd : d ∣ x) :
AllDivisorsGE (x / d) bound := by
simp only [AllDivisorsGE] at h ⊢
grind [Nat.div_dvd_of_dvd, Nat.dvd_trans]
@[grind .]
theorem AllDivisorsGE.add_one (h : AllDivisorsGE x bound) (h' : ¬ bound ∣ x) :
AllDivisorsGE x (bound + 1) := by
grind [AllDivisorsGE]
/-! ### Verification of the Inner Loop -/
attribute [grind =] Nat.dvd_iff_mod_eq_zero
theorem pairwise_le_factorizeAssumingFactorsGE
(h_bound : 2 ≤ bound ∧ AllDivisorsGE x bound)
(h_acc : acc.toList.Pairwise (· ≤ ·) ∧ acc.all (· ≤ bound)) :
(factorizeAssumingFactorsGE x bound acc).toList.Pairwise (· ≤ ·) := by
fun_induction factorizeAssumingFactorsGE x bound acc
· rename_i x bound acc _ _ _
rw [factorizeAssumingFactorsGE]
simp only [*, ↓reduceIte, Array.toList_push, List.pairwise_append, Array.mem_toList_iff,
Array.forall_mem_iff_forall_getElem]
grind [AllDivisorsGE, Nat.dvd_refl]
· grind [factorizeAssumingFactorsGE]
· rename_i ih
simp only [Array.toList_push, List.pairwise_append, Array.mem_toList_iff,
Array.forall_mem_iff_forall_getElem] at ih
grind [factorizeAssumingFactorsGE]
· grind [factorizeAssumingFactorsGE]
theorem isPrime_of_mem_factorizeAssumingFactorsGE
(h_bound : 2 ≤ bound ∧ AllDivisorsGE x bound) (h_acc : ∀ d ∈ acc, IsPrime d)
(hd : d ∈ factorizeAssumingFactorsGE x bound acc) :
IsPrime d := by
fun_induction factorizeAssumingFactorsGE x bound acc
· rename_i x bound _ _ _ _
rw [factorizeAssumingFactorsGE] at hd
simp only [↓reduceIte, Array.mem_push, *] at hd
cases hd
· grind
· rw [isPrime_iff_mul_self]
simp only [*]
refine ⟨by grind, ?_⟩
intro d' h_gt h_dvd
exact Std.lt_of_lt_of_le ‹_› (Nat.mul_self_le_mul_self (by grind [AllDivisorsGE]))
· grind [factorizeAssumingFactorsGE]
· rename_i x bound _ _ _ _ _
have : IsSmallestDivisor bound x := by grind [IsSmallestDivisor]
grind [factorizeAssumingFactorsGE]
· grind [factorizeAssumingFactorsGE]
theorem foldl_mul_factorizeAssumingFactorsGE
(h_bound : 2 ≤ bound ∧ AllDivisorsGE x bound) (hx : 0 < x) :
(factorizeAssumingFactorsGE x bound acc).foldl (init := 1) (· * ·) =
acc.foldl (init := 1) (· * ·) * x := by
fun_induction factorizeAssumingFactorsGE x bound acc
case case1 => grind [factorizeAssumingFactorsGE]
case case2 => grind [factorizeAssumingFactorsGE]
case case3 x bound _ _ _ h_dvd ih =>
simp only [Nat.div_pos_iff] at ih
simp only [← Nat.dvd_iff_mod_eq_zero] at h_dvd
have := Nat.le_mul_self bound
grind [factorizeAssumingFactorsGE, Nat.dvd_iff_div_mul_eq]
case case4 => grind [factorizeAssumingFactorsGE]
/-!
### Main results
The following three theorems prove the correctness of `factorize`.
They uniquely determine its behavior for `x > 1` because it has a unique sorted prime factorization.
-/
theorem pairwise_le_factorize :
(factorize x).toList.Pairwise (· ≤ ·) := by
apply pairwise_le_factorizeAssumingFactorsGE <;> grind [List.Pairwise.nil, AllDivisorsGE]
theorem isPrime_of_mem_factorize
(hd : d ∈ factorize x) :
IsPrime d := by
apply isPrime_of_mem_factorizeAssumingFactorsGE (hd := hd) <;> grind [AllDivisorsGE]
theorem foldl_mul_factorize (hx : 0 < x) :
(factorize x).foldl (init := 1) (· * ·) = x := by
rw [factorize, foldl_mul_factorizeAssumingFactorsGE] <;> grind [AllDivisorsGE]
/-!
## Prompt
```python3
from typing import List
def factorize(n: int) -> List[int]:
""" Return list of prime factors of given integer in the order from smallest to largest.
Each of the factors should be listed number of times corresponding to how many times it appeares in factorization.
Input number should be equal to the product of all factors
>>> factorize(8)
[2, 2, 2]
>>> factorize(25)
[5, 5]
>>> factorize(70)
[2, 5, 7]
"""
```
## Canonical solution
```python3
import math
fact = []
i = 2
while i <= int(math.sqrt(n) + 1):
if n % i == 0:
fact.append(i)
n //= i
else:
i += 1
if n > 1:
fact.append(n)
return fact
```
## Tests
```python3
METADATA = {
'author': 'jt',
'dataset': 'test'
}
def check(candidate):
assert candidate(2) == [2]
assert candidate(4) == [2, 2]
assert candidate(8) == [2, 2, 2]
assert candidate(3 * 19) == [3, 19]
assert candidate(3 * 19 * 3 * 19) == [3, 3, 19, 19]
assert candidate(3 * 19 * 3 * 19 * 3 * 19) == [3, 3, 3, 19, 19, 19]
assert candidate(3 * 19 * 19 * 19) == [3, 19, 19, 19]
assert candidate(3 * 2 * 3) == [2, 3, 3]
```
-/