Skip to content

Commit 10bf8f9

Browse files
committed
Add (partial )solution to HumanEval160
1 parent 3f1553c commit 10bf8f9

File tree

1 file changed

+123
-10
lines changed

1 file changed

+123
-10
lines changed

HumanEvalLean/HumanEval160.lean

Lines changed: 123 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,118 @@
1-
def do_algebra : Unit :=
2-
()
1+
inductive Op where
2+
| add
3+
| sub
4+
| mul
5+
| div
6+
| pow
7+
8+
namespace Op
9+
10+
instance : ToString Op where
11+
toString
12+
| add => "+"
13+
| sub => "-"
14+
| mul => "*"
15+
| div => "/"
16+
| pow => "^"
17+
18+
def prio : Op → Nat
19+
| add | sub => 1
20+
| mul | div => 2
21+
| pow => 3
22+
23+
def leftAssoc : Op → Bool
24+
| add | sub => true
25+
| mul | div => true
26+
| pow => false
27+
28+
def interpret : Op → (Nat → Nat → Nat)
29+
| add => (· + ·)
30+
| sub => (· - ·)
31+
| mul => (· * ·)
32+
| div => (· / ·)
33+
| pow => (· ^ ·)
34+
35+
end Op
36+
37+
inductive Expr where
38+
| lit (n : Nat)
39+
| app (op : Op) (arg₁ arg₂ : Expr)
40+
deriving Inhabited
41+
42+
namespace Expr
43+
44+
instance : ToString Expr where
45+
toString :=
46+
let rec go
47+
| .lit n => s!"{n}"
48+
| .app op arg₁ arg₂ => s!"({go arg₁} {op} {go arg₂})"
49+
go
50+
51+
def eval : Expr → Nat
52+
| lit n => n
53+
| app op arg₁ arg₂ => op.interpret arg₁.eval arg₂.eval
54+
55+
structure ParseState where
56+
ops : List Op := []
57+
args : List Nat := []
58+
hold : List Op := []
59+
output : List Expr := []
60+
deriving Inhabited
61+
62+
namespace ParseState
63+
64+
def pushArg (σ : ParseState) (arg : Nat) : ParseState :=
65+
{ σ with output := (lit arg) :: σ.output }
66+
67+
@[simp]
68+
theorem pushArg_ops (σ : ParseState) : (σ.pushArg arg).ops = σ.ops := rfl
69+
70+
def pushOp (σ : ParseState) (op : Op) : ParseState :=
71+
match σ.hold with
72+
| [] => { σ with hold := [op] }
73+
| top :: hold =>
74+
match compare top.prio op.prio, top.leftAssoc with
75+
| .lt, _ | .eq, false => { σ with hold := op :: top :: hold }
76+
| .gt, _ | .eq, true =>
77+
match σ.output with
78+
| arg₂ :: arg₁ :: out => { σ with hold := op :: hold, output := .app top arg₁ arg₂ :: out }
79+
| _ => σ -- Trash value chosen to easily satisfy `pushOp_ops`.
80+
81+
@[simp]
82+
theorem pushOp_ops (σ : ParseState) : (σ.pushOp op).ops = σ.ops := by
83+
rw [pushOp]
84+
repeat (split <;> try rfl)
85+
86+
def finalize (σ : ParseState) : ParseState :=
87+
match _ : σ.hold, σ.output with
88+
| op :: hold, arg₂ :: arg₁ :: out => finalize { σ with hold, output := .app op arg₁ arg₂ :: out }
89+
| _, _ => σ
90+
termination_by σ.hold
91+
decreasing_by simp_all +arith
92+
93+
end ParseState
94+
95+
-- Parses an expression based on the "shunting yard algorithm".
96+
def parse! (ops : List Op) (args : List Nat) : Expr :=
97+
go { ops, args } |>.output[0]!
98+
where
99+
go (σ : ParseState) : ParseState :=
100+
match _ : σ.ops, σ.args with
101+
| op :: ops, arg :: args => { σ with ops, args } |>.pushArg arg |>.pushOp op |> go
102+
| [], [arg] => { σ with args := [] } |>.pushArg arg |>.finalize
103+
| _, _ => panic! "Invalid parse state"
104+
termination_by σ.ops
105+
decreasing_by simp_all +arith
106+
107+
end Expr
108+
109+
def doAlgebra (ops : List Op) (args : List Nat) : Nat :=
110+
Expr.parse! ops args |>.eval
111+
112+
example : doAlgebra [.add, .mul, .sub] [2, 3, 4, 5] = 9 := by native_decide
113+
example : doAlgebra [.pow, .mul, .add] [2, 3, 4, 5] = 37 := by native_decide
114+
example : doAlgebra [.add, .mul, .sub] [2, 3, 4, 5] = 9 := by native_decide
115+
example : doAlgebra [.div, .mul] [7, 3, 4] = 8 := by native_decide
3116

4117
/-!
5118
## Prompt
@@ -8,16 +121,16 @@ def do_algebra : Unit :=
8121
9122
def do_algebra(operator, operand):
10123
"""
11-
Given two lists operator, and operand. The first list has basic algebra operations, and
12-
the second list is a list of integers. Use the two given lists to build the algebric
124+
Given two lists operator, and operand. The first list has basic algebra operations, and
125+
the second list is a list of integers. Use the two given lists to build the algebric
13126
expression and return the evaluation of this expression.
14127
15128
The basic algebra operations:
16-
Addition ( + )
17-
Subtraction ( - )
18-
Multiplication ( * )
19-
Floor division ( // )
20-
Exponentiation ( ** )
129+
Addition ( + )
130+
Subtraction ( - )
131+
Multiplication ( * )
132+
Floor division ( // )
133+
Exponentiation ( ** )
21134
22135
Example:
23136
operator['+', '*', '-']
@@ -56,4 +169,4 @@ def check(candidate):
56169
assert True, "This prints if this assert fails 2 (also good for debugging!)"
57170
58171
```
59-
-/
172+
-/

0 commit comments

Comments
 (0)