forked from leanprover/human-eval-lean
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathHumanEval128.lean
More file actions
146 lines (115 loc) · 3.96 KB
/
HumanEval128.lean
File metadata and controls
146 lines (115 loc) · 3.96 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
module
import Std
open Std Std.Do
set_option mvcgen.warning false
/-!
# HumanEval 128: Sum of magnitudes times product of signs
This problem description asks us to compute the sum of absolute values of an array, multiplied by
the product of the signs of all elements. We demonstrate how to implement and verify an
efficient implementation using `do` notation and `mvcgen`.
-/
/-!
## Missing API
-/
def List.product (xs : List Int) : Int :=
xs.foldr (· * ·) 1
@[grind =]
theorem List.product_nil : ([] : List Int).product = 1 := by
rfl
@[grind =]
theorem List.product_cons {x : Int} {xs : List Int} :
(x :: xs).product = x * xs.product := by
grind [List.product]
@[grind =]
theorem List.product_append {xs ys : List Int} :
(xs ++ ys).product = xs.product * ys.product := by
induction xs <;> grind [List.product_cons, Int.mul_assoc]
theorem List.product_eq_zero_iff {xs : List Int} :
xs.product = 0 ↔ 0 ∈ xs := by
induction xs <;> grind [List.product_cons, Int.mul_eq_zero]
theorem Option.of_wp {α} {prog : Option α} (P : Option α → Prop) :
(⊢ₛ wp⟦prog⟧ post⟨fun a => ⌜P (some a)⌝, fun _ => ⌜P none⌝⟩) → P prog := by
cases prog <;> simp [wp, Option.instWP._aux_1, OptionT.run]
theorem Option.of_wp_eq {α : Type} {x : Option α} {prog : Option α} (h : prog = x) (P : Option α → Prop) :
(⊢ₛ wp⟦prog⟧ post⟨fun a => ⌜P (some a)⌝, fun _ => ⌜P none⌝⟩) → P x := by
rw [← h]
apply Option.of_wp
/-!
## Implementation
-/
def prodSigns (arr : List Int) : Option Int := do
if arr.isEmpty then
none
let mut sum := 0
let mut sign := 1
for x in arr do
if x = 0 then
return 0
sum := sum + x.natAbs
sign := sign * x.sign
return sum * sign
/-!
## Tests
-/
example : prodSigns [1, 2, 2, -4] = some (-9) := by cbv
example : prodSigns [0, 1] = some 0 := by cbv
example : prodSigns [] = none := by cbv
example : prodSigns [1, 1, 1, 2, 3, -1, 1] = some (-10) := by cbv
example : prodSigns [2, 4, 1, 2, -1, -1, 9] = some 20 := by cbv
example : prodSigns [-1, 1, -1, 1] = some 4 := by cbv
example : prodSigns [-1, 1, 1, 1] = some (-4) := by cbv
example : prodSigns [-1, 1, 1, 0] = some 0 := by cbv
/-!
## Verification
-/
theorem prodSigns_nil :
prodSigns [] = none := by
grind [prodSigns]
theorem prodSigns_of_ne_nil {xs : List Int} (h : xs ≠ []) :
prodSigns xs = some ((xs.map Int.natAbs).sum * (xs.map Int.sign).product) := by
generalize hwp : prodSigns xs = wp
apply Option.of_wp_eq hwp
mvcgen [prodSigns]
invariants
· .withEarlyReturn
(fun cur ⟨sign, sum⟩ => ⌜sum = (cur.prefix.map Int.natAbs).sum ∧ sign = (cur.prefix.map Int.sign).product⌝)
(fun ret ⟨sign, sum⟩ => ⌜ret = 0 ∧ 0 ∈ xs⌝)
with grind [List.product_eq_zero_iff]
/-!
## Prompt
```python3
def prod_signs(arr):
"""
You are given an array arr of integers and you need to return
sum of magnitudes of integers multiplied by product of all signs
of each number in the array, represented by 1, -1 or 0.
Note: return None for empty arr.
Example:
>>> prod_signs([1, 2, 2, -4]) == -9
>>> prod_signs([0, 1]) == 0
>>> prod_signs([]) == None
"""
```
## Canonical solution
```python3
if not arr: return None
prod = 0 if 0 in arr else (-1) ** len(list(filter(lambda x: x < 0, arr)))
return prod * sum([abs(i) for i in arr])
```
## Tests
```python3
def check(candidate):
# Check some simple cases
assert True, "This prints if this assert fails 1 (good for debugging!)"
assert candidate([1, 2, 2, -4]) == -9
assert candidate([0, 1]) == 0
assert candidate([1, 1, 1, 2, 3, -1, 1]) == -10
assert candidate([]) == None
assert candidate([2, 4,1, 2, -1, -1, 9]) == 20
assert candidate([-1, 1, -1, 1]) == 4
assert candidate([-1, 1, 1, 1]) == -4
assert candidate([-1, 1, 1, 0]) == 0
# Check some edge cases that are easy to work out by hand.
assert True, "This prints if this assert fails 2 (also good for debugging!)"
```
-/