Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Генерация кроссвордов 
:(
    Опции темы
Kuvaldis
Дата 8.8.2006, 10:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


механик-вредитель
***


Профиль
Группа: Участник Клуба
Сообщений: 1189
Регистрация: 16.6.2006
Где: Минск

Репутация: 1
Всего: 61



Доброго всем времени суток!!!smile 

До учебы еще целый месяц, делать нечего. Поэтому учу С++ по книге Дейтела. А в ней в разряде "головоломные" раздела на строки предложена задача на генерацию кроссворда (заполненный словами, желательно симметричный) Ну, очевидное решение у меня есть - простой backtracking. Но, по-моему, очень (!) это неэффективно. В сети исходников нет (вроде искал хорошо), но есть куча готовых программ. Может кто, грешным делом, занимался этой проблемой? Подскажите хотя бы идею 

Заранее спасибо   


--------------------
Помни - когда ты спишь, враг не дремлет
Спи чаще и дольше, изматывай врага бессоницей
PM MAIL ICQ   Вверх
Kuvaldis
Дата 14.8.2006, 21:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


механик-вредитель
***


Профиль
Группа: Участник Клуба
Сообщений: 1189
Регистрация: 16.6.2006
Где: Минск

Репутация: 1
Всего: 61



Уважаемые форумчане! Я конечно понимаю, что спасение утопающих - дело рук самих утопающих. Но неужели мой вопрос окажется неуслышенным?


--------------------
Помни - когда ты спишь, враг не дремлет
Спи чаще и дольше, изматывай врага бессоницей
PM MAIL ICQ   Вверх
Akina
Дата 14.8.2006, 21:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 20
Всего: 454



Я не понял - речь о генерации сетки, заполнении готовой сетки, both?


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
Kuvaldis
Дата 14.8.2006, 23:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


механик-вредитель
***


Профиль
Группа: Участник Клуба
Сообщений: 1189
Регистрация: 16.6.2006
Где: Минск

Репутация: 1
Всего: 61



Akina
Цитата

Я не понял - речь о генерации сетки, заполнении готовой сетки, both?

Генерация готовой сетки по словарю (т.е. both)

как я понял в условии задачи, входные параметры = это только размер кроссворда,  а дальше генерится заполненная сетка со словами



--------------------
Помни - когда ты спишь, враг не дремлет
Спи чаще и дольше, изматывай врага бессоницей
PM MAIL ICQ   Вверх
nostromo
Дата 15.8.2006, 09:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 194
Регистрация: 23.3.2006

Репутация: 5
Всего: 10



Я, пожалуй, сделал бы следующую вариацию бэктрекинга.

Сначала, создаем базу данных с таблицей, содержащей поля: слово, длина слова, 1-я буква, 2-я буква, ...., 20-я буква. По всем полям  создаем индексы для быстрого поиска.
Запросы типа "найти все слова длины 6 где 2-я буква=А и 5-я буква=Ц" должны выполняться весьма быстро.
Таблица одна, скорее всего целитком влезет в память, поэтому полноценную СУБД задействовать, возможно, особого смысла нет и можно ограничиться самодельной программной реализацией.

Затем генерируем сетку нужной формы и пытаемся ее заполнять (обычный бэктрекинг). Думаю, что для типичных кроссвордов и со словарем в несколько тысяч слов время генерации таким методом будет вполне приемлемым.

В случае, когда словарь мал, алгоритм может сильно зависеть от того, насколько он мал и каковы требования к размеру и форме кроссворда. В грубом варианте, можно перебирать размещения слов на сетке в допустимых границах (действительно тяжелый перебор).
--------------------
На пыльных тропинках далеких планет останутся наши следы.
PM MAIL   Вверх
Kuvaldis
Дата 15.8.2006, 14:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


механик-вредитель
***


Профиль
Группа: Участник Клуба
Сообщений: 1189
Регистрация: 16.6.2006
Где: Минск

Репутация: 1
Всего: 61



nostromo
Во-первых, спасибо за ответ и за участие (к сожалению, пока 100 постов нет smile , но я запомню )
во-вторых, получается, что оптимальным вариантом является сначала генерация сетки, а потом ее заполнение? 
Совместить эти процессы никак не получится? или это нерационально?
Тем более если словарь не очень большой


--------------------
Помни - когда ты спишь, враг не дремлет
Спи чаще и дольше, изматывай врага бессоницей
PM MAIL ICQ   Вверх
Kernigan
Дата 25.8.2006, 17:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 18.6.2006

Репутация: нет
Всего: нет



Хотел бы тебе чем-то помощь, но, к сожалению, подобными вещами не занимался, хотя возможность была. 
Надеюсь, что до конца каникул и до начала учебного года, ты всёже найдёшь правильное решение.
PM MAIL   Вверх
Kuvaldis
Дата 25.8.2006, 18:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


механик-вредитель
***


Профиль
Группа: Участник Клуба
Сообщений: 1189
Регистрация: 16.6.2006
Где: Минск

Репутация: 1
Всего: 61



Вроде бы, нашел толковый вариант

Код

Для очередного слова в сетке (желательно начинать с длинных)

фаза Do
* определяешь маску (какие буквы уже определены)
* получаешь курсор выборки из словаря по данной маске и запоминаешь его значение
* если обломились — производишь откат к предыдущему слову
* вставляешь выбранное из словаря слово и переходишь к следующему

фаза Redo (когда был откат)
* переводишь курсор вперед
* если обломились (или вернулись на первое запомненное значение) — производишь откат к предыдущему слову
* вставляешь выбранное из словаря слово и переходишь к следующему

Чтобы внести элемент случайности, обращение к словарю сделаем с изюминкой.

Пусть есть таблица слов длиной N. Курсор — это индекс i в этой таблице.
Получение курсора:
* взять число i0 = random(0..N-1), i1 = (i0-1)%N
* взять число i; for(i=i0; i != i1 && !match_mask(word[i]); i=(i+1)%N) {}
* если !match_mask(word[i]), то курсор получить не удалось
* иначе cursor=i
Переход к следующему:
* то же самое, только i0 = cursor+1, i1 = cursor

Для случаев, когда в маске зафиксирован префикс (первые несколько букв) — диапазон поиска можно сократить.

Также можно ввести проверку — для каждой позиции буквы в слове собрать множество доступных букв и фильтровать запросы к словарю на основе этих данных.
Например, буква Ъ не встречается в начале слова — так что незачем сканировать словарь.

Как я уже говорил, удобно разбить словарь по длине слов.



--------------------
Помни - когда ты спишь, враг не дремлет
Спи чаще и дольше, изматывай врага бессоницей
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Алгоритмы"

maxim1000

Форум "Алгоритмы" предназначен для обсуждения вопросов, связанных только с алгоритмами и структурами данных, без привязки к конкретному языку программирования и/или программному продукту.


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, maxim1000.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Алгоритмы | Следующая тема »


 




[ Время генерации скрипта: 0.0743 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.