mirror of
https://github.com/zeroflag/fcl.git
synced 2025-01-11 20:01:10 +01:00
optimization
This commit is contained in:
parent
4373200e6a
commit
f6de8fd687
7 changed files with 91 additions and 28 deletions
|
@ -532,7 +532,7 @@ public class Fcl {
|
|||
addPrimitive(name, code, false);
|
||||
}
|
||||
|
||||
private void addPrimitive(String name, Runnable code, boolean immediate) {
|
||||
public void addPrimitive(String name, Runnable code, boolean immediate) {
|
||||
Primitive word = new Primitive(name, code);
|
||||
word.immediate(immediate);
|
||||
dict.add(word);
|
||||
|
|
|
@ -1,19 +1,23 @@
|
|||
package com.vectron.fcl;
|
||||
|
||||
import com.vectron.fcl.types.Lst;
|
||||
import com.vectron.fcl.types.Nil;
|
||||
import com.vectron.fcl.types.Obj;
|
||||
import com.vectron.fcl.types.Str;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.EmptyStackException;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
|
||||
public class Juggler {
|
||||
private final List<Obj> input;
|
||||
private final List<Obj> output;
|
||||
private final Stack<Obj> stack;
|
||||
private final Stack<Obj> rstack;
|
||||
private final LStack stack;
|
||||
private final LStack rstack;
|
||||
private final Set<Obj> uniqueOutput;
|
||||
private final List<Integer> code;
|
||||
private final List<Word> availableWords;
|
||||
|
@ -54,6 +58,21 @@ public class Juggler {
|
|||
}
|
||||
}
|
||||
|
||||
public static Obj solve(Lst input, Lst output, Lst excluded, int maxSteps) {
|
||||
List<String> words = solve(input.value(), output.value(), filter(excluded.value()), maxSteps);
|
||||
if (words == null) return Nil.INSTANCE;
|
||||
Lst result = new Lst();
|
||||
for (String each : words)
|
||||
result.append(new Str(each));
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Set<String> filter(List<Obj> excluded) {
|
||||
Set<String> result = new HashSet<>();
|
||||
for (Obj each : excluded) result.add(each.asStr().value());
|
||||
return result;
|
||||
}
|
||||
|
||||
public static List<String> solve(List<Obj> input, List<Obj> output, Set<String> excluded, int maxSteps) {
|
||||
Juggler juggler = new Juggler(input, output, excluded, maxSteps);
|
||||
return juggler.solve();
|
||||
|
@ -64,8 +83,8 @@ public class Juggler {
|
|||
this.output = output;
|
||||
this.maxSteps = maxSteps;
|
||||
this.uniqueOutput = new HashSet<>(output);
|
||||
this.stack = new Stack<>();
|
||||
this.rstack = new Stack<>();
|
||||
this.stack = new LStack();
|
||||
this.rstack = new LStack();
|
||||
this.code = new ArrayList<>();
|
||||
this.availableWords = populateWords(excluded);
|
||||
this.code.add(0);
|
||||
|
@ -98,8 +117,7 @@ public class Juggler {
|
|||
while (code.get(i) > max) {
|
||||
code.set(i, 0);
|
||||
if (i > 0) {
|
||||
i--;
|
||||
code.set(i, code.get(i) +1);
|
||||
code.set(--i, code.get(i) +1);
|
||||
} else {
|
||||
code.add(0, 0);
|
||||
}
|
||||
|
@ -110,16 +128,16 @@ public class Juggler {
|
|||
stack.clear();
|
||||
stack.addAll(input);
|
||||
rstack.clear();
|
||||
List<Stack<Obj>> stackHistory = new ArrayList<>();
|
||||
List<Stack<Obj>> rstackHistory = new ArrayList<>();
|
||||
List<LStack> stackHistory = new ArrayList<>();
|
||||
List<LStack> rstackHistory = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < code.size(); i++) {
|
||||
if (!nthWord(code.get(i)).eval(this) || nop() || cycle(stackHistory, rstackHistory)) {
|
||||
skip(i, code);
|
||||
return false;
|
||||
}
|
||||
stackHistory.add(copy(stack));
|
||||
rstackHistory.add(copy(rstack));
|
||||
stackHistory.add(new LStack(stack));
|
||||
rstackHistory.add(new LStack(rstack));
|
||||
}
|
||||
return rstack.isEmpty() && stack.equals(output);
|
||||
}
|
||||
|
@ -135,7 +153,7 @@ public class Juggler {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean cycle(List<Stack<Obj>> stackHistory, List<Stack<Obj>> rstackHistory) {
|
||||
private boolean cycle(List<LStack> stackHistory, List<LStack> rstackHistory) {
|
||||
for (int i = 0; i < stackHistory.size(); i++) {
|
||||
if (stackHistory.get(i).equals(stack) && rstackHistory.get(i).equals(rstack))
|
||||
return true;
|
||||
|
@ -147,12 +165,6 @@ public class Juggler {
|
|||
return rstack.isEmpty() && stack.equals(input);
|
||||
}
|
||||
|
||||
private Stack<Obj> copy(Stack<Obj> stack) {
|
||||
Stack<Obj> result = new Stack<>();
|
||||
result.addAll(stack);
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<String> result(List<Integer> code) {
|
||||
List<String> result = new ArrayList<>();
|
||||
for (Integer each : code)
|
||||
|
@ -165,7 +177,7 @@ public class Juggler {
|
|||
}
|
||||
|
||||
private boolean dup() {
|
||||
if (stack.empty()) return false;
|
||||
if (stack.size() == 0) return false;
|
||||
stack.push(pick(1));
|
||||
return true;
|
||||
}
|
||||
|
@ -185,7 +197,7 @@ public class Juggler {
|
|||
}
|
||||
|
||||
private boolean drop() {
|
||||
if (stack.empty()) return false;
|
||||
if (stack.size() == 0) return false;
|
||||
stack.pop();
|
||||
return !missing();
|
||||
}
|
||||
|
@ -313,10 +325,38 @@ public class Juggler {
|
|||
|
||||
private boolean missing() {
|
||||
for (Obj each : uniqueOutput) {
|
||||
if (!stack.contains(each) && !stack.contains(each))
|
||||
if (!stack.contains(each) && !rstack.contains(each))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public final class LStack extends ArrayList<Obj> {
|
||||
public LStack() {
|
||||
super(10);
|
||||
}
|
||||
|
||||
public LStack(final Collection<Obj> collection) {
|
||||
super(collection);
|
||||
}
|
||||
|
||||
public void push(Obj item) {
|
||||
add(item);
|
||||
}
|
||||
|
||||
public Obj pop() {
|
||||
Obj top = peek();
|
||||
remove(size() - 1);
|
||||
return top;
|
||||
}
|
||||
|
||||
public Obj peek() {
|
||||
int size = size();
|
||||
if (size == 0) {
|
||||
throw new EmptyStackException();
|
||||
}
|
||||
return get(size - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ public class JvmInterOp {
|
|||
Obj receiver = stack.pop();
|
||||
MethodSpec spec = MethodSpec.parseDynamic(
|
||||
methodName,
|
||||
receiver instanceof JvmObj ? ((JvmObj) receiver).value() : receiver);
|
||||
receiver instanceof JvmObj ? receiver.value() : receiver);
|
||||
spec.invoke(stack);
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ public class JvmInterOp {
|
|||
Obj receiver = stack.pop();
|
||||
MethodSpec spec = MethodSpec.parseDynamic(
|
||||
methodName,
|
||||
receiver instanceof JvmObj ? ((JvmObj) receiver).value() : receiver);
|
||||
receiver instanceof JvmObj ? receiver.value() : receiver);
|
||||
stack.push(spec.exists() ? Bool.TRUE : Bool.FALSE);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import com.vectron.fcl.exceptions.InterOpFailed;
|
|||
import com.vectron.fcl.types.Bool;
|
||||
import com.vectron.fcl.types.Dic;
|
||||
import com.vectron.fcl.types.JvmObj;
|
||||
import com.vectron.fcl.types.Lst;
|
||||
import com.vectron.fcl.types.Nil;
|
||||
import com.vectron.fcl.types.Num;
|
||||
import com.vectron.fcl.types.Obj;
|
||||
|
@ -115,6 +116,8 @@ class MethodSpec {
|
|||
params.add(value.doubleValue());
|
||||
else if (clazz == String.class)
|
||||
params.add((String)value.value());
|
||||
else if (clazz == Lst.class)
|
||||
params.add((Lst)value);
|
||||
else if (clazz == Dic.class)
|
||||
params.add((Dic)value);
|
||||
else if (clazz == Num.class)
|
||||
|
@ -137,6 +140,7 @@ class MethodSpec {
|
|||
case 's': return String.class;
|
||||
case 'm': return Map.class;
|
||||
case 't': return List.class;
|
||||
case 'T': return Lst.class;
|
||||
case 'N': return Num.class;
|
||||
case 'O': return Obj.class;
|
||||
case 'M': return Dic.class;
|
||||
|
|
|
@ -42,12 +42,12 @@ public class Lst implements Obj, ArithmeticOperand {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object value() {
|
||||
public List<Obj> value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object unwrap() {
|
||||
public List<Object> unwrap() {
|
||||
List<Object> result = new ArrayList<>();
|
||||
for (Obj each : value)
|
||||
result.add(each.unwrap());
|
||||
|
|
|
@ -47,4 +47,10 @@ var: irr-guess 0 irr-guess !
|
|||
loop
|
||||
nil ;
|
||||
|
||||
: irr* ( cashflow -- n ) list* irr ;
|
||||
: irr* ( cashflow -- n ) list* irr ;
|
||||
|
||||
var: juggler.steps 5 juggler.steps !
|
||||
[ ] val: juggler.exclude
|
||||
|
||||
: juggler.solve ( steps exclude-list output-list input-list -- list/nil ) :com.vectron.fcl.Juggler/solve/TTTi jvm-call-static ;
|
||||
: wzd* ( stack1 stack2 -- list/nil ) list* exchange list* aux> juggler.steps @ juggler.exclude 2swap juggler.solve ;
|
|
@ -19,6 +19,7 @@ import static org.junit.Assert.assertTrue;
|
|||
|
||||
public class JugglerTest {
|
||||
private final Set<String> excluded = new HashSet<>();
|
||||
private int maxSteps = 5;
|
||||
|
||||
@Test
|
||||
public void testEmpty() {
|
||||
|
@ -148,8 +149,12 @@ public class JugglerTest {
|
|||
|
||||
@Test
|
||||
public void testComplex4() {
|
||||
assertSolution(">r nip over r>", "0 1 2 3", "0 2 0 3");
|
||||
excluded.add("over");
|
||||
assertSolution("swap 2over drop 2swap nip", "0 1 2 3", "0 2 0 3");
|
||||
excluded.remove("over");
|
||||
excluded.add("2over");
|
||||
excluded.add("nip");
|
||||
assertSolution("rot drop >r over r>", "0 1 2 3", "0 2 0 3");
|
||||
}
|
||||
|
||||
|
@ -178,8 +183,16 @@ public class JugglerTest {
|
|||
assertSolution(null, "0 1 2 3 4 5", "0 0 2 1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoSolution2() {
|
||||
maxSteps = 6;
|
||||
long started = System.currentTimeMillis();
|
||||
assertSolution(null, "0 1 2 3 4 5 6 7 8", "10");
|
||||
System.out.println(System.currentTimeMillis() - started);
|
||||
}
|
||||
|
||||
private List<String> solve(List<Obj> input, List<Obj> output) {
|
||||
return Juggler.solve(input, output, excluded, 5);
|
||||
return Juggler.solve(input, output, excluded, maxSteps);
|
||||
}
|
||||
|
||||
private void assertSolution(String expected, String input, String output) {
|
||||
|
|
Loading…
Reference in a new issue