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); 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); Primitive word = new Primitive(name, code);
word.immediate(immediate); word.immediate(immediate);
dict.add(word); dict.add(word);

View file

@ -1,19 +1,23 @@
package com.vectron.fcl; 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.Obj;
import com.vectron.fcl.types.Str;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.EmptyStackException;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.Stack;
public class Juggler { public class Juggler {
private final List<Obj> input; private final List<Obj> input;
private final List<Obj> output; private final List<Obj> output;
private final Stack<Obj> stack; private final LStack stack;
private final Stack<Obj> rstack; private final LStack rstack;
private final Set<Obj> uniqueOutput; private final Set<Obj> uniqueOutput;
private final List<Integer> code; private final List<Integer> code;
private final List<Word> availableWords; 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) { public static List<String> solve(List<Obj> input, List<Obj> output, Set<String> excluded, int maxSteps) {
Juggler juggler = new Juggler(input, output, excluded, maxSteps); Juggler juggler = new Juggler(input, output, excluded, maxSteps);
return juggler.solve(); return juggler.solve();
@ -64,8 +83,8 @@ public class Juggler {
this.output = output; this.output = output;
this.maxSteps = maxSteps; this.maxSteps = maxSteps;
this.uniqueOutput = new HashSet<>(output); this.uniqueOutput = new HashSet<>(output);
this.stack = new Stack<>(); this.stack = new LStack();
this.rstack = new Stack<>(); this.rstack = new LStack();
this.code = new ArrayList<>(); this.code = new ArrayList<>();
this.availableWords = populateWords(excluded); this.availableWords = populateWords(excluded);
this.code.add(0); this.code.add(0);
@ -98,8 +117,7 @@ public class Juggler {
while (code.get(i) > max) { while (code.get(i) > max) {
code.set(i, 0); code.set(i, 0);
if (i > 0) { if (i > 0) {
i--; code.set(--i, code.get(i) +1);
code.set(i, code.get(i) +1);
} else { } else {
code.add(0, 0); code.add(0, 0);
} }
@ -110,16 +128,16 @@ public class Juggler {
stack.clear(); stack.clear();
stack.addAll(input); stack.addAll(input);
rstack.clear(); rstack.clear();
List<Stack<Obj>> stackHistory = new ArrayList<>(); List<LStack> stackHistory = new ArrayList<>();
List<Stack<Obj>> rstackHistory = new ArrayList<>(); List<LStack> rstackHistory = new ArrayList<>();
for (int i = 0; i < code.size(); i++) { for (int i = 0; i < code.size(); i++) {
if (!nthWord(code.get(i)).eval(this) || nop() || cycle(stackHistory, rstackHistory)) { if (!nthWord(code.get(i)).eval(this) || nop() || cycle(stackHistory, rstackHistory)) {
skip(i, code); skip(i, code);
return false; return false;
} }
stackHistory.add(copy(stack)); stackHistory.add(new LStack(stack));
rstackHistory.add(copy(rstack)); rstackHistory.add(new LStack(rstack));
} }
return rstack.isEmpty() && stack.equals(output); 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++) { for (int i = 0; i < stackHistory.size(); i++) {
if (stackHistory.get(i).equals(stack) && rstackHistory.get(i).equals(rstack)) if (stackHistory.get(i).equals(stack) && rstackHistory.get(i).equals(rstack))
return true; return true;
@ -147,12 +165,6 @@ public class Juggler {
return rstack.isEmpty() && stack.equals(input); 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) { private List<String> result(List<Integer> code) {
List<String> result = new ArrayList<>(); List<String> result = new ArrayList<>();
for (Integer each : code) for (Integer each : code)
@ -165,7 +177,7 @@ public class Juggler {
} }
private boolean dup() { private boolean dup() {
if (stack.empty()) return false; if (stack.size() == 0) return false;
stack.push(pick(1)); stack.push(pick(1));
return true; return true;
} }
@ -185,7 +197,7 @@ public class Juggler {
} }
private boolean drop() { private boolean drop() {
if (stack.empty()) return false; if (stack.size() == 0) return false;
stack.pop(); stack.pop();
return !missing(); return !missing();
} }
@ -313,10 +325,38 @@ public class Juggler {
private boolean missing() { private boolean missing() {
for (Obj each : uniqueOutput) { for (Obj each : uniqueOutput) {
if (!stack.contains(each) && !stack.contains(each)) if (!stack.contains(each) && !rstack.contains(each))
return true; return true;
} }
return false; 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(); Obj receiver = stack.pop();
MethodSpec spec = MethodSpec.parseDynamic( MethodSpec spec = MethodSpec.parseDynamic(
methodName, methodName,
receiver instanceof JvmObj ? ((JvmObj) receiver).value() : receiver); receiver instanceof JvmObj ? receiver.value() : receiver);
spec.invoke(stack); spec.invoke(stack);
} }
@ -37,7 +37,7 @@ public class JvmInterOp {
Obj receiver = stack.pop(); Obj receiver = stack.pop();
MethodSpec spec = MethodSpec.parseDynamic( MethodSpec spec = MethodSpec.parseDynamic(
methodName, methodName,
receiver instanceof JvmObj ? ((JvmObj) receiver).value() : receiver); receiver instanceof JvmObj ? receiver.value() : receiver);
stack.push(spec.exists() ? Bool.TRUE : Bool.FALSE); 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.Bool;
import com.vectron.fcl.types.Dic; import com.vectron.fcl.types.Dic;
import com.vectron.fcl.types.JvmObj; import com.vectron.fcl.types.JvmObj;
import com.vectron.fcl.types.Lst;
import com.vectron.fcl.types.Nil; import com.vectron.fcl.types.Nil;
import com.vectron.fcl.types.Num; import com.vectron.fcl.types.Num;
import com.vectron.fcl.types.Obj; import com.vectron.fcl.types.Obj;
@ -115,6 +116,8 @@ class MethodSpec {
params.add(value.doubleValue()); params.add(value.doubleValue());
else if (clazz == String.class) else if (clazz == String.class)
params.add((String)value.value()); params.add((String)value.value());
else if (clazz == Lst.class)
params.add((Lst)value);
else if (clazz == Dic.class) else if (clazz == Dic.class)
params.add((Dic)value); params.add((Dic)value);
else if (clazz == Num.class) else if (clazz == Num.class)
@ -137,6 +140,7 @@ class MethodSpec {
case 's': return String.class; case 's': return String.class;
case 'm': return Map.class; case 'm': return Map.class;
case 't': return List.class; case 't': return List.class;
case 'T': return Lst.class;
case 'N': return Num.class; case 'N': return Num.class;
case 'O': return Obj.class; case 'O': return Obj.class;
case 'M': return Dic.class; case 'M': return Dic.class;

View file

@ -42,12 +42,12 @@ public class Lst implements Obj, ArithmeticOperand {
} }
@Override @Override
public Object value() { public List<Obj> value() {
return value; return value;
} }
@Override @Override
public Object unwrap() { public List<Object> unwrap() {
List<Object> result = new ArrayList<>(); List<Object> result = new ArrayList<>();
for (Obj each : value) for (Obj each : value)
result.add(each.unwrap()); result.add(each.unwrap());

View file

@ -47,4 +47,10 @@ var: irr-guess 0 irr-guess !
loop loop
nil ; 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 ;

View file

@ -19,6 +19,7 @@ import static org.junit.Assert.assertTrue;
public class JugglerTest { public class JugglerTest {
private final Set<String> excluded = new HashSet<>(); private final Set<String> excluded = new HashSet<>();
private int maxSteps = 5;
@Test @Test
public void testEmpty() { public void testEmpty() {
@ -148,8 +149,12 @@ public class JugglerTest {
@Test @Test
public void testComplex4() { 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"); assertSolution("swap 2over drop 2swap nip", "0 1 2 3", "0 2 0 3");
excluded.remove("over");
excluded.add("2over"); excluded.add("2over");
excluded.add("nip");
assertSolution("rot drop >r over r>", "0 1 2 3", "0 2 0 3"); 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"); 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) { 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) { private void assertSolution(String expected, String input, String output) {