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

时间:2011-04-27 21:02:10

标签: java c++ algorithm crossword

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

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

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

另一件事,  我有两种语言选择。无论是c ++还是java,都可以更好地实现。

谢谢

3 个答案:

答案 0 :(得分:2)

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的时间)

答案 1 :(得分:1)

您可以使用称为Dancing Links or DLX算法的内容。这是解决确切覆盖问题的极其有效的算法。

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

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

答案 2 :(得分:1)

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

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

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

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

骨架算法:

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