序列生成/广度优先搜索

发布于 2024-12-18 14:18:27 字数 334 浏览 8 评论 0原文

本质上,我正在做的就是尝试通过广度优先搜索所有可能的动作来解决魔方问题。我知道这不是解决立方体的最佳方法,但我只需要它用于非常短的序列(因此搜索深度不可能比 3 更深),并且我不需要存储除当前序列。

我正在尝试找到一种打印出不断增加的数字字符串(0,1,2,00,01,02...)的方法,因此我可以将每个字符串插入一个函数中以检查该特定序列是否移动解决了立方体,但我很难找到一种无限期地继续该序列的方法。

到目前为止,我所管理的只是嵌套 for 循环,但每次搜索变得更深时都需要另一个循环。有谁知道我该如何解决这个问题?

抱歉,如果我太含糊了,我可以写一篇关于我想做的事情的文章,但我想我会尽量保持简单。

Essentially what I'm doing is trying to solve a Rubik's cube with a breadth first search of all possible moves. I know this isn't the best way to solve the cube, but I only need it for very short sequences (so the depth of the search is unlikely to be deeper than 3), and I don't need to store anything other than the current sequence.

I'm trying to find a way of printing out ever increasing strings of number (0,1,2,00,01,02...), so I can just plug each one into a function to check if that particular sequence of moves solves the cube, but I'm having trouble finding a way of continuing the sequence indefinitely.

So far all I've managed is nested for loops, but there needs to be another loop each time the search gets deeper. Does anyone have any idea how I can approach this problem?

Sorry if I've been too vague, I could write an essay on what I'm trying to do but thought I'd try and keep it simple.

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

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

发布评论

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

评论(4

虚拟世界 2024-12-25 14:18:27

我对 Java 库中的内容不太熟悉,所以如果这是实现已经存在的东西,我很抱歉,但如果我从头开始编写这个,我可能会做这样的事情:

public class Enumerator {
    private int maxDepth;
    private int currentDepth;
    private int currentPerm;
    private String alphabet;

    public Enumerator(String alphabet, int d) {
        this.maxDepth = d;
        this.currentDepth = 1;
        this.currentPerm = 0;
        this.alphabet = alphabet;
    }

    public boolean next() {
        int numPermutations = (int) Math.pow(alphabet.length(), this.currentDepth);
        boolean res=false;

        // finished if
        if ((this.currentDepth == this.maxDepth) && 
            (this.currentPerm == numPermutations - 1)) {
            res = false;
        }
        // next perm at this depth
        else if (this.currentPerm < numPermutations - 1) {
            this.currentPerm++;
            res = true;
        }
        // next depth
        else if (this.currentDepth <= this.maxDepth) {
            this.currentDepth++;
            this.currentPerm = 0;
            res = true;
        }
        return res;
    }

    public String getPermutation() {
        int tmpPerm = this.currentPerm;
        String res = "";
        for (int i=0; i<this.currentDepth; i++) {
          int ind = tmpPerm % this.alphabet.length();
          res = this.alphabet.charAt(ind) + res;
          tmpPerm /= this.alphabet.length();
        }
        return res;
    }

    public static void main(String args[]) {
        int depth = 3;
        String alphabet = "012";
        Enumerator e = new Enumerator(alphabet, depth); 
        do {
            System.out.println(e.getPermutation());
        } while (e.next());
    }
}

这样你就可以从任意深度的任意符号的字母表。这也可以满足您的需求,因为它会迭代深度,并为每个深度生成完整的可能序列集。正如 Gian 所说,它也可以通过递归来完成,这可能更优雅。在 Python 中,我会使用生成器函数来实现此目的,但我不熟悉 Java 中的类似功能。

I'm not very familiar with what's in the Java libraries, so apologies if this is implementing something that is already there, but if I were writing this from scratch, I'd probably do something like this:

public class Enumerator {
    private int maxDepth;
    private int currentDepth;
    private int currentPerm;
    private String alphabet;

    public Enumerator(String alphabet, int d) {
        this.maxDepth = d;
        this.currentDepth = 1;
        this.currentPerm = 0;
        this.alphabet = alphabet;
    }

    public boolean next() {
        int numPermutations = (int) Math.pow(alphabet.length(), this.currentDepth);
        boolean res=false;

        // finished if
        if ((this.currentDepth == this.maxDepth) && 
            (this.currentPerm == numPermutations - 1)) {
            res = false;
        }
        // next perm at this depth
        else if (this.currentPerm < numPermutations - 1) {
            this.currentPerm++;
            res = true;
        }
        // next depth
        else if (this.currentDepth <= this.maxDepth) {
            this.currentDepth++;
            this.currentPerm = 0;
            res = true;
        }
        return res;
    }

    public String getPermutation() {
        int tmpPerm = this.currentPerm;
        String res = "";
        for (int i=0; i<this.currentDepth; i++) {
          int ind = tmpPerm % this.alphabet.length();
          res = this.alphabet.charAt(ind) + res;
          tmpPerm /= this.alphabet.length();
        }
        return res;
    }

    public static void main(String args[]) {
        int depth = 3;
        String alphabet = "012";
        Enumerator e = new Enumerator(alphabet, depth); 
        do {
            System.out.println(e.getPermutation());
        } while (e.next());
    }
}

That way you can enumerate sequences from alphabets of arbitrary symbols to an arbitrary depth. This also does what you want insofar as it iterates over depth and for each depth generates the full set of possible sequences. It could also be done with recursion, as Gian says, which might be more elegant. In Python I'd use a generator function for this, but I'm not familiar with anything similar in Java.

万劫不复 2024-12-25 14:18:27

听起来你想要一个递归解决方案,这样你的函数就会生成一个给定序列作为输入的后继移动列表,在这种情况下,你可以根据需要多次在其自己的输出上调用该函数。

Sounds like you want a recursive solution, such that your function generates a list of successor moves given a sequence as input, in which case you can just keep calling the function on its own output as many times as is necessary.

殤城〤 2024-12-25 14:18:27

递归函数不可以做到这一点吗?可以限制递归的深度并逐渐加深。

[更新] 向函数传递一个指定深度的 int;每次递归时,都会递减该值 - 检查它是否为零,如果是则返回。

对于值,将字符串或字符串构建器的集合传递到递归函数中。每个级别都会读取(并删除)前一级别中的值,附加所有可能的下一步操作并将结果放回到集合中(事实上,如果您愿意,您可以迭代而不是递归地执行此操作) 。

Level 1 generates 0,1,2,...

Level 2 removes 0 and replaces it with 00,01,02,...
Level 2 removes 1 and replaces it with 10,11,12,...
etc

Wouldn't a recursive function do this? You can limit the depth of recursion and gradually deepen it.

[Update] Pass the function an int specifying the depth; each time you recurse, decrement the value - check if it is zero, and return if so.

For the values, pass a collection of strings or stringbuilders into the recursive function. Each level reads (and removes) the values from the previous level, appends all possible next moves and places the results back in the collection (in fact, you could do this iteratively rather than recursively if you wanted).

Level 1 generates 0,1,2,...

Level 2 removes 0 and replaces it with 00,01,02,...
Level 2 removes 1 and replaces it with 10,11,12,...
etc
难理解 2024-12-25 14:18:27

FIFO 队列可能是比递归更好的方法,正如维基百科关于广度优先搜索的文章所建议的那样:http: //en.wikipedia.org/wiki/Breadth_first_search

我在 C# 中的解决方案:

string SolveRubiks()
{
    string[] singleMoves = {"0","1","2"};
    Queue<string> queue = new Queue<string>(singleMoves);
    while (true)
    {
        string moveSequence = queue.Dequeue();
        if (isSolution(moveSequence))
        {
            return moveSequence;
        }
        foreach (string singleMove in singleMoves)
        {
            queue.Enqueue(moveSequence + singleMove);
        }
    }
}

如果你需要一个迭代器,你可以用一个yield return 交换 if 块并更改方法签名,在 Java 中我想你必须实现一个迭代器接口(类似于 Philip Uren 的类)。

A FIFO queue might be a better approach than recursion, as suggested by the Wikipedia article on breadth-first search: http://en.wikipedia.org/wiki/Breadth_first_search.

My solution in C#:

string SolveRubiks()
{
    string[] singleMoves = {"0","1","2"};
    Queue<string> queue = new Queue<string>(singleMoves);
    while (true)
    {
        string moveSequence = queue.Dequeue();
        if (isSolution(moveSequence))
        {
            return moveSequence;
        }
        foreach (string singleMove in singleMoves)
        {
            queue.Enqueue(moveSequence + singleMove);
        }
    }
}

If you need an iterator, you can swap the if block with a yield return and change the method signature, in Java I guess you'll have to implement an iterator interface (similar to Philip Uren's class).

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