【问题标题】:Java: Generator of true's & false's combinations by giving the number N;Java:通过给出数字 N 来生成真假组合;
【发布时间】:2012-06-11 00:32:53
【问题描述】:

我尽可能简化任务,所以我可以将它应用到我的算法中。

这是数学家和程序员面临的挑战:

我需要创建一个传递参数 int n 的方法:

public void optionality_generator(int n){
  //some kind of loops, or recursions...to make it workable
  System.out.println("current combination: ...");
}

输出应显示真假的所有可能组合。

这里是 N=1 的例子; N=2; N=3; N=4; N=5,其中 x=false,0=true;请注意,空折线只是为了让您更容易识别模式。希望我包括了所有可能的组合):

Combination of 1:
0
x

Combination of 2:
00
x0
0x
xx

Combination of 3:
000
X00
0X0
00X
XX0
0XX
XXX

Combination of 4:
0000

X000
0X00
00X0
000X

XX00
X0X0
X00X

0XX0
0X0X

00XX

XXX0
XX0X
X0XX
0XXX

XXXX

Combination of 5:
00000
X0000
0X000
00X00
000X0
0000X

XX000
X0X00
X00X0
X000X

X0X00
X00X0
X000X

0XX00
0X0X0
0X00X

00XX0
00X0X

000XX

XXX00
XX0X0
XX00X

X0XX0
X0X0X
X00XX

0XXX0
0XX0X

00XXX

XXXX0
XXX0X
XX0XX
X0XXX
0XXXX

XXXXX

另外,如果您看到输出,这是我识别的模式,所有组合都反转了一半(例如,第一个组合是 00000,最后一个是 XXXXX,第二个是 X0000,最后一个之前的一个是 0XXXX 等..)。也许,这种模式将有助于使整个算法更高效,对此不确定。 提前谢谢!

【问题讨论】:

  • 这就是为什么每个人都应该先学习汇编!或者至少有点数学和二进制补码。

标签: java recursion boolean generator combinations


【解决方案1】:

这是一种仅使用 Java API 的非常基本的方法:

final int n = 3;
for (int i = 0; i < Math.pow(2, n); i++) {
    String bin = Integer.toBinaryString(i);
    while (bin.length() < n)
        bin = "0" + bin;
    System.out.println(bin);
}

结果:

000
001
010
011
100
101
110
111

当然,您可以将n 设置为您喜欢的任何值。而且,有了这个结果,您可以从字符串中选择nth 字符作为真/假。

如果只需要检查某个位是否为真,则不需要将其转换为字符串。这只是为了说明输出值。

【讨论】:

  • 如果 int n = 5,您的代码将失败,因为 2^5 = 32 大于 n*n,也许使用 Math.pow(2,n);代替?
  • 我已经更新了我的代码...我的大脑将 n^2 与 2^n 混淆了!谢谢!
【解决方案2】:

只是一个线索,但请考虑为最多具有“n”位的数字设置的位。你会看到你是否从 0 到 'n' 位数(在这种情况下为 3);这些位是 000, 001, 010, 011, 100, 101, 110, 111。您可以使用 ((n*n)-1) 公式计算出可以放入“n”位的最大数量。

【讨论】:

    【解决方案3】:

    这应该可以解决问题

    int cols = 3;
    int rows = (int) Math.pow(2, cols);
    for (int row = 0; row < rows; row++)
        System.out.println(String.format("%" + cols + "s", 
                Integer.toBinaryString(row)).replace(' ', '0').replace('1', 'X'));
    

    出来:

    000
    00X
    0X0
    0XX
    X00
    X0X
    XX0
    XXX
    

    【讨论】:

    • 有点可惜String.format不支持%0s格式,而C/C++支持。
    【解决方案4】:

    使用递归并不像使用 Java Integer.toBinaryString() API 生成二进制字符串那么容易。但是下面的代码使您可以灵活地生成任何基本表示,例如基地3: “000” “001” “002” “010” “011” “012”

    对于 base 2(即二进制)字符串,您可以这样称呼它:

    getBinaryStrings(2, 3);
    

    对于 base 3 字符串,您可以这样称呼它:

    getBinaryStrings(3, 3);
    

    代码如下:

    public static List<String> getBinaryStrings(int base, int n){
        ArrayList<String> result = new ArrayList<>();
        getBinaryStringsCore(base, n, "", result);
        return result;
    }
    
    private static void getBinaryStringsCore(int base, int n, String tempString, List<String> result){
        if (tempString.length() == n) {
            result.add(tempString);
            return;
        }
    
        for (int i = 0; i < base; i++) {
            tempString += i;
            getBinaryStringsCore(base, n, tempString, result);
            tempString = tempString.substring(0, tempString.length() - 1);
        }
    }
    

    【讨论】:

    • base-2 和 base-3 字符串的代码是相同的(即getBinaryStrings(2, 3);)。这是故意的吗?
    • 感谢@entpnerd。我的用法描述中有错字。现在已更正。
    【解决方案5】:

    这是一个使用递归实现的简单版本

    public void optionality_generator(int n){
        ArrayList<String> strings = generatorHelper(n); 
        for(String s : strings){
            System.out.println(s);
        }
    }
    
    private ArrayList<String> generatorHelper(int n){
        if(n == 1){
            ArrayList<String> returnVal = new ArrayList<String>();
            returnVal.add("0");
            returnVal.add("X");
            return returnVal;
        }
        ArrayList<String> trueStrings = generatorHelper(n-1);
        for(String s : trueStrings){
            s += "0";
        }
        ArrayList<String> falseStrings = generatorHelper(n-1);
        for(String s : falseStrings){
            s += "X";
        }
        trueStrings.addAll(falseStrings);
        return trueStrings;
    }
    

    【讨论】:

    • 对其他人的注意:也许它有效,但输出格式不同,所有内容都在单列中,因此无法区分每个组合的开始位置和结束位置。无论如何,谢谢!
    【解决方案6】:

    这是一个测试驱动的版本:

    import static org.junit.Assert.assertEquals;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import org.junit.Test;
    
    public class OptionalityTest {
    
        @Test
        public void testOptionality0() throws Exception {
            assertEquals("[]", optionality(0).toString());
        }
    
        @Test
        public void testOptionality1() throws Exception {
            assertEquals("[0, x]", optionality(1).toString());
        }
    
        @Test
        public void testOptionality2() throws Exception {
            assertEquals("[00, x0, 0x, xx]", optionality(2).toString());
        }
    
        @Test
        public void testOptionality3() throws Exception {
            assertEquals("[000, x00, 0x0, xx0, 00x, x0x, 0xx, xxx]", optionality(3).toString());
        }
    
        private List<String> optionality(int i) {
            final ArrayList<String> list = new ArrayList<String>();
            if (i == 1) {
                list.add("0");
                list.add("x");
            }
            if (i > 1) {
                List<String> sublist = optionality(i - 1);
                for (String s : sublist) {
                    list.add("0" + s);
                    list.add("x" + s);
                }
            }
            return list;
        }
    
    }
    

    【讨论】:

      【解决方案7】:

      这是对上述 Erics 代码的修改,它使用 c# 并允许输入任意数量的布尔变量名称。它将在 c# 代码中输出所有可能的组合,以便插入到 if 语句中。只需使用 var 名称编辑第一行代码,然后在 LINQpad 中运行以获取文本输出。

      输出示例...

      !VariableNameA && !VariableNameB && !VariableNameC 
      !VariableNameA && !VariableNameB &&  VariableNameC 
      !VariableNameA &&  VariableNameB && !VariableNameC 
      !VariableNameA &&  VariableNameB &&  VariableNameC 
       VariableNameA && !VariableNameB && !VariableNameC 
       VariableNameA && !VariableNameB &&  VariableNameC 
       VariableNameA &&  VariableNameB && !VariableNameC 
       VariableNameA &&  VariableNameB &&  VariableNameC 
      

          //To setup edit var names below
          string[] varNames = { "VariableNameA", "VariableNameB", "VariableNameC" };
      
          int n = varNames.Count();        
          for (int i = 0; i < Math.Pow(2, n); i++) {
            String bin = Convert.ToString(i, 2);
            while (bin.Length < n) {
                bin = "0" + bin;
            }        
            string and = " && ";
            string f = "!";
            string t = " ";
            var currentNot = bin[0] == '0' ? f : t;
            //string visual = bin[0].ToString();
            string visual = currentNot + varNames[0];
              for (var j = 1; j < n; j++) {
              currentNot = bin[j] == '0' ? f : t;
              //visual = visual + and + bin[j].ToString();
              visual = visual + and + currentNot + varNames[j];
            }		
            Console.WriteLine(visual);	
          }

      【讨论】:

        猜你喜欢
        • 2017-02-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多