【问题标题】:recursion resulting in extra unwanted data递归导致额外的不需要的数据
【发布时间】:2011-02-28 19:46:34
【问题描述】:

我正在编写一个模块来处理掷骰子。给定 x y 边的骰子,我正在尝试列出所有可能的掷骰组合。

此代码假设有 3 个骰子,每个骰子有 3 个面,分别标记为 1、2 和 3。(我意识到我使用的是“幻数”,但这只是为了简化并让基本代码正常工作。)

        int[] set = { 1, 1, 1 };
        list = diceroll.recurse(0,0, list, set);

...

    public ArrayList<Integer> recurse(int index, int i, ArrayList<Integer> list, int[] set){
        if(index < 3){
//          System.out.print("\n(looping on "+index+")\n");
            for(int k=1;k<=3;k++){
//              System.out.print("setting i"+index+" to "+k+" ");
                set[index] = k;
                dump(set);
                recurse(index+1, i, list, set);
            }
        }
        return list;
    }

(dump() 是一个简单的方法,只显示list[]的内容。变量i暂时不用。)

我正在尝试做的是将 list[index] 增加一,逐步遍历列表的整个长度并随着我的前进而增加。

这是我的“最佳尝试”代码。这是输出:

粗体输出是我正在寻找的。我不知道如何摆脱其余的。 (这是假设三个骰子,每个骰子有 3 个面。使用递归,所以我可以将它扩展到任何具有 y 面的 x 骰子。)

[1][1][1] [1][1][1]

[1][1][1] [1][1][2] [1][1][3] [1][2][3]

[1][2][1] [1][2][2] [1][2][3] [1][3][3]

[1][3][1] [1][3][2] [1][3][3] [2][3][3] [2][ 1][3]

[2][1][1] [2][1][2] [2][1][3] [2][2][3]

[2][2][1] [2][2][2] [2][2][3] [2][3][3]

[2][3][1] [2][3][2] [2][3][3] [3][3][3] [3][ 1][3]

[3][1][1] [3][1][2] [3][1][3] [3][2][3]

[3][2][1] [3][2][2] [3][2][3] [3][3][3]

[3][3][1] [3][3][2] [3][3][3]

我为格式道歉,我能想到的最好的。

任何帮助将不胜感激。 (这种方法实际上是为了将数据用于非常琐碎的事情,但已经变成了个人挑战。:)

编辑:如果有其他方法可以解决这个问题,我会全力以赴,但我也想解决我当前的问题,并成功地将递归用于有用的东西。

编辑2: 运行代码,包括“简单修复”。当心未使用的变量和奇怪的 hack,我还没有清理它。

package code.testing;

import java.util.ArrayList;

public class CodeTesting {

    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<Integer>();
        int[] set = { 1, 1, 1 };
        list = recurse(0,0, list, set);
    }

    public static ArrayList<Integer> recurse(int index, int i, ArrayList<Integer> list, int[] set){
        if(index < 3){
//          System.out.print("\n(looping on "+index+")\n");
            for(int k=1;k<=3;k++){
//              System.out.print("setting i"+index+" to "+k+" ");
                set[index] = k;
                if (index==2){
                    dump(set);
                }
                recurse(index+1, i, list, set);
            }
        }
        return list;
    }

    static void dump(int[] arr) {
        for (int s : arr) {
            System.out.format("[%s]", s);
        }
        System.out.println();
    }
}

【问题讨论】:

    标签: java recursion dice


    【解决方案1】:

    仅在index == 2 时调用dump()

    顺便说一句,ilist 似乎未使用。动词是“recur”。 :)

    【讨论】:

    • 效果很好。我花了一秒钟才弄清楚它为什么起作用。这似乎是一种偷偷摸摸的黑客行为。我将使用这个以及 polygenelubricants 的代码来进行一些很好的学习。谢谢!
    • 好吧,index == 2 确实是您的基本情况,关键是输出发生在递归的基本情况中。它应该是index == set.length-1 或其他东西,如果这就是你的意思,否则它是合适的。是的,您可以像在其他答案中一样重写代码,以使其表现得更好,以表明这实际上是您需要做的。
    【解决方案2】:

    很抱歉,我不得不重写代码,但它与您的算法几乎相同,但有一些更正:

    public class DiceRolls {
        static void recurse(int diceNumber, int[] values, final int MAX) {
            if (diceNumber == values.length) {
                System.out.println(java.util.Arrays.toString(values));
            } else {
                for (int v = 1; v <= MAX; v++) {
                    values[diceNumber] = v;
                    recurse(diceNumber + 1, values, MAX);
                }
            }
        }
        public static void main(String[] args) {
            recurse(0, new int[3], 4);
        }
    }
    

    这是一个标准的连音递归生成器。如果要将所有int[] 添加到List 中,请确保add(values.clone()) 是独立的int[] 对象。


    但是额外的输出是什么?

    问题是您在掷完所有骰子之前就过早地倾倒了。在伪代码中,这就是你正在做的事情:

    if we're not done yet
        trying all possibilities for this dice
           dump result so far // premature dumping!
           recurse for next dice
    

    对您的代码进行简单的修复是执行以下操作:

    if we're not done yet
        trying all possibilities for this dice
           recurse for next dice
    else, we're done, so
        dump result // timely!
    

    所以回到 Java 实现,修复只是将dump(set); 移动到elseif (index &lt; 3) 语句。

    【讨论】:

    • 已更新以根据请求发布我的糟糕(可运行)。在这一点上,我认为它只是因为 LOL 因素。我很欣赏正确、干净的方法,以及我的代码被破坏的原因。由于这是我第一次尝试“真正的”(有用的)递归,我肯定会撕开您发布的内容,以便更好地了解事物。谢谢!
    • @spacerace:我推荐codingbat.com/java 作为练习题的好来源。它有一个递归部分,尽管它现在有点受限。哦,如您所见,我删除了我的评论,要求提供更完整的代码。我认为你的情况很好,只是我没有给予足够的关注。
    【解决方案3】:

    这是一个非递归的替代方案。改变这两个常数来计算不同骰子和不同骰子数量的所有组合。

    package utils;
    
    public class Dice {
        private static int FACES = 3;
        private static int NUMBER_OF_DICE = 3;
    
        public static void main(String[] args) {
            int start = createPair(1);
            int end = createPair(FACES);
            for (int i = start; i <= end; i++) {
                String combination = Integer.toString(i, FACES+1);
                if (combination.indexOf('0') < 0)
                    System.out.println(combination);
            }
        }
    
        private static int createPair(int number) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < NUMBER_OF_DICE; i++) {
                sb.append(number);
            }
            return Integer.parseInt(sb.toString(), FACES+1);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2013-04-27
      • 2016-06-25
      • 2016-11-18
      • 1970-01-01
      • 1970-01-01
      • 2014-12-13
      • 1970-01-01
      • 2016-02-20
      • 1970-01-01
      相关资源
      最近更新 更多