【问题标题】:Algorithm to find combinations of integers and any operand to obtain a fixed result查找整数和任何操作数的组合以获得固定结果的算法
【发布时间】:2015-11-02 18:29:32
【问题描述】:

我正在编写一个程序,它以 4 个数字作为输入,然后尝试查看四个数字的加减除法和乘法的组合是否可以使它们等于 24。我的方法是为每个可能的组合创建一个方法四个数字和四个操作数,有点冗长。这是 2 种方法的示例。

public static boolean add(int a, int b, int c, int d) {
    boolean adBool;
    adBool = a + b + c + d == 24;
    return adBool;
}

public static boolean sub1(int a, int b, int c, int d) {
    boolean subBool1;
    subBool1 = a - b - c - d == 24;
    return subBool1;
}

然后在我的 Main 中,我确实为每个方法创建了一个 while 循环,如果该方法返回 true,将打印它停止的方法是解决方案。这是一个例子。

while (add(num1, num2, num3, num4)) {
    System.out.println("Your solution is "
            + num1 + " + " + num2 + " + " + num3 + " + " + num4
            + " = 24\nCongratulations!");
    break;

}
while (sub1(num1, num2, num3, num4)) {
    System.out.println("Your solution is "
            + num1 + " - " + num2 + " - " + num3 + " - " + num4
            + " = 24\nCongratulations!");
    break;
}

有没有办法存储像 + 和 - 这样的操作数,这样我就可以将它们放在一个数组中,然后使用一些嵌套的 for 循环来编写它?

【问题讨论】:

  • 您不一定需要单独的减法新方法。您可以使用与加法​​相同的方法,但改为发送负值。
  • 它变得更复杂了我认为这不会节省我很多时间,因为我有加减除法相结合的方法
  • 您应该能够将所有 4 种方法的逻辑放在一个方法中。
  • 你需要找到所有的组合还是一个就足够了?
  • 你是如何处理操作顺序的?您是否需要担心这 4 个数字的关联性?

标签: java algorithm math


【解决方案1】:

假设操作数是固定的,您可以创建一个生成器来转储可能的操作符,并将它们传递给评估器以确定它们是否为真。

while (generator.hasNext()){
    Operators ops = generator.getNext();
    if evaluatesTo(operand1, operand2, operand3, operand4, 24, ops){
       // print it
    }
}

一个简单的生成器可以这样完成:

List<String> list = new ArrayList<String>();
list.add("+++");
list.add("++-");
...
Iterator generator = list.iterator();

其中生成器实现了 java.util.Iterator 接口,该接口使用所有运算符 (+-*/) 进行初始化并转储出所有大小为 3 的排列。

evalutesTo 方法只是简单地计算它:

public boolean (int operand1, int operand2, int operand3, int operand4, int total, Operators ops ){
    // calculate operand1 "ops.get(0)" operand2 "ops.get(1)" operand3 "ops.get(2)" operand4  == total
}

所以如果 ops 是 [+-/] 它会检查

if (operand1 + operand2 - operand3 / operand4 == 24) return true;

我应该补充一下,您以后可以添加各种效率,但您的问题是如何通过更好的策略来做到这一点。其他用户的详细信息有一些 cmet,但我现在不担心。首先你需要设置这种框架,然后你可以担心细节。最关键的是,您不需要制作 100 种相似的外观方法。

【讨论】:

  • evaluatesTo 方法在哪里?我在哪里传递运算符?这一切将如何安排?
  • 另外,导入Java.util.Iterator后我的IDE找不到生成器
  • 你必须实现生成器。
  • 我还是 java 新手,所以你能多解释一下每个步骤吗,我真的不想让任何人为我做这件事(没有理由,这不是任务,它纯粹是教育),但我不明白该怎么做。
【解决方案2】:

我为你做了一些挖掘工作。
我发现 this stackexchange question 正在讨论如何为给定的字符集创建所有可能的组合。您可以使用问题中描述的方法来生成所有可能的 +,-,/,* 组合。

public static void combinations(int maxLength, char[] alphabet, String curr) {
  // If the current string has reached it's maximum length
  if (curr.length() == maxLength) {
    System.out.println(curr);

    // Else add each letter from the alphabet to new
    // strings and process these new strings again
  } else {
    for (int i = 0; i < alphabet.length; i++) {
      String oldCurr = curr;
      curr += alphabet[i];
      combinations(maxLength, alphabet, curr);
      curr = oldCurr;
    }
  }
}

并用类似的东西调用它

char[] operators = new char[]{'+', '-', '/', '*'};
// You want to call it with 3 since you only need 3 operators.
combinations(3, operators , "");

在(或代替)打印出新组合 (System.out.println(curr);) 之后,您可以调用一个方法来解释输出。
您可以使用类似于 stackoverflow simple calculator example 的内容。
例如,你可以有类似的东西:

if (curr.charAt(0) == '+') {
  //add the first and second number
}

我认为这应该足以让你继续前进。


我手头有时间,想完成这个,因为我觉得它很有趣。给你。这完全符合您的需要。

import java.util.Random;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

public class Blah {
  public static void main(String[] args) throws ScriptException {
    char[] operators = new char[]{'+', '-', '/', '*'};
    combinations(3, operators, "");
  }

  public static void combinations(
        int maxLength, char[] alphabet, String curr)
        throws ScriptException {
    // If the current string has reached it's maximum length
    if (curr.length() == maxLength) {
      System.out.println(curr);
      calculate(curr);

      // Else add each letter from the alphabet to new
      // strings and process these new strings again
    } else {
      for (int i = 0; i < alphabet.length; i++) {
        String oldCurr = curr;
        curr += alphabet[i];
        combinations(maxLength, alphabet, curr);
        curr = oldCurr;
      }
    }
  }

  private static void calculate(String operators) throws ScriptException {
    int operand1, operand2, operand3, operand4;
    Random randGen = new Random();
    ScriptEngineManager mgr = new ScriptEngineManager();
    ScriptEngine engine = mgr.getEngineByName("JavaScript");

    int result = 0;
    String operation = ""; // this will hold all the operands and operators
    while (result != 20) {
      operand1 = randGen.nextInt(101);
      operand2 = randGen.nextInt(101);
      operand3 = randGen.nextInt(101);
      operand4 = randGen.nextInt(101);
      // So here is where it got a bit tricky
      // and you can go different ways about this.
      // I went the easy way and used the built-in Javascript engine.
      operation = String.valueOf(operand1) + operators.charAt(0)
              + String.valueOf(operand2) + operators.charAt(1)
              + String.valueOf(operand3) + operators.charAt(2)
              + String.valueOf(operand4);
      // System.out.println(operation);
      result = (int) Double.parseDouble(engine.eval(operation).toString());
    }
    System.out.println(operation + "= 20");
  }
}

为了有趣,我使用了随机数。不知道你是如何得到你的数字输入的。要记住的一件事是,在处理整数时,小数会在除法中被删除。所以像 12/64 = 0 或 11/5=2。
这是一个示例输出:

run:
+++
0+0+10+10= 20
++-
59+3+38-80= 20
++/
19+0+66/53= 20
++*
15+5+0*54= 20
+-+
23+26-97+68= 20
+--
87+66-73-60= 20
+-/
15+5-0/33= 20
+-*
63+57-50*2= 20
+/+
8+61/37+11= 20
+/-
72+38/55-52= 20
+//
20+61/71/8= 20
+/*
18+5/28*14= 20
+*+
2+0*14+18= 20
+*-
35+1*75-90= 20
+*/
20+8*5/54= 20
+**
20+91*0*2= 20
-++
37-100+17+66= 20
-+-
65-89+46-2= 20
-+/
52-32+33/84= 20
-+*
52-32+44*0= 20
--+
39-74-22+77= 20
---
92-0-54-18= 20
--/
62-41-45/73= 20
--*
54-34-0*82= 20
-/+
22-98/9+9= 20
-/-
66-27/71-45= 20
-//
20-0/17/41= 20
-/*
42-20/71*76= 20
-*+
9-2*0+11= 20
-*-
90-6*10-10= 20
-*/
40-75*24/90= 20
-**
20-0*26*90= 20
/++
65/47+6+13= 20
/+-
91/5+56-54= 20
/+/
64/4+69/16= 20
/+*
54/81+2*10= 20
/-+
80/89-68+88= 20
/--
65/2-11-1= 20
/-/
86/4-96/98= 20
/-*
80/4-0*100= 20
//+
12/64/57+20= 20
//-
64/1/1-44= 20
///
82/1/4/1= 20
//*
45/7/18*57= 20
/*+
45/12*4+5= 20
/*-
44/21*45-74= 20
/*/
87/6*55/38= 20
/**
29/76*5*11= 20
*++
0*36+3+17= 20
*+-
4*13+55-87= 20
*+/
2*10+14/72= 20
*+*
0*100+2*10= 20
*-+
49*1-29+0= 20
*--
48*2-54-22= 20
*-/
1*21-11/73= 20
*-*
44*52-27*84= 20
*/+
7*8/56+19= 20
*/-
38*77/55-33= 20
*//
95*99/6/77= 20
*/*
2*9/72*83= 20
**+
0*11*40+20= 20
**-
8*6*1-28= 20
**/
29*59*1/82= 20
***
4*1*5*1= 20
BUILD SUCCESSFUL (total time: 34 minutes 35 seconds)

由于有 100 个随机整数上限,因此需要 34 分钟才能完成运行,因为 /// 和 *** 等非常棘手的问题。此外,我没有费心让它尽可能干净/高效,也没有注意对象泄漏/不必要的对象创建。这将取决于您。

【讨论】:

  • 它超级慢,因为您正在修改字符串,然后每次解析字符串并评估。仅存储运算符效率更高
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-15
相关资源
最近更新 更多