जवाबों:
मैं एक समाधान के साथ आया था जो शायद सबसे कुशल नहीं है, लेकिन यह काफी अच्छी तरह से काम करता है। मूल रूप से:
यह एक काम करता है, अभी तक अक्सर काफी गरीब वर्ग। बेहतर परिणाम के साथ आने के लिए मैंने ऊपर दिए गए मूल नुस्खा में कई परिवर्तन किए।
मैंने हाल ही में पायथन में अपना खुद का लिखा है। आप इसे यहाँ पा सकते हैं: http://bryanhelmig.com/python-crossword-puzzle-generator/ । यह घने NYT शैली वर्ग पहेली नहीं बनाता है, लेकिन वर्ग पहेली की शैली आपको एक बच्चे की पहेली पुस्तक में मिल सकती है।
कुछ एल्गोरिदम के विपरीत मुझे वहां पता चला कि शब्दों को रखने का एक यादृच्छिक जानवर-बल पद्धति लागू की गई है जैसे कुछ ने सुझाव दिया है, मैंने शब्द प्लेसमेंट पर थोड़ा चालाक जानवर-बल दृष्टिकोण लागू करने की कोशिश की। यहाँ मेरी प्रक्रिया है:
अंत में, आपके पास एक सभ्य क्रॉसवर्ड पहेली या शब्द खोज पहेली है, क्योंकि वे उसी के बारे में हैं। यह अच्छी तरह से चलने के लिए जाता है, लेकिन मुझे बताएं कि क्या आपके पास सुधार के बारे में कोई सुझाव है। बड़ा ग्रिड तेजी से धीमी गति से चलता है; बड़ा शब्द रैखिक रूप से सूचीबद्ध होता है। बड़े शब्द सूचियों में बेहतर शब्द प्लेसमेंट संख्या में बहुत अधिक संभावना है।
array.sort(key=f)
स्थिर है, जिसका अर्थ है (उदाहरण के लिए) जो केवल लंबाई द्वारा एक वर्णमाला शब्द सूची को क्रमबद्ध कर रहा है, सभी 8-अक्षर शब्दों को वर्णानुक्रम में क्रमबद्ध रखेगा।
मैंने वास्तव में लगभग दस साल पहले एक क्रॉसवर्ड पीढ़ी का कार्यक्रम लिखा था (यह गूढ़ था लेकिन सामान्य वर्ग के लिए वही नियम लागू होंगे)।
इसमें शब्दों की एक सूची थी (और संबद्ध सुराग) एक फ़ाइल में संग्रहित थी जो आज तक अवरोही उपयोग द्वारा सॉर्ट की गई थी (ताकि कम-उपयोग किए गए शब्द फ़ाइल के शीर्ष पर थे)। एक टेम्पलेट, जो मूल रूप से काले और मुक्त वर्गों का प्रतिनिधित्व करने वाला एक बिट-मास्क था, जिसे क्लाइंट द्वारा प्रदान किए गए पूल से बेतरतीब ढंग से चुना गया था।
फिर, पहेली में प्रत्येक गैर-पूर्ण शब्द के लिए (मूल रूप से पहला रिक्त वर्ग ढूंढें और देखें कि क्या सही में एक (पूर्ण-शब्द) या नीचे (नीचे-शब्द) भी रिक्त है), एक खोज की गई थी फ़ाइल जो पहले शब्द की तलाश में है, उस शब्द में पहले से ही अक्षरों को ध्यान में रखते हुए। यदि कोई ऐसा शब्द नहीं था जो फिट हो सकता है, तो आपने पूरे शब्द को अधूरा चिह्नित किया और आगे बढ़ गए।
अंत में कुछ अनकहे शब्द होंगे जिन्हें कंपाइलर को भरना होगा (और यदि वांछित हो तो शब्द और एक क्लू फ़ाइल में जोड़ें)। अगर वे किसी के साथ नहीं आ सके विचार के , तो वे बाधाओं को बदलने के लिए मैन्युअल रूप से क्रॉसवर्ड को संपादित कर सकते हैं या कुल पुन: पीढ़ी के लिए पूछ सकते हैं।
एक बार जब शब्द / सुराग फ़ाइल एक निश्चित आकार तक बढ़ जाती है (और इस ग्राहक के लिए एक दिन में 50-100 सुराग जोड़ रहा था), तो शायद ही कभी दो या तीन से अधिक मैनुअल फिक्स अप का मामला था जो प्रत्येक क्रॉसवर्ड के लिए किया जाना था। ।
यह एल्गोरिथ्म 50 घना 6x9 बनाता है 60 सेकंड में एरो क्रॉसवर्ड । यह एक शब्द डेटाबेस (शब्द + युक्तियों के साथ) और एक बोर्ड डेटाबेस (पूर्व-कॉन्फ़िगर बोर्डों के साथ) का उपयोग करता है।
1) Search for all starting cells (the ones with an arrow), store their size and directions
2) Loop through all starting cells
2.1) Search a word
2.1.1) Check if it was not already used
2.1.2) Check if it fits
2.2) Add the word to the board
3) Check if all cells were filled
एक बड़ा शब्द डेटाबेस पीढ़ी समय को काफी कम कर देता है और कुछ प्रकार के बोर्डों को भरना मुश्किल होता है! बड़े बोर्डों को सही ढंग से भरने के लिए अधिक समय की आवश्यकता होती है!
उदाहरण:
पूर्व-कॉन्फ़िगर 6x9 बोर्ड:
(# मतलब एक सेल में एक टिप,% का मतलब है एक सेल में दो टिप्स, नहीं दिखाए गए तीर)
# - # # - % # - #
- - - - - - - - -
# - - - - - # - -
% - - # - # - - -
% - - - - - % - -
- - - - - - - - -
उत्पन्न 6x9 बोर्ड:
# C # # P % # O #
S A T E L L I T E
# N I N E S # T A
% A B # A # G A S
% D E N S E % W E
C A T H E D R A L
युक्तियाँ [पंक्ति, स्तंभ]:
[1,0] SATELLITE: Used for weather forecast
[5,0] CATHEDRAL: The principal church of a city
[0,1] CANADA: Country on USA's northern border
[0,4] PLEASE: A polite way to ask things
[0,7] OTTAWA: Canada's capital
[1,2] TIBET: Dalai Lama's region
[1,8] EASEL: A tripod used to put a painting
[2,1] NINES: Dressed up to (?)
[4,1] DENSE: Thick; impenetrable
[3,6] GAS: Type of fuel
[1,5] LS: Lori Singer, american actress
[2,7] TA: Teaching assistant (abbr.)
[3,1] AB: A blood type
[4,3] NH: New Hampshire (abbr.)
[4,5] ED: (?) Harris, american actor
[4,7] WE: The first person of plural (Grammar)
हालांकि यह एक पुराना सवाल है, मैं इसी तरह के काम के आधार पर उत्तर देने का प्रयास करूंगा।
बाधा समस्याओं को हल करने के लिए कई दृष्टिकोण हैं (जो कि सामान्य रूप से एनपीसी जटिलता वर्ग में हैं)।
यह कॉम्बिनेटरियल ऑप्टिमाइज़ेशन और बाधा प्रोग्रामिंग से संबंधित है। इस मामले में अड़चनें ग्रिड की ज्यामिति और आवश्यकता है कि शब्द अद्वितीय आदि हैं।
रैंडमाइजेशन / एनलिंग दृष्टिकोण भी काम कर सकते हैं (हालांकि उचित सेटिंग के भीतर)।
कुशल सादगी सिर्फ परम ज्ञान हो सकता है!
आवश्यकताएँ अधिक या कम पूर्ण क्रॉसवर्ड कंपाइलर और (विज़ुअल WYSIWYG) बिल्डर के लिए थीं।
WYSIWYG बिल्डर भाग को छोड़कर, संकलक रूपरेखा यह थी:
उपलब्ध शब्दसूची लोड करें (शब्द की लंबाई के आधार पर छांटे, अर्थात 2,3, .., 20)
उपयोगकर्ता-निर्मित ग्रिड (जैसे x पर शब्द, लंबाई L, क्षैतिज या लंबवत) (जटिलता O (N)) पर शब्द-शब्द (यानी ग्रिड शब्द) खोजें
ग्रिड शब्दों (जो भरे जाने की आवश्यकता है) के जटिल बिंदुओं की गणना करें (जटिलता O (N ^ 2))
उपयोग किए गए वर्णमाला के विभिन्न अक्षरों के साथ शब्दसूची में शब्दों के अंतरों की गणना करें (यह एक टेम्पलेट का उपयोग करके मिलान शब्दों की खोज करने की अनुमति देता है। सी । सी । कंबॉन थीसिस का उपयोग cwc द्वारा किया जाता है ) (जटिलता ओ (WL * AL))
चरण .3 और .4 इस कार्य को करने की अनुमति देते हैं:
ए। स्वयं के साथ ग्रिड शब्दों के अंतर इस ग्रिड शब्द के लिए उपलब्ध शब्दों के संबद्ध शब्द सूची में मिलान खोजने की कोशिश करने के लिए एक "टेम्पलेट" बनाने में सक्षम हैं (इस शब्द के साथ अन्य इंटरसेक्टिंग शब्दों के अक्षरों का उपयोग करके जो पहले से ही एक निश्चित रूप से भरे हुए हैं एल्गोरिथ्म का चरण)
ख। वर्णमाला के साथ एक शब्दसूची में शब्दों के अंतर मिलान (उम्मीदवार) शब्दों को खोजने में सक्षम होते हैं जो किसी दिए गए "टेम्पलेट" से मेल खाते हैं (उदाहरण के लिए 1 स्थान पर 'ए' और तीसरे स्थान पर 'बी' आदि)।
इसलिए इन डेटा संरचनाओं को लागू करने के लिए इस्तेमाल किया एल्गोरिथ्म इस तरह से था:
नोट: यदि ग्रिड और शब्दों का डेटाबेस स्थिर है तो पिछले चरण सिर्फ एक बार किए जा सकते हैं।
एल्गोरिथ्म का पहला चरण यादृच्छिक पर एक खाली शब्द-शब्द (ग्रिड शब्द) का चयन करें और इसे अपने संबंधित शब्दसूची से एक उम्मीदवार शब्द के साथ भरें (रैंडमाइजेशन एल्गोरिदम के लगातार निष्पादन में विभिन्न विलेयन्स बनाने में सक्षम बनाता है) (जटिलता ओ (1) या ओ) एन))
प्रत्येक अभी भी खाली शब्द स्लॉट के लिए (जिसमें पहले से ही भरे हुए शब्द-बिंदुओं के साथ चौराहे हैं), एक बाधा अनुपात की गणना करें (यह अलग-अलग हो सकता है, sth सरल उस चरण में उपलब्ध समाधानों की संख्या है) और इस अनुपात द्वारा रिक्त शब्द-बिंदुओं को क्रमबद्ध करें (Complex O) (NlogN) ) या ओ (एन)
पिछले चरण में गणना की गई खाली शब्दसूची के माध्यम से लूप करें और प्रत्येक के लिए कई प्रकार के कैनडिकडेट समाधानों की कोशिश करें (यह सुनिश्चित करना कि "चाप-संगति बरकरार है", अर्थात ग्रिड के पास इस कदम के बाद एक समाधान है यदि इस शब्द का उपयोग किया जाता है) और उनके अनुसार क्रमबद्ध करें अगले चरण के लिए अधिकतम उपलब्धता (यानी अगले चरण में एक अधिकतम संभव समाधान है यदि इस शब्द का उपयोग उस स्थान पर उस समय किया जाता है, आदि ..) (जटिलता ओ (एन * मैक्सकंडिडेट्स यूडेड)
उस शब्द को भरें (भरे हुए के रूप में चिह्नित करें और चरण 2 पर जाएं)
यदि कोई शब्द नहीं मिला जो कि चरण के मानदंड को संतुष्ट करता है। 3 कुछ पिछले चरण के दूसरे उम्मीदवार समाधान के लिए पीछे हटने का प्रयास करें (मानदंड यहां भिन्न हो सकते हैं) (जटिलता ओ (एन))
यदि बैकट्रैक मिला, तो वैकल्पिक का उपयोग करें और वैकल्पिक रूप से किसी भी पहले से भरे शब्दों को रीसेट करें जिन्हें रीसेट की आवश्यकता हो सकती है (उन्हें फिर से अनफिल्टर्ड करें) (जटिलता ओ (एन))
यदि कोई बैकट्रैक नहीं मिला, तो कोई समाधान नहीं मिल सकता है (कम से कम इस कॉन्फ़िगरेशन, प्रारंभिक बीज आदि के साथ)।
जब सभी शब्द-पत्र भर जाते हैं तो आपके पास एक ही उपाय होता है
यह एल्गोरिथ्म समस्या के समाधान के पेड़ के एक यादृच्छिक निरंतर चलना करता है। यदि किसी बिंदु पर एक मृत अंत है, तो यह पिछले नोड का बैकट्रैक करता है और किसी अन्य मार्ग का अनुसरण करता है। अनटील या तो एक समाधान पाया जाता है या विभिन्न नोड्स के लिए उम्मीदवारों की संख्या समाप्त हो जाती है।
संगतता भाग सुनिश्चित करता है कि पाया गया एक समाधान वास्तव में एक समाधान है और यादृच्छिक भाग विभिन्न निष्पादन में विभिन्न समाधानों का उत्पादन करने में सक्षम बनाता है और औसतन बेहतर प्रदर्शन भी करता है।
पुनश्च। यह सब (और अन्य) शुद्ध जावास्क्रिप्ट (समानांतर प्रसंस्करण और WYSIWYG) क्षमता के साथ लागू किया गया था
पीएस 2। एक ही समय में एक से अधिक (अलग) समाधान का उत्पादन करने के लिए एल्गोरिथ्म को आसानी से समानांतर किया जा सकता है
उम्मीद है की यह मदद करेगा
शुरू करने के लिए एक यादृच्छिक संभाव्य दृष्टिकोण का उपयोग क्यों न करें। एक शब्द के साथ शुरू करें, और फिर बार-बार एक यादृच्छिक शब्द चुनें और इसे आकार आदि पर बाधाओं को तोड़ने के बिना पहेली की वर्तमान स्थिति में फिट करने का प्रयास करें। यदि आप असफल होते हैं, तो बस फिर से शुरू करें।
आपको आश्चर्य होगा कि इस तरह का मोंटे कार्लो दृष्टिकोण कितनी बार काम करता है।
यहाँ कुछ जावास्क्रिप्ट कोड है जो कि निक के उत्तर और ब्रायन के पायथन कोड पर आधारित है। बस इसे पोस्ट करने की स्थिति में किसी और को इसकी आवश्यकता होती है।
function board(cols, rows) { //instantiator object for making gameboards
this.cols = cols;
this.rows = rows;
var activeWordList = []; //keeps array of words actually placed in board
var acrossCount = 0;
var downCount = 0;
var grid = new Array(cols); //create 2 dimensional array for letter grid
for (var i = 0; i < rows; i++) {
grid[i] = new Array(rows);
}
for (var x = 0; x < cols; x++) {
for (var y = 0; y < rows; y++) {
grid[x][y] = {};
grid[x][y].targetChar = EMPTYCHAR; //target character, hidden
grid[x][y].indexDisplay = ''; //used to display index number of word start
grid[x][y].value = '-'; //actual current letter shown on board
}
}
function suggestCoords(word) { //search for potential cross placement locations
var c = '';
coordCount = [];
coordCount = 0;
for (i = 0; i < word.length; i++) { //cycle through each character of the word
for (x = 0; x < GRID_HEIGHT; x++) {
for (y = 0; y < GRID_WIDTH; y++) {
c = word[i];
if (grid[x][y].targetChar == c) { //check for letter match in cell
if (x - i + 1> 0 && x - i + word.length-1 < GRID_HEIGHT) { //would fit vertically?
coordList[coordCount] = {};
coordList[coordCount].x = x - i;
coordList[coordCount].y = y;
coordList[coordCount].score = 0;
coordList[coordCount].vertical = true;
coordCount++;
}
if (y - i + 1 > 0 && y - i + word.length-1 < GRID_WIDTH) { //would fit horizontally?
coordList[coordCount] = {};
coordList[coordCount].x = x;
coordList[coordCount].y = y - i;
coordList[coordCount].score = 0;
coordList[coordCount].vertical = false;
coordCount++;
}
}
}
}
}
}
function checkFitScore(word, x, y, vertical) {
var fitScore = 1; //default is 1, 2+ has crosses, 0 is invalid due to collision
if (vertical) { //vertical checking
for (i = 0; i < word.length; i++) {
if (i == 0 && x > 0) { //check for empty space preceeding first character of word if not on edge
if (grid[x - 1][y].targetChar != EMPTYCHAR) { //adjacent letter collision
fitScore = 0;
break;
}
} else if (i == word.length && x < GRID_HEIGHT) { //check for empty space after last character of word if not on edge
if (grid[x+i+1][y].targetChar != EMPTYCHAR) { //adjacent letter collision
fitScore = 0;
break;
}
}
if (x + i < GRID_HEIGHT) {
if (grid[x + i][y].targetChar == word[i]) { //letter match - aka cross point
fitScore += 1;
} else if (grid[x + i][y].targetChar != EMPTYCHAR) { //letter doesn't match and it isn't empty so there is a collision
fitScore = 0;
break;
} else { //verify that there aren't letters on either side of placement if it isn't a crosspoint
if (y < GRID_WIDTH - 1) { //check right side if it isn't on the edge
if (grid[x + i][y + 1].targetChar != EMPTYCHAR) { //adjacent letter collision
fitScore = 0;
break;
}
}
if (y > 0) { //check left side if it isn't on the edge
if (grid[x + i][y - 1].targetChar != EMPTYCHAR) { //adjacent letter collision
fitScore = 0;
break;
}
}
}
}
}
} else { //horizontal checking
for (i = 0; i < word.length; i++) {
if (i == 0 && y > 0) { //check for empty space preceeding first character of word if not on edge
if (grid[x][y-1].targetChar != EMPTYCHAR) { //adjacent letter collision
fitScore = 0;
break;
}
} else if (i == word.length - 1 && y + i < GRID_WIDTH -1) { //check for empty space after last character of word if not on edge
if (grid[x][y + i + 1].targetChar != EMPTYCHAR) { //adjacent letter collision
fitScore = 0;
break;
}
}
if (y + i < GRID_WIDTH) {
if (grid[x][y + i].targetChar == word[i]) { //letter match - aka cross point
fitScore += 1;
} else if (grid[x][y + i].targetChar != EMPTYCHAR) { //letter doesn't match and it isn't empty so there is a collision
fitScore = 0;
break;
} else { //verify that there aren't letters on either side of placement if it isn't a crosspoint
if (x < GRID_HEIGHT) { //check top side if it isn't on the edge
if (grid[x + 1][y + i].targetChar != EMPTYCHAR) { //adjacent letter collision
fitScore = 0;
break;
}
}
if (x > 0) { //check bottom side if it isn't on the edge
if (grid[x - 1][y + i].targetChar != EMPTYCHAR) { //adjacent letter collision
fitScore = 0;
break;
}
}
}
}
}
}
return fitScore;
}
function placeWord(word, clue, x, y, vertical) { //places a new active word on the board
var wordPlaced = false;
if (vertical) {
if (word.length + x < GRID_HEIGHT) {
for (i = 0; i < word.length; i++) {
grid[x + i][y].targetChar = word[i];
}
wordPlaced = true;
}
} else {
if (word.length + y < GRID_WIDTH) {
for (i = 0; i < word.length; i++) {
grid[x][y + i].targetChar = word[i];
}
wordPlaced = true;
}
}
if (wordPlaced) {
var currentIndex = activeWordList.length;
activeWordList[currentIndex] = {};
activeWordList[currentIndex].word = word;
activeWordList[currentIndex].clue = clue;
activeWordList[currentIndex].x = x;
activeWordList[currentIndex].y = y;
activeWordList[currentIndex].vertical = vertical;
if (activeWordList[currentIndex].vertical) {
downCount++;
activeWordList[currentIndex].number = downCount;
} else {
acrossCount++;
activeWordList[currentIndex].number = acrossCount;
}
}
}
function isActiveWord(word) {
if (activeWordList.length > 0) {
for (var w = 0; w < activeWordList.length; w++) {
if (word == activeWordList[w].word) {
//console.log(word + ' in activeWordList');
return true;
}
}
}
return false;
}
this.displayGrid = function displayGrid() {
var rowStr = "";
for (var x = 0; x < cols; x++) {
for (var y = 0; y < rows; y++) {
rowStr += "<td>" + grid[x][y].targetChar + "</td>";
}
$('#tempTable').append("<tr>" + rowStr + "</tr>");
rowStr = "";
}
console.log('across ' + acrossCount);
console.log('down ' + downCount);
}
//for each word in the source array we test where it can fit on the board and then test those locations for validity against other already placed words
this.generateBoard = function generateBoard(seed = 0) {
var bestScoreIndex = 0;
var top = 0;
var fitScore = 0;
var startTime;
//manually place the longest word horizontally at 0,0, try others if the generated board is too weak
placeWord(wordArray[seed].word, wordArray[seed].displayWord, wordArray[seed].clue, 0, 0, false);
//attempt to fill the rest of the board
for (var iy = 0; iy < FIT_ATTEMPTS; iy++) { //usually 2 times is enough for max fill potential
for (var ix = 1; ix < wordArray.length; ix++) {
if (!isActiveWord(wordArray[ix].word)) { //only add if not already in the active word list
topScore = 0;
bestScoreIndex = 0;
suggestCoords(wordArray[ix].word); //fills coordList and coordCount
coordList = shuffleArray(coordList); //adds some randomization
if (coordList[0]) {
for (c = 0; c < coordList.length; c++) { //get the best fit score from the list of possible valid coordinates
fitScore = checkFitScore(wordArray[ix].word, coordList[c].x, coordList[c].y, coordList[c].vertical);
if (fitScore > topScore) {
topScore = fitScore;
bestScoreIndex = c;
}
}
}
if (topScore > 1) { //only place a word if it has a fitscore of 2 or higher
placeWord(wordArray[ix].word, wordArray[ix].clue, coordList[bestScoreIndex].x, coordList[bestScoreIndex].y, coordList[bestScoreIndex].vertical);
}
}
}
}
if(activeWordList.length < wordArray.length/2) { //regenerate board if if less than half the words were placed
seed++;
generateBoard(seed);
}
}
}
function seedBoard() {
gameboard = new board(GRID_WIDTH, GRID_HEIGHT);
gameboard.generateBoard();
gameboard.displayGrid();
}
मैं दो नंबर जेनरेट करूंगा: लंबाई और स्क्रैबल स्कोर। मान लें कि कम स्क्रैबल स्कोर का मतलब है कि इसमें शामिल होना आसान है (कम स्कोर = बहुत सारे सामान्य अक्षर)। सूची को लंबाई अवरोही और स्क्रैबल स्कोर आरोही द्वारा क्रमबद्ध करें।
अगला, बस सूची में नीचे जाएं। यदि शब्द किसी मौजूदा शब्द (क्रमशः उनकी लंबाई और स्क्रैबल स्कोर द्वारा प्रत्येक शब्द के खिलाफ जांच) के साथ पार नहीं करता है, तो इसे कतार में डालें, और अगले शब्द की जांच करें।
कुल्ला और दोहराएं, और यह एक क्रॉसवर्ड उत्पन्न करना चाहिए।
बेशक, मुझे पूरा यकीन है कि यह O (n!) है और यह आपके लिए क्रॉसवर्ड पूरा करने की गारंटी नहीं है, लेकिन शायद कोई इसे सुधार सकता है।
मैं इस समस्या के बारे में सोच रहा हूं। मेरी समझ में यह है कि वास्तव में घनीभूत क्रॉसवर्ड बनाने के लिए, आप यह आशा नहीं कर सकते कि आपकी सीमित शब्द सूची पर्याप्त होने वाली है। इसलिए, आप एक शब्दकोश लेना चाहते हैं और इसे "ट्राइ" डेटा संरचना में रख सकते हैं। यह आपको आसानी से उन शब्दों को खोजने की अनुमति देगा जो बाईं ओर रिक्त स्थान को भरते हैं। एक ट्राइ में, यह एक ट्रावेल को लागू करने के लिए काफी कुशल है, जो कहता है, आपको "सी-टी" फॉर्म के सभी शब्द देता है।
तो, मेरी सामान्य सोच यह है: कम घनत्व वाले क्रॉस को बनाने के लिए यहां वर्णित कुछ शब्दों के रूप में कुछ हद तक अपेक्षाकृत तेज बल दृष्टिकोण का निर्माण करें, और शब्दकोश शब्दों के साथ रिक्त स्थान भरें।
अगर किसी और ने यह तरीका अपनाया है, तो कृपया मुझे बताएं।
मैं क्रॉसवर्ड जनरेटर इंजन के आसपास खेल रहा था, और मुझे यह सबसे महत्वपूर्ण लगा:
0।!/usr/bin/python
ए। allwords.sort(key=len, reverse=True)
ख। जब तक आप बाद में यादृच्छिक विकल्प द्वारा पुनरावृति नहीं करना चाहते हैं, तब कुछ आइटम / ऑब्जेक्ट को कर्सर की तरह बनाएं जो कि आसान अभिविन्यास के लिए मैट्रिक्स के चारों ओर घूमेंगे।
पहले, पहले जोड़े को उठाएं और उन्हें 0,0 से नीचे और नीचे रखें; हमारे वर्तमान क्रॉसवर्ड 'लीडर' के रूप में पहले स्टोर करें।
आदेश विकर्ण या अगले खाली सेल के लिए अधिक विकर्ण संभावना के साथ यादृच्छिक चाल कर्सर
शब्दों पर पुनरावृति और अधिकतम शब्द लंबाई को परिभाषित करने के लिए मुक्त स्थान लंबाई का उपयोग करें:
temp=[]
for w_size in range( len( w_space ), 2, -1 ) :
# t
for w in [ word for word in allwords if len(word) == w_size ] :
#
if w not in temp and putTheWord( w, w_space ) :
#
temp.append( w )
मुक्त स्थान के खिलाफ शब्द की तुलना करने के लिए जिसका मैंने उपयोग किया है:
w_space=['c','.','a','.','.','.'] # whereas dots are blank cells
# CONVERT MULTIPLE '.' INTO '.*' FOR REGEX
pattern = r''.join( [ x.letter for x in w_space ] )
pattern = pattern.strip('.') +'.*' if pattern[-1] == '.' else pattern
prog = re.compile( pattern, re.U | re.I )
if prog.match( w ) :
#
if prog.match( w ).group() == w :
#
return True
सफलतापूर्वक उपयोग किए गए प्रत्येक शब्द के बाद, दिशा बदलें। लूप जबकि सभी कोशिकाएं भरी हुई हैं या आप शब्दों से बाहर या पुनरावृत्तियों की सीमा से भागते हैं:
# CHANGE ALL WORDS LIST
inexOf1stWord = allwords.index( leading_w )
allwords = allwords[:inexOf1stWord+1][:] + allwords[inexOf1stWord+1:][:]
... और फिर से नया क्रॉसवर्ड।
भरने की सहजता, और कुछ अनुमान बछड़ों द्वारा स्कोरिंग प्रणाली बनाएं। यदि वर्तमान स्कोर स्कोर आपके सिस्टम द्वारा संतुष्ट है, तो इसे वर्तमान वर्ग पहेली और संकीर्ण बाद की पसंद के लिए बनाए गए वर्ग पहेली की सूची में स्कोर दें।
पहले पुनरावृत्ति सत्र के बाद नौकरी खत्म करने के लिए किए गए वर्ग पहेली की सूची से फिर से पुनरावृति।
अधिक मापदंडों का उपयोग करके गति को एक विशाल कारक द्वारा सुधारा जा सकता है।
मुझे संभावित क्रॉस को जानने के लिए प्रत्येक शब्द द्वारा उपयोग किए जाने वाले प्रत्येक अक्षर का एक सूचकांक मिलेगा। तब मैं सबसे बड़ा शब्द चुनूंगा और इसे आधार के रूप में उपयोग करूंगा। अगले बड़े का चयन करें और इसे पार करें। धोये और दोहराएं। यह शायद एक एनपी समस्या है।
एक अन्य विचार एक आनुवंशिक एल्गोरिथ्म का निर्माण कर रहा है जहां ताकत मीट्रिक है कि आप ग्रिड में कितने शब्द डाल सकते हैं।
मेरे द्वारा पाया जाने वाला कठिन हिस्सा एक निश्चित सूची को जानना है जिसे संभवतः पार नहीं किया जा सकता है।
यह एआई CS50 पाठ्यक्रम में एक परियोजना के रूप में दिखाई देता है हार्वर्ड से । विचार यह है कि क्रॉसवर्ड पीढ़ी की समस्या को एक बाधा संतुष्टि समस्या के रूप में तैयार किया जाए और इसे खोज स्थान को कम करने के लिए विभिन्न उत्तराधिकारियों के साथ वापस हल किया जाए।
शुरू करने के लिए हमें कुछ इनपुट फ़ाइलों की आवश्यकता है:
`
###_####_#
____####_#
_##_#_____
_##_#_##_#
______####
#_###_####
#_##______
#_###_##_#
_____###_#
#_######_#
##_______#
`
एक इनपुट शब्दावली (शब्द सूची / शब्दकोश) जिसमें से उम्मीदवार शब्द चुने जाएंगे (जैसे दिखाए गए एक प्रकार)।
a
abandon
ability
able
abortion
about
above
abroad
absence
absolute
absolutely
...
अब सीएसपी को परिभाषित किया गया है और निम्नानुसार हल किया जा सकता है:
निम्नलिखित CSP हल एल्गोरिथ्म के कार्यान्वयन का उपयोग करके प्राप्त किया गया आउटपुट दिखाता है:
`
███S████D█
MUCH████E█
E██A█AGENT
S██R█N██Y█
SUPPLY████
█N███O████
█I██INSIDE
█Q███E██A█
SUGAR███N█
█E██████C█
██OFFENSE█
`
निम्नलिखित एनीमेशन पीछे के चरणों को दर्शाता है:
यहाँ बंगला (बंगाली) भाषा शब्द-सूची के साथ एक और है:
मैंने इस समस्या का एक जावास्क्रिप्ट / jQuery समाधान कोडित किया है:
नमूना डेमो: http://www.earthfluent.com/crossword-puzzle-demo.html
सोर्स कोड: https://github.com/HoldOffHunger/jquery-crossword-puzzle-generator
मैं इस्तेमाल किया एल्गोरिथ्म का इरादा:
मैं उपयोग किए गए एल्गोरिदम का वर्णन करूंगा:
उन शब्दों को एक साथ समूहित करें जो एक आम पत्र साझा करते हैं।
इन समूहों से, एक नई डेटा संरचना ("शब्द ब्लॉक") के सेट का निर्माण करते हैं, जो एक प्राथमिक शब्द है (जो सभी अन्य शब्दों से चलता है) और फिर अन्य शब्द (जो प्राथमिक शब्द के माध्यम से चलते हैं)।
क्रॉसवर्ड पहेली के शीर्ष-बाएँ स्थिति में इन शब्द ब्लॉकों में से सबसे पहले क्रॉसवर्ड पहेली को शुरू करें।
शेष शब्द ब्लॉक के लिए, क्रॉसवर्ड पहेली के दाईं ओर सबसे नीचे की ओर से शुरू करते हुए, ऊपर की ओर और बाईं ओर आगे बढ़ें, जब तक कि भरने के लिए अधिक उपलब्ध स्लॉट न हों। यदि बाईं ओर से अधिक खाली स्तंभ हैं, तो ऊपर की ओर बढ़ें, और इसके विपरीत।
var crosswords = generateCrosswordBlockSources(puzzlewords);
। बस कंसोल इस मान को लॉग इन करें। मत भूलो, गेम में एक "चीट-मोड" है, जहां आप तुरंत "रिवील आंसर" पर क्लिक कर सकते हैं, ताकि तुरंत मूल्य मिल सके।