Как получить несколько решений для кроссворда? - PullRequest
1 голос
/ 28 апреля 2011

Я уже видел форумы и разные вопросы по этому вопросу.

Но я хочу спросить что-то другое. У меня есть два списка разных слов и одна сетка, заданная 0 и 1. мне придется выбрать слово из списка слов 1 для строк и 2 для столбцов.

Основная проблема заключается в том, что мне нужно найти несколько решений в течение определенного времени. Может кто-нибудь предложить мне хороший алгоритм для этого. Я не понимаю, какой алгоритмический подход я должен использовать.

Другое дело, У меня есть два варианта языка. Либо С ++, либо Java, который лучше реализовать.

спасибо

Ответы [ 3 ]

2 голосов
/ 28 апреля 2011

Я нашел решение, которое делает то, что вы хотите . К сожалению, я не могу взять кредит на это :) 1003 *

Вот пример. Вы передаете ему файл шаблона, например 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

Конечно, с большими шаблонами или меньшими списками слов ваш пробег может отличаться (дико). Я смог сделать 1000 поколений за 26,5 секунды на процессоре Q9550, используя

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 голос
/ 28 апреля 2011

При создании кроссворда человек обычно ищет слово определенной длины с определенной буквой в определенной позиции. Итак, вам, вероятно, понадобится такая функция:

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

Который, вероятно, мог бы использовать набор предварительно созданных HashMaps для быстрого создания набора кандидатов. (Возможно, вы также захотите отследить, используется ли слово уже в кроссворде ... при условии, что дубликаты не допускаются)

Еще одна вещь, которую люди делают, это угадывают, используя подсказки. Я полагаю, что вы, вероятно, не ищете сильный ИИ, так что остаются алгоритмы грубой силы ... в этом случае попробуйте заполнить кроссворд, начиная с самых больших слов, так как там обычно меньше возможностей.

Скелетный алгоритм:

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);
        }
    }
}
1 голос
/ 28 апреля 2011

Вы можете использовать то, что называется Dancing Links или DLX алгоритм.Это чрезвычайно эффективный алгоритм для решения точных задач прикрытия.

Есть несколько программ, которые используют его для решения головоломок Судоку.

Честно говоря, я не знаю достаточно о точных проблемах прикрытия, чтобы сказать, что это определенно подойдет для ваших нужд, но стоит взглянуть.

...