我正在尝试生成所有可能的方程式给定一个运算符的String数组(+, - ,*,/)和一个String变量数组(a,b,c ...)。每个等式将由变量和数字对(a + b-c / b)组成,除了最后一个变量,它没有跟随它的运算符。该算法必须生成可变长度的方程(2个项,6个项等)。在Java中生成此列表的最有效方法是什么?
请不要递归。 :)
嗯,不,这不是功课。这是一个个人项目,我正在尝试利用遗传算法找到最佳方程来拟合数据。如果您这么认为,对一般算术的描述就足够了。答案 0 :(得分:1)
既然你说它不是家庭作业,而且我是一个信任的人......
通过针对operator array =>运行每个变量来构建一个新的变量 - 运算符组合数组[“a +”,“a - ”,“a *”,“a /”,“b +”......“d /”]。我们称之为BuiltArray1
针对运算符运行此数组,输出每个运算符并将每个数组存储在新数组中=> [“a + a”,“a + b”,“a + c”,“a + d”,“a-a”......“d / d”]。我们称之为BuiltArray2。我们现在可以删除原始变量数组[“a”,“b”,“c”,“d”] - 我们不会再使用它了。
现在事情变得更有趣了......现在我们正在构建BuiltArray3。针对BuiltArray2中的每个项目运行BuiltArray1中的每个项目,输出每个项目并将其存储在BuiltArray3 =>中。 [“a + a + a”,“a-a + a”,“a * a + a”,“a / a + a”,“b + a + a”......“d / d / d” ]。我们现在可以删除BuiltArray2以节省一些内存(这将开始快速消耗内存!)
对于BuiltArray4,直到我们的计算机在它可以处理的最后一个BuiltArray_n上尖叫,我们在BuiltArray1中针对先前构建的阵列运行每个项目,输出并将每个结果存储在新阵列中,然后删除前一个阵列。
这将扼杀记忆和处理能力,但我无法想到任何更优雅的东西。
希望它有所帮助。
这是Ruby codez:
@arr1 = ["a", "b", "c", "d"]
arr2 = ["+", "-", "*", "/"]
@base = []
@arr1.each do |char|
arr2.each do |op|
@base << char + op
end
end
@right_vals = @arr1
loop do
@new_values = []
@base.each do |left|
@right_vals.each do |right|
val = left + right
puts val
@new_values << val
end
end
@right_vals = @new_values
end
答案 1 :(得分:1)
所以这是我提出的代码。我正在使用单个LinkedList来存储我生成的方程式。我生成所有可能的运算符和变量对,然后将它们附加到我已经生成的解决方案中以提出新的解决方案。有更好/更快的方法吗?
LinkedList<String> solutions = new LinkedList<String>();
//String[] vars and operators are initialized elsewhere.
int start = 0, end = solutions.size()-1;
//creating the first solutions
for(String s : vars)
solutions.add(s);
//precompute pairs of operators and variables
String[] pairs = new String[operators.length * vars.length];
for(int i=0, j=0; j<operators.length; j++)
for(int k=0; k<vars.length; k++)
{
pairs[i++]= operators[j]+vars[k];
}
//while the the terms in equations is under maximum
while(solutions.get(solutions.size()-1).split("[+/*-]").length<4)
{
for(int i=start; i<end; i++)
{
String soln = solutions.get(i);
for(int j=0; j<pairs.length; j++)
{
solutions.add(soln+pairs[j]);
}
}
start = end +1;
end = solutions.size()-1;
}
答案 2 :(得分:0)
既然我也认为这可能是家庭作业,我不会用任何语言给你代码,但是......
你可以有两个嵌套循环,一个循环遍历数组一,另一个循环遍历数组二。
你会看到每个组合的索引都将通过内循环,你可以在那里进行数学运算。
答案 3 :(得分:0)
这不是Java,而是递归,但Haskell解决方案看起来像这样:
permuteEquations :: Int -> [String] -> [String] -> [String]
permuteEquations 1 vars _ = vars
permuteEquations n vars ops =
[v ++ t1 | t1 <- [o ++ t2 | t2 <- permuteEquations (n-1) vars ops, o <- ops],
v <- vars]
这会生成包含 n 变量的所有可能方程式。
或者,如果你想要一个以一个变量的方程式(即变量列表)开头的版本,然后一直到 n 变量,那么它是:
permuteEquations1 :: Int -> [String] -> [String] -> [String]
permuteEquations1 0 _ _ = []
permuteEquations1 n vars ops =
[v ++ t1 | t1 <- "" : [o ++ t2 | t2 <- permuteEquations1 (n-1) vars ops,
o <- ops],
v <- vars]
由于延迟评估,这些函数在恒定空间中运行,如果您生成数十亿个方程式,这将非常方便。有谁知道你会用Java做到这一点? (我确信它可能,我只是好奇看它的样子)。
实际上,由于懒惰的评估,您可以摆脱 n 术语并生成一个无限列表,客户端会截断它所需的任何长度。
permuteEquations2 :: [String] -> [String] -> [String]
permuteEquations2 vars ops =
[v ++ t1 | t1 <- "" : [o ++ t2 | t2 <- permuteEquations2 vars ops, o <- ops],
v <- vars]
答案 4 :(得分:0)
运行时间随着变量的数量呈指数增长。这是另一种方法。
import java.util.List;
import java.util.ArrayList;
public class Equations {
public static void main(String[] args) {
String[] operators = "+ - * / %".split(" ");
String[] variables = "a b c d e f g".split(" ");
printAllPermutations(operators, variables);
}
private static void printAllPermutations(String[] operators, String[] variables) {
if (variables.length >= 31)
throw new IllegalArgumentException("Need to use BigInteger to support such a large number variables.length="+variables.length);
int permuations = 1 << variables.length;
for(int p=1;p<permuations;p++) {
List<String> variableList = new ArrayList<String>();
int p2 = p;
for (String variable : variables) {
if ((p2 & 1) != 0)
variableList.add(variable);
p2 /= 2;
}
printPermutations(operators, variableList.toArray(new String[variableList.size()]));
}
}
private static void printPermutations(String[] operators, String[] variables) {
long permutations = 1;
// more accurate than Math.pow.
for (int i = 0; i < variables.length-1; i++) {
String variable = variables[i];
permutations *= operators.length;
}
for(long p = 0; p < permutations;p++) {
long p2 = p;
for (int i = 0; i < variables.length-1; i++) {
System.out.print(variables[i]);
int oper = (int) (p2 % operators.length);
System.out.print(operators[oper]);
p2 /= operators.length;
}
System.out.println(variables[variables.length-1]);
}
}
}
答案 5 :(得分:0)
的Javascript 给定集合,第一个操作数,应该应用于第二组数字,然后我们用目标值评估生成的表达式。
var targetValue=10;
var set=[2,4,8,16,64];
//var ops=['+','-', '/', '*'];
var retArray=new Array();
function permutateSigns(operand, numbers, pos, epx){
var sum = 0;
if (pos == numbers.length-1) {
epx += numbers[pos];
//console.log(epx);
retArray.push(epx);
} else {
epx += (numbers[pos]) + operand;
permutateSigns('+', numbers, pos + 1, epx);
permutateSigns('-', numbers, pos + 1, epx);
permutateSigns('*', numbers, pos + 1, epx);
permutateSigns('/', numbers, pos + 1, epx);
}
}
permutateSigns('+',set,0,"");
var per=retArray;
console.log(per);
var validExpr;
for (var i = 0; i < retArray.length; i++) {
var result=eval(retArray[i]);
if(result===targetValue)
validExpr= retArray[i];
else
console.log(retArray[i] + ":" + eval(retArray[i]));
}
console.log("valid expression is:" + validExpr + "; value:"+ eval(validExpr) + "number of permutations is:"+ retArray.length);
答案 6 :(得分:-1)
我认为这与语言无关。这是家庭作业吗?这听起来像是家庭作业,所以我不会给你一个例子,但我会使用3个while
循环(虽然你可以很容易地使用for
循环,但我更喜欢使用while
或多个)。