Skip to content

Instantly share code, notes, and snippets.

@taichi
Created September 6, 2012 09:59
Show Gist options
  • Save taichi/3654183 to your computer and use it in GitHub Desktop.
Save taichi/3654183 to your computer and use it in GitHub Desktop.
Simple Calculator
import java.util.Deque;
/**
* @author taichi
*/
public class StackMachine {
interface Op {
void execute(Deque<String> stack);
}
static abstract class UniOp implements Op {
@Override
public void execute(Deque<String> stack) {
stack.push(this.execute(stack.pop()));
}
abstract String execute(String value);
}
static abstract class BiOp implements Op {
@Override
public void execute(Deque<String> stack) {
stack.push(this.execute(stack.pop(), stack.pop()));
}
String execute(String l, String r) {
return String.valueOf(this.execute(Integer.parseInt(l),
Integer.parseInt(r)));
}
abstract int execute(int l, int r);
}
public Op to(final String v) {
switch (v) {
case "!":
return new UniOp() {
@Override
String execute(String value) {
long result = 1L;
for (int i = 1, v = Integer.parseInt(value); i <= v; i++) {
result *= i;
}
return String.valueOf(result);
}
};
case "+":
return new BiOp() {
@Override
int execute(int l, int r) {
return r + l;
}
};
case "-":
return new BiOp() {
@Override
int execute(int l, int r) {
return r - l;
}
};
case "*":
return new BiOp() {
@Override
int execute(int l, int r) {
return r * l;
}
};
case "/":
return new BiOp() {
@Override
int execute(int l, int r) {
return r / l;
}
};
default: // do nothing.
break;
}
return new Op() {
@Override
public void execute(Deque<String> stack) {
stack.push(v);
}
};
}
public String execute(String input) {
Deque<String> stack = new java.util.ArrayDeque<>();
for (String s : input.split("\\s")) {
this.to(s).execute(stack);
}
return stack.pop();
}
}
import static org.junit.Assert.assertEquals;
import java.util.Arrays;
import java.util.Collection;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
/**
* Junit4.11 is not released. use <a
* href="https://github.com/KentBeck/junit/downloads">snapshot</a>.
*
* @author taichi
* @see
* @see <a
* href="https://github.com/KentBeck/junit/commit/e0cddcdfa8ec823da136af500cce0910a1dd2264">Add
* names for parameterized tests. Fixes #24 and #44.</a>
*/
@RunWith(value = Parameterized.class)
public class StackMachineTest {
String input;
String expected;
StackMachine target;
public StackMachineTest(String input, String expected) {
this.input = input;
this.expected = expected;
}
// if you use Junit4.10 or less, remove name attribute.
@Parameters(name = "{0} -> {1}")
public static Collection<Object[]> data() {
Object[][] data = new Object[][] { //
{ "1", "1" }, //
{ "1 2 +", "3" }, //
{ "3 1 -", "2" }, //
{ "10 2 /", "5" }, //
{ "2 5 8 + +", "15" }, //
{ "2 5 8 + *", "26" }, //
{ "2 5 8 * +", "42" }, //
{ "1 2 + 3 4 + *", "21" }, //
{ "2 3 * 4 5 * +", "26" }, //
{ "3 ! !", "720" }, //
{ "4 1 - ! 1 + ! 56 /", "90" }, //
{ "0 !", "1" } };
return Arrays.asList(data);
}
@Before
public void setUp() {
this.target = new StackMachine();
}
@Test
public void test() {
assertEquals(this.expected, this.target.execute(this.input));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment