如何在Java中生成Collat​​z树?

时间:2016-08-25 19:40:03

标签: java collatz

我无可救药地试图在collat​​z序列中生成所有数字的无限循环。 该程序应该从一个开始并打印所有可能的collat​​z,直到用户停止,或者我们得到内存溢出。所以我们必须是一个反向collat​​z功能。 逻辑将是这样的:(如果n甚至是重复它,如果n / 3是整数,我们进行逆运算,奇数运算。)

import java.math.BigInteger;

public class InverseColatz {
    public static void main(String args[]) throws InterruptedException{
        BigInteger n = BigInteger.valueOf(2);
        System.out.println(1);
        while(true){
            if(n.mod(BigInteger.valueOf(3)).equals(BigInteger.ZERO)){
                n = n.divide(BigInteger.valueOf(3));
                n = n.subtract(BigInteger.ONE);
                System.out.println(n);
               Thread.sleep(500);
            }
            if(n.mod(BigInteger.valueOf(2)).equals(BigInteger.ZERO)) {
                n = n.multiply(BigInteger.valueOf(2));
                System.out.println(n);
                Thread.sleep(500);
            }
        } 
    }
}

问题是我只是生成偶数序列(n * 2),但我无法生成奇数((n / 3)-1),因为此代码永远不会达到奇数条件,因为生成的所有数字都与第一个条件不匹配。有人可以给我一些启示吗? 提前谢谢。

1 个答案:

答案 0 :(得分:0)

首先,请原谅我的格式,我不能用图像来显示方程式,因为这是我的第一篇文章。

让我们先来看看Collatz Conjecture。我们知道所涉及的系列被称为Halestone系列,参考所有数字2 n 的行为,其中n是正整数。系列的定义是根据值是奇数还是偶数来递归修改值。

  
      
  • 如果数字是偶数,则除以2。
  •   
  • 如果数字为奇数,则将其加倍并添加一个。
  •   

要扭转此过程,一个数字可能会有两个结果。例如,5和32都评估为16。

  
      
  • 5是奇数,(3 * 5)+ 1 = 16
  •   
  • 32是偶数,32/2 = 16
  •   

要找到反函数,我们需要考虑每个数字可以有两个答案。我们还需要定义一个有效的答案。反函数的有效答案必须为正整数。

现在我们做一些代数来得到反转。将 a 定义为Halestone系列的一次迭代的结果。

解决n:
名词
3n + 1 = a 2 = a

a - 1
n = 3 n = 2a

所以现在我们有了新的规则。我们知道 n = 2a 总会评估为正整数,因此该表达式始终为true。但是,如果 a - 1 可被3整除,则另一个等式仅计算为正整数。每个其他实例不会返回整数,而是会被追踪通过无限数量的三或六。这些十进制数是不可接受的,将被抛弃。注意4的输入值如何作为答案之一返回1

要开始考虑代码,我们应该将提议的树分解为多个层。与this image的水平分层相似。对于每次迭代,每个分支都有可能分成两个独立的分支。这意味着我们需要在迭代树时存储未知数量的数字。

这就是我想出的。从本质上讲,它仍然只是一个数据流,需要格式化为可读的东西。当堆栈大小用完或并发分支数超过2 31 时,它应该失败 - 这是由于数组的性质。

public static void main(String args[]) throws InterruptedException {
    ArrayList<BigInteger> tree = new ArrayList<BigInteger>();
    tree.add(BigInteger.valueOf(2));
    System.out.println(1);
    while (true) {
        // Store a snapshot of the current tree so new branches created don't mess with
        // the iteration process.
        BigInteger[] originalTree = tree.toArray(new BigInteger[tree.size()]);

        // Keep track of new branches added during each step for index alignment in
        // the stepping method.
        int newBranchCount = 0;

        // Iterate over the values of the original tree.
        for(int i = 0; i < originalTree.length; i++) {
            // Evaluate branch
            stepBranch(tree, originalTree[i], i + newBranchCount);

            // Update branch count after step.
            newBranchCount = tree.size() - originalTree.length;
        }
    }
}

/*
 * Given the tree to mutate, a value from a mutation free version of the tree,
 * and the current working index of the tree:
 * Evaluate whether or not to add a new odd valued branch and report new value(s).
*/
public static void stepBranch(ArrayList<BigInteger> tree, BigInteger branch, int index) throws InterruptedException {

    // If (n + 1) is divisible by three, do so and create a new branch to store the new value
    if (branch.subtract(BigInteger.ONE).mod(BigInteger.valueOf(3)).equals(BigInteger.ZERO)) {

        // If the input is 4, the output is 1 which appears earlier, therefore requires no attention.
        if(!branch.equals(BigInteger.valueOf(4))) {
            // Create new value. 
            BigInteger odd = branch.subtract(BigInteger.ONE).divide(BigInteger.valueOf(3));

            // If the output is even, it doesn't fit the requirements for an odd cell.
            if(!odd.mod(BigInteger.valueOf(2)).equals(BigInteger.ZERO)) {
                tree.add(index + 1, odd);
                System.out.println(tree.get(index + 1));
            }
        } else {
            System.out.println(1);
        }
        Thread.sleep(500);
    }

    // The original branch, not considering a new branch if one was created, is
    // multiplied by 2 so as to check for a new odd node in the next iteration.
    tree.set(index, branch.multiply(BigInteger.valueOf(2)));
    System.out.println(tree.get(index));
    Thread.sleep(500);
}

希望这有帮助!