optimization

This commit is contained in:
zeroflag 2021-08-08 11:03:13 +02:00
parent 4373200e6a
commit f6de8fd687
7 changed files with 91 additions and 28 deletions

View file

@ -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);

View file

@ -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);
}
}
}

View file

@ -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);
}

View file

@ -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;

View file

@ -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());

View file

@ -48,3 +48,9 @@ var: irr-guess 0 irr-guess !
nil ;
: 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 ;

View file

@ -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) {