Skip to content

Commit 9f0aa73

Browse files
committed
HumanEval43
1 parent 7fe45c5 commit 9f0aa73

File tree

2 files changed

+158
-4
lines changed

2 files changed

+158
-4
lines changed

HumanEvalLean/HumanEval43.lean

Lines changed: 157 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,99 @@
1-
def pairs_sum_to_zero : Unit :=
2-
()
1+
import Std.Data.HashSet.Lemmas
2+
import Std.Tactic.Do
3+
4+
open Std Do
5+
6+
theorem List.exists_mem_iff_exists_getElem (P : α → Prop) (l : List α) :
7+
(∃ x ∈ l, P x) ↔ ∃ (i : Nat), ∃ hi, P (l[i]'hi) := by
8+
grind [mem_iff_getElem]
9+
10+
structure List.Any₂ (P : α → α → Prop) (l : List α) where
11+
not_pairwise : ¬ l.Pairwise (fun x y => ¬P x y)
12+
13+
theorem List.any₂_iff_not_pairwise {P : α → α → Prop} {l : List α} :
14+
l.Any₂ P ↔ ¬l.Pairwise (fun x y => ¬P x y) := by
15+
grind [List.Any₂]
16+
17+
@[simp, grind]
18+
theorem not_any₂_nil {P : α → α → Prop} : ¬List.Any₂ P [] := by
19+
simp [List.any₂_iff_not_pairwise]
20+
21+
@[simp, grind]
22+
theorem List.any₂_cons {P : α → α → Prop} {x : α} {xs : List α} :
23+
List.Any₂ P (x::xs) ↔ (∃ y ∈ xs, P x y) ∨ List.Any₂ P xs := by
24+
grind [List.any₂_iff_not_pairwise]
25+
26+
@[grind]
27+
theorem List.any₂_append {P : α → α → Prop} {xs ys : List α} :
28+
List.Any₂ P (xs ++ ys) ↔ List.Any₂ P xs ∨ List.Any₂ P ys ∨ (∃ x ∈ xs, ∃ y ∈ ys, P x y) := by
29+
grind [List.any₂_iff_not_pairwise]
30+
31+
def pairsSumToZero (l : List Int) : Bool :=
32+
go l ∅
33+
where
34+
go (m : List Int) (seen : HashSet Int) : Bool :=
35+
match m with
36+
| [] => false
37+
| x::xs => if -x ∈ seen then true else go xs (seen.insert x)
38+
39+
example : pairsSumToZero [1, 3, 5, 0] = false := by native_decide
40+
example : pairsSumToZero [1, 3, -2, 1] = false := by native_decide
41+
example : pairsSumToZero [1, 2, 3, 7] = false := by native_decide
42+
example : pairsSumToZero [2, 4, -5, 3, 5, 7] = true := by native_decide
43+
example : pairsSumToZero [1] = false := by native_decide
44+
45+
-- `simp` does not solve this!!
46+
example {x : Int} : -x + x = 0 := by omega
47+
48+
theorem pairsSumToZero_go_iff (l : List Int) (seen : HashSet Int) :
49+
pairsSumToZero.go l seen = true
50+
l.Any₂ (fun a b => a + b = 0) ∨ ∃ a ∈ seen, ∃ b ∈ l, a + b = 0 := by
51+
fun_induction pairsSumToZero.go <;> simp <;> grind
52+
53+
theorem pairsSumToZero_iff (l : List Int) :
54+
pairsSumToZero l = true ↔ l.Any₂ (fun a b => a + b = 0) := by
55+
simp [pairsSumToZero, pairsSumToZero_go_iff]
56+
57+
def pairsSumToZero' (l : List Int) : Id Bool := do
58+
let mut seen : HashSet Int := ∅
59+
for x in l do
60+
if -x ∈ seen then
61+
return true
62+
seen := seen.insert x
63+
return false
64+
65+
-- Pain: I have no idea what the system wants from me when building an invariant.
66+
-- What is a PostCond? What does the function I'm returning mean? How are early returns
67+
-- and things like that represented?
68+
69+
-- Pain: The need to have the `l = z.pref` trick in the loop invariant. If you don't know this
70+
-- it's hard to make progress. It would be really cool if there was some kind of "interactive"
71+
-- way to build the loop invariant in multiple steps where I only have to input the
72+
-- `(∀ x, x ∈ s ↔ x ∈ z.rpref) ∧ ¬ z.pref.Any₂ (fun a b => a + b = 0)` and
73+
-- `l.Any₂ (fun a b => a + b = 0)` parts and the `o = none/some` and `l = z.pref` gadgets are
74+
-- added automatically.
75+
76+
-- Pain: `refine` does not play well with `⇓` it seems
77+
78+
-- Pain: mvcgen generated multiple assumptions named `h`, leading to inaccessible names
79+
-- Pain: mvcgen generally creates inaccessible names
80+
81+
@[simp]
82+
theorem List.Zipper.pref_mk {l : List α} {rpref suff h} :
83+
(List.Zipper.mk rpref suff h : List.Zipper l).pref = rpref.reverse := rfl
84+
85+
set_option mvcgen.warning false
86+
87+
theorem pairsSumToZero'_spec (l : List Int) :
88+
⦃⌜True⌝⦄ pairsSumToZero' l ⦃⇓r => r = true ↔ l.Any₂ (fun a b => a + b = 0)⦄ := by
89+
mvcgen [pairsSumToZero']
90+
91+
case inv =>
92+
exact (fun (⟨o, s⟩, z) =>
93+
(o = none ∧ (∀ x, x ∈ s ↔ x ∈ z.rpref) ∧ ¬ z.pref.Any₂ (fun a b => a + b = 0)) ∨
94+
(o = some true ∧ l.Any₂ (fun a b => a + b = 0) ∧ l = z.pref), ())
95+
96+
all_goals simp_all [List.any₂_append] <;> grind
397

498
/-!
599
## Prompt
@@ -56,4 +150,64 @@ def check(candidate):
56150
assert candidate([-3, 9, -1, 4, 2, 31]) == False
57151
58152
```
59-
-/
153+
-/
154+
155+
/-! Bonus material -/
156+
157+
theorem List.exists_append (l : List α) (n : Nat) (h : n ≤ l.length) : ∃ xs ys, ys.length = n ∧ l = xs ++ ys :=
158+
⟨l.take (l.length - n), l.drop (l.length - n), by grind, by simp⟩
159+
160+
@[simp]
161+
theorem Std.HashSet.toList_emptyWithCapacity {α : Type u} [BEq α] [Hashable α]
162+
[EquivBEq α] [LawfulHashable α] {n : Nat} :
163+
(HashSet.emptyWithCapacity n : HashSet α).toList = [] := by
164+
simp [← List.isEmpty_iff]
165+
166+
@[simp]
167+
theorem Std.HashSet.toList_empty {α : Type u} [BEq α] [Hashable α]
168+
[EquivBEq α] [LawfulHashable α] : (∅ : HashSet α).toList = [] := by
169+
simp [← List.isEmpty_iff]
170+
171+
theorem List.Any₂.append_left {P : α → α → Prop} (xs : List α) {ys : List α} (h : ys.Any₂ P) : (xs ++ ys).Any₂ P :=
172+
List.any₂_append.2 (by simp [h])
173+
174+
theorem List.Any₂.append_right {P : α → α → Prop} {xs : List α} (ys : List α) (h : xs.Any₂ P) : (xs ++ ys).Any₂ P :=
175+
List.any₂_append.2 (by simp [h])
176+
177+
theorem List.any₂_append_left_right {P : α → α → Prop} (xs ys : List α) (h : ∃ x ∈ xs, ∃ y ∈ ys, P x y) :
178+
(xs ++ ys).Any₂ P :=
179+
List.any₂_append.2 (by simp [h])
180+
181+
theorem List.any₂_iff_exists (P : α → α → Prop) (l : List α) :
182+
List.Any₂ P l ↔ ∃ xs x ys, l = xs ++ x :: ys ∧ ∃ y ∈ ys, P x y := by
183+
constructor
184+
· rintro ⟨h⟩
185+
induction l with
186+
| nil => grind
187+
| cons x xs ih =>
188+
rw [List.pairwise_cons, Classical.not_and_iff_not_or_not] at h
189+
simp only [Classical.not_forall, Classical.not_not] at h
190+
rcases h with (⟨y, hy, hxy⟩|h)
191+
· exact ⟨[], by grind⟩
192+
· grind
193+
· grind
194+
195+
theorem List.any₂_iff_exists_getElem (P : α → α → Prop) (l : List α) :
196+
List.Any₂ P l ↔ ∃ (i j : Nat), ∃ hi hj, i < j ∧ P (l[i]'hi) (l[j]'hj) := by
197+
rw [List.any₂_iff_exists]
198+
constructor
199+
· rintro ⟨xs, x, ys, ⟨rfl, h⟩⟩
200+
obtain ⟨j₀, hj₀, hj₀'⟩ := (List.exists_mem_iff_exists_getElem _ _).1 h
201+
exact ⟨xs.length, xs.length + 1 + j₀, by grind⟩
202+
· rintro ⟨i, j, hi, hj, hij, h⟩
203+
exact ⟨l.take i, l[i], l.drop (i + 1), by simp,
204+
(List.exists_mem_iff_exists_getElem _ _).2 ⟨j - i - 1, by grind, by grind⟩⟩
205+
206+
@[simp, grind]
207+
theorem List.any₂_append_singleton {P : α → α → Prop} {xs : List α} {x : α} :
208+
List.Any₂ P (xs ++ [x]) ↔ List.Any₂ P xs ∨ ∃ y ∈ xs, P y x := by
209+
grind [List.any₂_iff_not_pairwise]
210+
211+
@[simp, grind]
212+
theorem not_any₂_singleton {P : α → α → Prop} {x : α} : ¬List.Any₂ P [x] := by
213+
simp [List.any₂_iff_not_pairwise]

lean-toolchain

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
leanprover/lean4:v4.21.0
1+
leanprover/lean4:v4.22.0-rc1

0 commit comments

Comments
 (0)