如何获得填字游戏的多个解决方案?

发布于 2024-11-03 10:19:17 字数 237 浏览 4 评论 0原文

我已经看过有关此的论坛和不同的问题。

但我想问一些不同的事情。 我有两个不同单词的单词列表和一个由 0 和 1 指定的网格。 我必须从单词列表 1 中选择单词作为行,从单词列表 2 中选择单词作为列。

主要问题是我必须在给定的时间限制内找到多个解决方案。有人可以建议我一些好的算法吗?我不知道我应该采取什么样的算法方法。

另一件事, 我有两种语言选择。 c++或者java哪个比较好实现。

谢谢

I have already seen the forums and different questions on this.

But i want to ask something different.
I have two wordlist of different words and one grid specified by 0 and 1.
i will have to select word from wordlist 1 for rows and 2 for columns.

The main problem is i have to find multiple solution within given time constraint. Can someone suggest me some good algorithm for that. I am not getting what kind of algorithmic approach should i take.

Another thing,
I have two language options. Either c++ or java which would be better to implement.

thank you

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

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

发布评论

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

评论(3

旧街凉风 2024-11-10 10:19:17

找到了一个可以满足您需求的解决方案。遗憾的是我不能把它归功于:)

这是一个例子。您向其提供一个模式文件,例如 pattern1

    ##   ##    
    #     #    
    #     #    
           #   
###   ###    ##
#      #      #
   #     #     
    #     #    
     #     #   
#      #      #
##    ###   ###
   #           
    #     #    
    #     #    
    ##   ##    

您在其上调用程序,例如:

./cword pattern1 /etc/dictionaries-common/words

输出是

SODS##HOG##AMPS
APIA#RADON#LAUE
TESS#ALONE#ERNA
ENCHANTRESS#GYM
###ADS###TUTU##
#PAYDAY#ESPIES#
REV#SCALD#SCRIP
ARON#KNOWS#SITE
MCCOY#KNITS#TET
#HARASS#NAPPED#
##TACT###DIE###
MCI#COORDINATES
ELOY#AMARU#ROLL
SINE#TARIM#LIMA
SOSA##REP##SLOT

或者,再运行一次:

PAWN##HOT##BEST
OLEO#SURYA#OMAR
LOAN#AGAPE#ABLE
SELFISHNESS#RTE
###ASH###OKAY##
#KATMAI#EPILOG#
INN#SYNOD#MULES
SETH#SCHWA#MONA
MEIER#AMIDS#GEM
#SPLATS#NOWAYS#
##APSE###RAY###
WIS#PATRONYMICS
ALTA#CHOKE#AREA
SLOP#HEARD#ROBS
PSST##ERA##ANUS

当然,对于较大的模式或较小的单词列表,您的里程可能会有所不同(疯狂地)。我能够在 Q9550 处理器上在 26.5 秒内完成 1000 代,使用

time for a in $(seq 1 200)
do 
    for a in 1 2 3 4 5
    do 
        ./cword pattern1 /etc/dictionaries-common/words | md5sum&
    done
    wait
done | sort | uniq -c | sort -n | tee >(wc -l)

输出确认这些实际上是 1000 个独特解决方案。如果你问我的话,还不错。 (时间包括计算每个解决方案的 md5sums 的时间)

I found a solution that does what you want. Sadly I can't take credit for it :)

Here is an example. You feed it a pattern file, like pattern1:

    ##   ##    
    #     #    
    #     #    
           #   
###   ###    ##
#      #      #
   #     #     
    #     #    
     #     #   
#      #      #
##    ###   ###
   #           
    #     #    
    #     #    
    ##   ##    

You invoke the program on it, like e.g. so:

./cword pattern1 /etc/dictionaries-common/words

The output is

SODS##HOG##AMPS
APIA#RADON#LAUE
TESS#ALONE#ERNA
ENCHANTRESS#GYM
###ADS###TUTU##
#PAYDAY#ESPIES#
REV#SCALD#SCRIP
ARON#KNOWS#SITE
MCCOY#KNITS#TET
#HARASS#NAPPED#
##TACT###DIE###
MCI#COORDINATES
ELOY#AMARU#ROLL
SINE#TARIM#LIMA
SOSA##REP##SLOT

Or, run another time:

PAWN##HOT##BEST
OLEO#SURYA#OMAR
LOAN#AGAPE#ABLE
SELFISHNESS#RTE
###ASH###OKAY##
#KATMAI#EPILOG#
INN#SYNOD#MULES
SETH#SCHWA#MONA
MEIER#AMIDS#GEM
#SPLATS#NOWAYS#
##APSE###RAY###
WIS#PATRONYMICS
ALTA#CHOKE#AREA
SLOP#HEARD#ROBS
PSST##ERA##ANUS

Of course, with larger patterns or smaller wordlists your mileage may vary (wildly). I was able to do 1000 generations in 26.5 seconds on a Q9550 processor, using

time for a in $(seq 1 200)
do 
    for a in 1 2 3 4 5
    do 
        ./cword pattern1 /etc/dictionaries-common/words | md5sum&
    done
    wait
done | sort | uniq -c | sort -n | tee >(wc -l)

The output confirmed that these were in fact 1000 unique solutions. Not bad, if you ask me. (The timing included the time to calculate the md5sums per solution)

挖个坑埋了你 2024-11-10 10:19:17

您也许可以使用称为Dancing Links 或DLX 算法的算法。这是解决精确覆盖问题的极其有效的算法。

有几个程序使用它来解决数独难题。

老实说,我对确切的封面问题了解不够,不能说这肯定会满足您的需求,但值得一看。

You may be able to use something called the Dancing Links or DLX algorithm. This is an extremely efficient algorithm for solving exact cover problems.

There are several programs out there that use this to solve Sudoku puzzles.

I honestly don't know enough about exact cover problems to say that this will definitely work for your needs but it's worth taking a look.

稚气少女 2024-11-10 10:19:17

在做填字游戏时,人们通常会发现自己正在寻找一个特定长度的单词,并且特定字母位于其中的特定位置。因此,您可能需要这样的函数:

List<String> findWord(int ofLength, char withLetter, int atIndex) {/*implementation*/}

它可能会使用一组预构建的 HashMap 来快速生成一组候选者。 (您可能还希望能够跟踪该单词当前是否已在填字游戏中使用......假设不允许重复)

人们做的另一件事是使用提示进行猜测。我认为你可能不是在寻找强大的人工智能,因此只剩下暴力算法......在这种情况下,尝试先从最大的单词开始填写填字游戏,因为那里的可能性通常较少。

骨架算法:

private void checkPuzzleOn(Row row, SolutionSet s) {

    List<Row> crossingRows = row.getCrossingRows();

    if(allAlreadyFilled(crossingRows)) {
        //This part of the crossword works; store info in solution set.
        return;
    }

    crossingRows.sortBiggestToSmallest();

    foreach(Row crossing in crossingRows) {

        int index = row.getIndexOfIntersectionWith(crossing);
        char c = row.charAt(index);

        List<String> candidates = findWords(crossing.length, c, index);
        foreach(String candidate in candidates) {
            verifyAgainstPresentWords(crossing, candidate); //check that using this word won't collide with others; important because of cycles.
        }

        if(candidates.isEmpty()) {
            //This part of the crossword won't match! store info in solution set.
            return;
        }

        foreach(String candidate in candidates) {
            crossing.setWord(candidate);
            checkPuzzleOn(crossing, s);
        }
    }
}

When doing a crossword, one usually finds oneself looking for a word of a certain length, with a certain letter at a certain position in it. So, you're probably going to want a function like this:

List<String> findWord(int ofLength, char withLetter, int atIndex) {/*implementation*/}

Which could probably use a set of pre-built HashMaps to produce a set of candidates quickly. (You'll probably also want to be able to track whether the word is currently used already in the crossword...assuming duplicates aren't allowed)

The other thing people do is guess using hints. I figure you're probably not looking for strong AI, so that leaves brute force algorithms...in which case, try to fill in the crossword starting with the biggest words first, since there are generally fewer possibilities there.

Skeleton algorithm:

private void checkPuzzleOn(Row row, SolutionSet s) {

    List<Row> crossingRows = row.getCrossingRows();

    if(allAlreadyFilled(crossingRows)) {
        //This part of the crossword works; store info in solution set.
        return;
    }

    crossingRows.sortBiggestToSmallest();

    foreach(Row crossing in crossingRows) {

        int index = row.getIndexOfIntersectionWith(crossing);
        char c = row.charAt(index);

        List<String> candidates = findWords(crossing.length, c, index);
        foreach(String candidate in candidates) {
            verifyAgainstPresentWords(crossing, candidate); //check that using this word won't collide with others; important because of cycles.
        }

        if(candidates.isEmpty()) {
            //This part of the crossword won't match! store info in solution set.
            return;
        }

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