Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/385.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何让我的程序存储81位BigInteger中55位的所有可能组合?_Java_Arrays_Sorting_Biginteger_Combinatorics - Fatal编程技术网

Java 如何让我的程序存储81位BigInteger中55位的所有可能组合?

Java 如何让我的程序存储81位BigInteger中55位的所有可能组合?,java,arrays,sorting,biginteger,combinatorics,Java,Arrays,Sorting,Biginteger,Combinatorics,我正在制作一个数独程序,我想把81位整数中x位的每一个组合存储到一个列表中。我希望能够洗牌这个列表,遍历它,每一个on位都代表一个要从现有数独网格中删除的单元格,x取决于难度。然后,我的程序测试这个独特的谜题,看看它是否可以解决,如果不能,继续下一个组合。你们明白吗?有更好的办法吗 目前,我有一个带有BigInteger的for循环,每次迭代加1,并测试结果数字的位数是否等于55。但这需要很长时间。我认为宇宙中没有足够的时间这样做 LOOP: for(BigInteger big = new

我正在制作一个数独程序,我想把81位整数中x位的每一个组合存储到一个列表中。我希望能够洗牌这个列表,遍历它,每一个on位都代表一个要从现有数独网格中删除的单元格,x取决于难度。然后,我的程序测试这个独特的谜题,看看它是否可以解决,如果不能,继续下一个组合。你们明白吗?有更好的办法吗

目前,我有一个带有BigInteger的for循环,每次迭代加1,并测试结果数字的位数是否等于55。但这需要很长时间。我认为宇宙中没有足够的时间这样做

  LOOP: for(BigInteger big = new BigInteger("36028797018963967"); 
            big.compareTo(new BigInteger("2417851639229258349412351")) < 0;
            big = big.add(big.ONE))
            {
               int count = 0;
               for(int i = 0; i < 81; i++)
               {
                  if(big.testBit(i)) count++;
                  if(count > 55) continue LOOP;
               }
               //just printing first, no arraylist yet
               if(count == 55) System.out.println(big.toString(2));
            }

当然,有些方法会在你年老死去之前完成。例如:


按照David Choweller在评论中的建议,创建一个数组或位集来表示位,并根据需要打开任意多个数组或位集,直到有足够的位为止。然后将其转换成一个大整数。

我感谢您的反馈。以下内容似乎比我最初的想法更好,因为我相信列出所有可能的组合肯定会导致内存不足错误。它不是完美的,但这个选项会取出一个随机单元,测试它是否可解,如果不将最后一个取出的数字放回去,然后继续移除下一个随机单元,直到取出足够的单元,或者重新开始

  int[] candidates = new int[81];
  SudokuGrid grid = new SudokuGrid();

  LOOP: while(true)
  {
     ArrayList<Integer> removals = new ArrayList<Integer>();
     for(int i = 0; i < 81; i++)
     {
        removals.add(i);
        candidates[i] = grid.get(i);
     }
     Collections.shuffle(removals);
     int k = 55;
     for(int i = 0; i < k; i++)
     {
        int num = candidates[removals.get(i)];
        candidates[removals.get(i)] = 0;
        cand = new Candidates(candidates);
        SudokuSolver solver = new SudokuSolver(cand);
        if(!resolveGrid(solver))
        {
           candidates[removals.get(i)] = num;
           k++;
           if(k > removals.size())
              continue LOOP;
        }
     }

     break;
  }

这大约需要5秒钟来解决。这比我希望的要慢一点,但很大程度上取决于我对解决策略的编码方式。

正如您已经注意到的,将所有组合存储在一个列表中,然后将它们洗牌是不可行的选择。 相反,您可以使用库获得所有组合的无序流

您可能不想生成给定难度的所有谜题,但只生成其中的一小部分。
您可以通过设置限制来实现这一点,请参见上面代码中的注释行。

我不确定这是否会提高速度,但您是否考虑过使用Java的位集类?它有一个基数方法,返回设置的位数。你要处理很多组合。为了更好地理解这一点,一个家伙运用聪明的推理,用一个程序证明16是解决这个难题所需的最小起始数字。他花了9个月的时间运行这个程序,至少是3.6028797e+16组合,对吗?不管你做什么,都要花很长时间。事实上,仔细阅读,他只完成了一个数独游戏,并且想要将x个位置变灰。那么是81 x?这仍然是一堆废话。你似乎是对的@pvg。稍后我会发布一个备选答案。如果有人想否决任何人,为什么不在评论中给他们一个解释或改进建议,谢谢。我同意这种看法。
import org.beryx.streamplify.combination.Combinations;
...
SudokuGrid grid = new SudokuGrid();
int[] solvedPuzzle = IntStream.range(0, 81).map(i -> grid.get(i)).toArray();
int k = 55;
new Combinations(81, k)
        .shuffle()
        .parallelStream()
        .map(removals -> {
            int[] puzzle = new int[81];
            System.arraycopy(solvedPuzzle, 0, puzzle, 0, 81);
            for(int i : removals) {
                puzzle[i] = 0;
            }
            return puzzle;
        })
        .filter(puzzle -> resolveGrid(new SudokuSolver(new Candidates(puzzle))))
        //.limit(10)
        .forEach(puzzle -> System.out.println(Arrays.toString(puzzle)));