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

Posted

技术标签:

【中文标题】如何为填字游戏获得多个解决方案?【英文标题】:How to get multiple solutions for a crossword? 【发布时间】:2011-04-27 21:02:09 【问题描述】:

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

但我想问一些不同的问题。 我有两个不同单词的单词表和一个由 0 和 1 指定的网格。 我将不得不从 wordlist 1 中选择单词来表示行,2 来表示列。

主要问题是我必须在给定的时间限制内找到多个解决方案。有人可以为此建议我一些好的算法。我不知道我应该采用哪种算法方法。

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

谢谢

【问题讨论】:

Java 还是 C++?对于这个问题,您使用哪种编程语言都没有关系。使用你喜欢的任何东西。 通过问这个我的意思是根据字符串访问或数据结构等算法会更容易 @Pruthvid 这取决于你知道什么。如果你既不会 Java 也不会 C++,那么 Java 比 C++ 更容易学习。 @jesper 我对他们俩都很了解,这就是我问的原因。用什么类型的算法更容易实现。我无法获得一种算法,它可以为给定的单词列表提供多种解决方案。 @Pruthvid 如果您对 Java 和 C++ 都很了解,那么我的原始答案是:没关系,使用您最熟悉的任何语言。如您所知,Java 和 C++ 都有很好的标准库和集合等。 【参考方案1】:

我found a solution that does what you want。可悲的是,我不能把它归功于它:)

这是一个例子。你给它一个模式文件,比如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 的时间)

【讨论】:

@AnnaVopureta 啊来源是pdos.csail.mit.edu/~rtm/cword-src 显然他们删除了演示CGI【参考方案2】:

您也许可以使用称为Dancing Links or DLX 算法的东西。这是解决精确覆盖问题的一种非常有效的算法。

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

http://www.ocf.berkeley.edu/~jchu/publicportal/sudoku/sudoku.paper.html

老实说,我对确切的封面问题知之甚少,无法说这肯定会满足您的需求,但值得一看。

【讨论】:

这看起来很有希望/很有趣 是的,但我需要研究一下如何使用它来解决填字游戏【参考方案3】:

在做填字游戏时,通常会发现自己在寻找一个特定长度的单词,其中某个字母位于某个位置。所以,你可能会想要一个这样的函数:

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

【讨论】:

是的,但蛮力将允许我设计一个单一的解决方案。我想为同一个单词列表提供多个解决方案,此外,如果我从较大的单词开始,直到最后一个单词,让我说我有 3 个大小为 10 的单词。如果我发现这个单词被错误地选了一半,那么在完成拼图的一半之后那么我将如何追溯?我怎样才能实现一些检查点风格的功能? 好吧,蛮力通过有条不紊地检查所有可能性来发挥作用。如果有多种解决方案,蛮力最终会找到它们。至于你如何追溯,我认为你会想要使用递归算法。我在答案中加入了一种骨架算法。 找到第一个算法后不要停止算法。让它不停地换词,尝试每一种组合。找到解决方案后,记下它,但要继续寻找。

以上是关于如何为填字游戏获得多个解决方案?的主要内容,如果未能解决你的问题,请参考以下文章

填字游戏搜索的最佳数据结构

如何为 Google Play 游戏上传您自己的个人资料图片

如何为 extern 的新声明解决多个先前声明?

如何为溶解效果编写 sceneKit 着色器修改器

如何为相同的资源使用多个路由

PROLOG中的填字游戏解算器