递归导致额外不需要的数据

发布于 2024-09-04 19:12:44 字数 2721 浏览 2 评论 0原文

我正在编写一个模块来处理骰子滚动。给定 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: 运行包含“简单修复”的代码。当心未使用的变量和奇怪的黑客,我还没有清理它。

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();
    }
}

I'm writing a module to handle dice rolling. Given x die of y sides, I'm trying to come up with a list of all potential roll combinations.

This code assumes 3 die, each with 3 sides labeled 1, 2, and 3. (I realize I'm using "magic numbers" but this is just an attempt to simplify and get the base code working.)

        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() is a simple method to just display the contents of list[]. The variable i is not used at the moment.)

What I'm attempting to do is increment a list[index] by one, stepping through the entire length of the list and incrementing as I go.

This is my "best attempt" code. Here is the output:

Bold output is what I'm looking for. I can't figure out how to get rid of the rest. (This is assuming three dice, each with 3 sides. Using recursion so I can scale it up to any x dice with y sides.)

[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]

I apologize for the formatting, best I could come up with.

Any help would be greatly appreciated. (This method was actually stemmed to use the data for something quite trivial, but has turned into a personal challenge. :)

edit: If there is another approach to solving this problem I'd be all ears, but I'd also like to solve my current problem and successfully use recursion for something useful.

edit2:
Running code including the "easy fix." Beware unused variables and weird hacks, I haven't cleaned it up yet.

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();
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

空‖城人不在 2024-09-11 19:12:44

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

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); 移动到 < if (index < 3) 语句的 code>else 情况。

I'm sorry I had to rewrite the code, but it's pretty much the same algorithm as yours with some corrections:

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);
    }
}

This is a standard tuplet recursive generator. If you want to add all the int[] into a List, then make sure to add(values.clone()) so they are independent int[] objects.


But what's with the extra output?

The problem is that you were dumping prematurely, before you're done throwing all the dices. In pseudocode, this is what you're doing:

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

An easy fix to your code is to do the following:

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

So back to the Java implementation, the fix is merely moving dump(set); to an else case for the if (index < 3) statement.

明天过后 2024-09-11 19:12:44

仅当 index == 2 时才调用 dump()

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

Call dump() only when index == 2.

Incidentally, i and list seem unused. And the verb is "recur". :)

烧了回忆取暖 2024-09-11 19:12:44

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

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);
    }
}

Here is a non-recursive alternative. Change the two constants to calculate all combinations for different dices and different numbers of dice.

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);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文