Skip to content

Commit a03271f

Browse files
committed
HumanEval24
1 parent d05093a commit a03271f

File tree

1 file changed

+132
-3
lines changed

1 file changed

+132
-3
lines changed

HumanEvalLean/HumanEval24.lean

Lines changed: 132 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,134 @@
1-
def largest_divisor : Unit :=
2-
()
1+
/-- Computes the largest divisor in O(sqrt n) via trial divison. -/
2+
def largestDivisor (n : Nat) : Nat :=
3+
go 2
4+
where
5+
go (i : Nat) : Nat :=
6+
if h : n < i * i then
7+
1
8+
else if n % i = 0 then
9+
n / i
10+
else go (i + 1)
11+
termination_by n - i
12+
decreasing_by
13+
have : i < n := by
14+
match i with
15+
| 0 => omega
16+
| 1 => omega
17+
| i + 2 => exact Nat.lt_of_lt_of_le (Nat.lt_mul_self_iff.2 (by omega)) (Nat.not_lt.1 h)
18+
omega
19+
20+
example : largestDivisor 3 = 1 := by native_decide
21+
example : largestDivisor 7 = 1 := by native_decide
22+
example : largestDivisor 10 = 5 := by native_decide
23+
example : largestDivisor 100 = 50 := by native_decide
24+
example : largestDivisor 49 = 7 := by native_decide
25+
26+
inductive LargestDivisorSpec (n : Nat) : Nat → Prop
27+
| one : (∀ j, 2 ≤ j → j * j ≤ n → n % j ≠ 0) → LargestDivisorSpec n 1
28+
| div {i} : (∀ j, 2 ≤ j → j < i → n % j ≠ 0) → 2 ≤ i → n % i = 0 → LargestDivisorSpec n (n / i)
29+
30+
theorem largestDivisorSpec_go {n i : Nat} (hi : 2 ≤ i)
31+
(hi' : ∀ j, 2 ≤ j → j < i → n % j ≠ 0) : LargestDivisorSpec n (largestDivisor.go n i) := by
32+
fun_induction largestDivisor.go n i
33+
case case1 i hni =>
34+
rw [largestDivisor.go, dif_pos hni]
35+
apply LargestDivisorSpec.one
36+
intro j hj hj'
37+
apply hi' _ hj
38+
exact Nat.mul_self_lt_mul_self_iff.1 (Nat.lt_of_le_of_lt hj' hni)
39+
case case2 i hni hni' =>
40+
rw [largestDivisor.go, dif_neg hni, if_pos hni']
41+
exact LargestDivisorSpec.div hi' hi hni'
42+
case case3 i hni hni' ih =>
43+
rw [largestDivisor.go, dif_neg hni, if_neg hni']
44+
apply ih (by omega)
45+
intro j hj hij
46+
by_cases hij' : j = i
47+
· exact hij' ▸ hni'
48+
· exact hi' _ hj (by omega)
49+
50+
theorem largestDivisorSpec_largestDivisor {n : Nat} :
51+
LargestDivisorSpec n (largestDivisor n) := by
52+
rw [largestDivisor]
53+
exact largestDivisorSpec_go (Nat.le_refl _) (by omega)
54+
55+
theorem Nat.lt_mul_iff {a b : Nat} : a < a * b ↔ 0 < a ∧ 1 < b := by
56+
obtain (rfl|ha) := Nat.eq_zero_or_pos a
57+
· simp
58+
· simp [ha]
59+
60+
theorem helper {n i : Nat} (hn : 1 < n) (h : ∀ j, 2 ≤ j → j < i → n % j ≠ 0) (hi : n % i = 0)
61+
(k : Nat) (hk : n / i < k) (hk₁ : k < n) : n % k ≠ 0 := by
62+
intro hk₂
63+
obtain ⟨d, rfl⟩ := Nat.dvd_of_mod_eq_zero hk₂
64+
rw [Nat.lt_mul_iff] at hk₁
65+
have hi₀ : 0 < i := by
66+
apply Nat.pos_iff_ne_zero.2
67+
rintro rfl
68+
simp only [Nat.mod_zero] at hi
69+
omega
70+
refine h d ?_ ?_ (by simp)
71+
· omega
72+
· rw [Nat.div_lt_iff_lt_mul hi₀] at hk
73+
exact Nat.lt_of_mul_lt_mul_left hk
74+
75+
theorem similar_helper {n : Nat} (hn : 1 < n) (h : ∀ j, 2 ≤ j → j * j ≤ n → n % j ≠ 0)
76+
(k : Nat) (hk : n < k * k) (hk₁ : k < n) : n % k ≠ 0 := by
77+
intro hk₂
78+
obtain ⟨d, rfl⟩ := Nat.dvd_of_mod_eq_zero hk₂
79+
rw [Nat.lt_mul_iff] at hk₁
80+
refine h d ?_ ?_ (by simp)
81+
· omega
82+
· refine Nat.mul_le_mul_right _ (Nat.le_of_lt ?_)
83+
exact Nat.lt_of_mul_lt_mul_left hk
84+
85+
theorem largestDivisorSpec_iff {n i : Nat} (hn : 1 < n) :
86+
LargestDivisorSpec n i ↔ i < n ∧ n % i = 0 ∧ ∀ j, j < n → n % j = 0 → j ≤ i := by
87+
constructor
88+
· rintro (h|h)
89+
· refine ⟨hn, Nat.mod_one _, fun j hj hj₁ => Nat.not_lt.1 (fun hj₂ => ?_)⟩
90+
by_cases hj₃ : j * j ≤ n
91+
· exact h j (by omega) hj₃ hj₁
92+
· exact similar_helper hn h j (by omega) hj hj₁
93+
· rename_i i hi hi'
94+
refine ⟨?_, ?_, fun j hj hj₁ => ?_⟩
95+
· apply Nat.div_lt_self <;> omega
96+
· exact Nat.mod_eq_zero_of_dvd (Nat.div_dvd_of_dvd (Nat.dvd_of_mod_eq_zero hi'))
97+
· exact Nat.not_lt.1 (fun hj₂ => helper hn h hi' j hj₂ hj hj₁)
98+
· rintro ⟨hi₁, hi₂, hi₃⟩
99+
obtain (h|rfl|h) := Nat.lt_trichotomy i 1
100+
· obtain rfl : i = 0 := by omega
101+
omega
102+
· refine LargestDivisorSpec.one (fun j hj hj₁ hj₂ => absurd (hi₃ j ?_ hj₂) (by omega))
103+
exact Nat.lt_of_lt_of_le (Nat.lt_mul_self_iff.2 (by omega)) hj₁
104+
· obtain ⟨d, rfl⟩ := Nat.dvd_of_mod_eq_zero hi₂
105+
have hd : 0 < d := Nat.pos_iff_ne_zero.2 (fun hd => by simp [hd] at hn)
106+
rw (occs := [2]) [← Nat.mul_div_cancel (m := i) (n := d) hd]
107+
refine LargestDivisorSpec.div ?_ ?_ (by simp)
108+
· intro j hj₁ hj₂ hj₃
109+
have : ¬ i * d / j ≤ i := by
110+
rw [Nat.not_le, Nat.lt_div_iff_mul_lt_of_dvd (by omega) (Nat.dvd_of_mod_eq_zero hj₃)]
111+
exact Nat.mul_lt_mul_of_pos_left hj₂ (by omega)
112+
refine absurd (hi₃ _ ?_ ?_) this
113+
· apply Nat.div_lt_self (by omega) (by omega)
114+
· exact Nat.mod_eq_zero_of_dvd (Nat.div_dvd_of_dvd (Nat.dvd_of_mod_eq_zero hj₃))
115+
· rw [Nat.lt_mul_iff] at hi₁
116+
omega
117+
118+
theorem largestDivisorSpec_unique {n i k : Nat} (hn : 1 < n)
119+
(hi : LargestDivisorSpec n i) (hk : LargestDivisorSpec n k) : i = k := by
120+
simp only [largestDivisorSpec_iff hn] at hi hk
121+
apply Nat.le_antisymm
122+
· apply hk.2.2 _ hi.1 hi.2.1
123+
· apply hi.2.2 _ hk.1 hk.2.1
124+
125+
theorem largestDivisor_eq_iff {n i : Nat} (hn : 1 < n) :
126+
largestDivisor n = i ↔ i < n ∧ n % i = 0 ∧ ∀ j, j < n → n % j = 0 → j ≤ i := by
127+
rw [← largestDivisorSpec_iff hn]
128+
refine ⟨?_, fun hi => ?_⟩
129+
· rintro rfl
130+
apply largestDivisorSpec_largestDivisor
131+
· apply largestDivisorSpec_unique hn largestDivisorSpec_largestDivisor hi
3132

4133
/-!
5134
## Prompt
@@ -40,4 +169,4 @@ def check(candidate):
40169
assert candidate(100) == 50
41170
assert candidate(49) == 7
42171
```
43-
-/
172+
-/

0 commit comments

Comments
 (0)