# Code Golf: Parser

Discussion in 'Programming' started by glatteis, May 16, 2016.

1. ### glatteis

I thought I'd make another code golf! Rules are here: http://glatteis.bplaced.net/CodeGolf

This time, the task is to make a method (or function) that takes a string containing an expression that follows the rules stated below. It should return a double (or number) that is the solution of the evaluated expression.

Code (Text):
The parser should parse expressions of the following pattern: There are four functions, which are add, sub, mul and div. They add, subtract, multiply and divide respectively. All of the functions take two arguments. Example:

'add 5 8' should return 5 + 8, which is 13.
'div 8 2' should return 8 / 2, which is 4.
'mul 6 0.5' should return 6 * 0.5, which should be about 3.

(the method should not return the calculations but the solutions.)

Arguments of functions themselves can be solutions of functions. Example:

'mul add 4 7 2' should return (4+7) * 2, which is 22.

Special handling of dividing by 0 is not nessecary.
Happy golfing! The golf ends in one or two weeks, depending on how many people want to participate.

• Like x 1
• Agree x 1
2. I have been waiting for you to do this :/
Even though I suck lol

3. I did the first part, but rqed at the second.

4. ### glatteis

I have yet to try this myself. I will do that now.

5. ### glatteis

Reference ruby implementation I did:
Code (Text):
# @return [int]
# @param [String] expression
def parse(expression)
a = expression.split(' ')
(a.length - 1).downto(1).each do |i|
unless is_number?(a[i])
sol = parse(a.slice(i, i+2).join(' '))
a.delete_at(i)
a.delete_at(i + 1)
a.delete_at(i + 2)
a[i] = sol
return parse a.join(' ')
end
end

b = a.to_f
c = a.to_f

case a
b + c
when 'sub'
b - c
when 'div'
b / c
when 'mul'
b * c
else
-1
end

end

def is_number?(s)
true if Float(s) rescue false
end
Not very short though • Agree x 1
6. I think I can do the part with one function, but not two. Does it have to be able to do more than 2 so 5 functions or only a max of two?

7. My attempt in C#
Code (C#):
int Parse(string input)
{
Stack<string> op = new Stack<string>();
List<double> args = new List<double>();

foreach (string part in input.Split(' '))
{
switch (part)
{
case "add": case "sub": case "mul": case "div":
op.Push(part);
break;
default:
break;
}
}

Stack<double> stack = new Stack<double>(args.Reverse<double>());

while (op.Count > 0)
{
switch (op.Pop())
{
stack.Push(stack.Pop() + stack.Pop());
break;
case "sub":
stack.Push(stack.Pop() - stack.Pop());
break;
case "mul":
stack.Push(stack.Pop() * stack.Pop());
break;
case "div":
stack.Push(stack.Pop() / stack.Pop());
break;
}
}
return Convert.ToInt32(stack.Pop());
}
Mine isn't very short either #7
Last edited: May 22, 2016
• Agree x 1
8. I decided to code this in JavaScript to show you how broken JavaScript can be.
Code (Java):
function parse(input) {
var opStack = [], argStack = [], token = input.split(' ');
for (var o in token)
isNaN(token[o]) ? opStack.push(token[o]) : argStack.unshift(parseFloat(token[o]));
for (opStack.length > 0; o = opStack.pop();)
argStack.push(eval("argStack.pop() " + (o == "add" ? "+" : o == "sub" ? "-" : o == "mul" ? "*" : "/") + " argStack.pop()"));
return argStack.pop();
}
Here's a happy list of abuse in those lines of code:
• Single line variable assignment abuse
• Ternary abuse
• Eval abuse
• Single line blocks abuse

I'm probably satan for abusing JavaScript. There's argument it could be slightly shorter but hey Edit:
Code (Java):
function parse(e){var z=[],a=[],k=e.split(" ");for(var o in k)isNaN(k[o])?z.push(k[o]):a.unshift(parseFloat(k[o]));for(z.length>0;o=z.pop();)a.push(eval("a.pop() "+("add"==o?"+":"sub"==o?"-":"mul"==o?"*":"/")+" a.pop()"));return a.pop()};
(Tested in browsers)

#8
Last edited: May 22, 2016
• Like x 1
9. Redid mine to solve recursively Code (C#):
int Parse(string[] input)
{
string[] args = input.Split(' ');
switch (args)
{
case "add": case "sub": case "mul": case "div":
string[] pass = new string[input.Count() + 1];
for (int i = 0; i < pass.Count(); i++)
{
pass[i] = (i == 0) ? input.Substring(4) : ((i == input.Count()) ? args : input[i]);
}
return Parse(pass);
default:
Stack<double> operands = new Stack<double>(args.Select(arg => Convert.ToDouble(arg)).Reverse());
for (int i = input.Count() - 1; i > 0; i--)
{
switch (input[i])
{
operands.Push(operands.Pop() + operands.Pop()); break;
case "sub":
operands.Push(operands.Pop() - operands.Pop()); break;
case "mul":
operands.Push(operands.Pop() * operands.Pop()); break;
case "div":
operands.Push(operands.Pop() / operands.Pop()); break;
}
}
return Convert.ToInt32(operands.Pop());
}
}
^ I managed to take off 9 lines from my previous one.

#9
Last edited: May 22, 2016
10. ### akselm

Here's a java one that's probably not as concise as could be but 473 characters:
Code (Text):
public static float p(String i){
String[] d = i.split(" ");
int o = d.length - 3;
float c = m(d, Float.valueOf(d), Float.valueOf(d));
for (int n = 0; n < o; n++){
c = m(d, c, Float.valueOf(d[3+n]));
}
return c;
}

public static float m(String t, float x, float y){
return (t.equals("mul") ? x * y : t.equals("add") ? x + y : t.equals("sub") ? x - y: t.equals("div") ? x/y:0);
}
m() is a utility method. it works recursively for any amount of numbers inputted
EDIT: Better (longer ) version down below that does the arguments.

#10
Last edited: May 22, 2016
11. Oh lord... what have you done.

12. That won't work if it's something like "mul add 4 7 2"

EDIT: My entry will come.

13. ### akselm

New version that supports multiple arguments (oops) 620 characters, i bet it could be shorter.
Code (Text):
public static float p(String i){
String[] d = i.split(" ");
int l = 0;
for (int n = 0; n < d.length; n++) if (!d[n].matches("-?\\d+(.\\d+)?")) l = n;
int o = d.length - 3 - l;
float c = m(d, Float.valueOf(d[l+1]), Float.valueOf(d[l+2]));
for (int n = 0; n < o; n++){
c = m((l > 0 && l-n >= 0) ? d[l+n] : d, c, Float.valueOf(d[n+3+l]));
}
return c;
}

public static float m(String t, float x, float y){
return (t.equals("mul") ? x * y : t.equals("add") ? x + y : t.equals("sub") ? x - y: t.equals("div") ? x/y:0);
}

#13
Last edited: May 22, 2016
14. In Java 399 characters, supports one or more calculations inside each other. (Completely changed all variables and removed spaces).
Code (Text):
class A{public static void main(String[]a){int b=0;while(a[b].matches("^[a-zA-Z]*\$"))b++;b--;float c=0;int d=b+1;boolean e=true;do{if(e){c=a(a[b],Float.valueOf(a[d]),Float.valueOf(a[d+1]));e=false;d+=2;}else{c=a(a[b],c,Float.valueOf(a[d]));d++;}b--;}while(b>=0);System.out.println(c);}static float a(String a,float b,float c){return a.equals("add")?b+c:a.equals("sub")?b-c:a.equals("mul")?b*c:b/c;}}
Best of all it uses the default arguments from the java main method, so I don't have to split it myself . This is the code with spaces:
Code (Text):
class A {
public static void main(String[] a) {
int b = 0;
while(a[b].matches("^[a-zA-Z]*\$"))
b++;
b--;
float c = 0;
int d = b + 1;
boolean e = true;
do {
if (e) {
c = a(a[b], Float.valueOf(a[d]), Float.valueOf(a[d + 1]));
e = false;
d += 2;
} else {
c = a(a[b], c, Float.valueOf(a[d]));
d++;
}
b--;
} while (b>=0);
System.out.println(c);
}

static float a(String a, float b, float c) {
return a.equals("add") ? b + c : a.equals("sub") ? b - c : a.equals("mul") ? b * c : b / c;
}
}

15. Yeah, I found an easier method, with only 324 characters! This is it:
Code (Text):
class A{public static void main(String[]a){int b=0;while(a[b].matches("^[a-zA-Z]*\$"))b++;b--;int d=b+1;float c=Float.valueOf(a[d]);do{d++;c=a(a[b],c,Float.valueOf(a[d]));b--;}while(b>=0);System.out.println(c);}static float a(String a,float b,float c){return a.equals("add")?b+c:a.equals("sub")?b-c:a.equals("mul")?b*c:b/c;}}
The whole code with spaces:
Code (Text):
class A {
public static void main(String[] a) {
int b = 0;
while(a[b].matches("^[a-zA-Z]*\$"))
b++;
b--;
int d = b + 1;
float c = Float.valueOf(a[d]);
do {
d++;
c = a(a[b], c, Float.valueOf(a[d]));
b--;
} while (b >= 0);
System.out.println(c);
}

static float a(String a, float b, float c) {
return a.equals("add") ? b + c : a.equals("sub") ? b - c : a.equals("mul") ? b * c : b / c;
}
}

16. A lot of posting, but I found a shorter way. I won't rest 'till it fits in a Twitter message . It's now only 282 characters. But aside of that here it is:
Code (Text):
class A{public static void main(String[]a){int b=0;while(a[b].matches("^[a-zA-Z]*\$"))b++;b--;int d=b+1;float c=Float.valueOf(a[d]);do{d++;float e=Float.valueOf(a[d]);c=a[b].equals("add")?c+e:a[b].equals("sub")?c-e:a[b].equals("mul")?c*e:c/e;b--;}while(b>=0);System.out.println(c);}}
Here is it again with spaces:
Code (Text):
class A {
public static void main(String[] a) {
int b = 0;
while(a[b].matches("^[a-zA-Z]*\$"))
b++;
b--;
int d = b + 1;
float c = Float.valueOf(a[d]);
do {
d++;
float e = Float.valueOf(a[d]);
c = a[b].equals("add") ? c + e : a[b].equals("sub") ? c - e : a[b].equals("mul") ? c * e : c / e;
b--;
} while(b >= 0);
System.out.println(c);
}
}

• Like x 1

No max!

18. ### glatteis

You don't have to declare static or the class. It could just begin with:
Code (Text):
double main(String[] a)
Keep in mind that I want a String, not an array of Strings! The method should also return an double or float, not print it.
EDIT: mul add 4 8 div 4 2 throws an exception

#18
Last edited: May 23, 2016
19. ### glatteis

mul add 4 8 div 4 2 returns 9, should return 24 D:

20. ### glatteis

mul add 4 8 div 4 2 returns 8, should return 24 D: