Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Algorithm for crossword puzzle with given grid [closed]

Before I write something about the problem, I need to let you know:

  1. This problem is my homework (I had about 1 week to return working program)
  2. I was working on this problem for about a week, every day, trying to figure out my own solution
  3. I'm not asking for complete program; I need a general idea about the algorithm

Problem:

Given: a wordlist and a "grid", for example:

grid (X means any letter):

X X 
XXXX
X X
XXXX

wordlist:

ccaa
baca
baaa
bbbb

You have to find example "solution" - is it possible to fit words from wordlist into a given grid? If there is at least one solution, print one (whichever correct). If no - print message, that there is no possible solution. For given example, there is a solution:

b c 
baca
b a 
baaa

It's hard for me to write everything that I've already tried (because English is not my native language and I also have a lot of papers with wrong ideas).

My naive algorithm works something like this:

  1. First word needs just proper length, so find any (first?) word with proper length (I'm going to use given example grid and wordlist to demonstrate what I think):

    c X 
    cXXX
    a X
    aXXX
    
  2. For first common letter (on the crossing of 2 words) find any (first) word, that fit the grid (so, have proper length and common letter on proper position). If there is no such words, go back to (1) and take another first word. In the orginal example there is no word which starts with "c", so we go back to (1) and select next words (this step repeats few times until we have "bbbb" for 1st word). Now we have:

    b X 
    bXXX
    b X
    bXXX
    

    And we're looking for a word(s) which starts with "b", for example:

    b X 
    baca
    b X
    bXXX
    
  3. General process: try to find pairs of words which fit to the given grid. If there is no such words, go back to previous step and use another combination - if there is no such - there is no solution.

Everything above is chaotic, I hope that you understand at least problem description. I wrote a draft of an algorithm, but I'm not sure if that works and how to properly code this (in my case: c++). Moreover, there are cases (even in example above) that we need to find a word that depends on 2 or more other words.

Maybe I just can't see something obvious, maybe I'm too stupid, maybe... Well, I really tried to solve this problem. I don't know English well enough to precisely describe what I think about this problem, so I can't put here all my notes (I tried to describe one idea and it was hard). Believe or not, I've spend many long hours trying to figure out solution and I have almost nothing...

If you can describe a solution, or give a hint how to solve this problem, I would really appreciate this.

like image 337
exTyn Avatar asked Dec 21 '11 04:12

exTyn


2 Answers

The corssword problem is NP-Complete, so your best shot is brute force: just try all possibilities, and stop when a possibility is a valid. Return failure when you exhausted all possible solutions.

reduction that prove that this problem is NP-Complete can be found in this article section 3.3

Brute force solution using backtracking could be: [pseudo code]:

solve(words,grid):
   if words is empty:
       if grid.isValudSol():
          return grid
       else:
          return None
   for each word in words:
       possibleSol <- grid.fillFirst(word)
       ret <- solve(words\{word},possibleSol)
       if (ret != None):
          return ret
   return None

in here we assume fillFirst() is a function that fills the first space which was not already filled [first can actually be any consistent ordering of the empty spaces, but it should be consistent!] , and isValid() is returning a boolean indicating if the given grid is a valid solution.

like image 126
amit Avatar answered Sep 20 '22 12:09

amit


I wrote a progam this morning. Here is a slightly more efficient version in pseudocode:

#pseudo-code
solve ( words , grid ) : solve ( words , grid , None ) 

solve ( words , grid , filledPositions ) :
    if words is empty :
        if grid is solved :
            return grid
        else :
            raise ( no solution )
    for ( current position ) as the first possible word position in grid 
            that is not of filledPositions :
        # note : a word position must have no letters before the word
            # 'before the word' means, eg, to the left of a horizontal word
            # no letters may be placed over a ' ' 
            # no letters may be placed off the grid
        # note : a location may have two 'positions' : one across , one down
        for each word in words :
            make a copy of grid
            try :
                fill grid copy, with the current word, at the current position
            except ( cannot fill position ) :
                break
            try :
                return solve ( words\{word} , grid copy , 
                        filledPositions+{current position} )
            except ( no solution ) :
                break
        raise ( no solution )

Here is my code for fitting a word horizontally in the grid : http://codepad.org/4UXoLcjR

Here are some things I used from the STL:

http://www.cplusplus.com/reference/algorithm/remove_copy/

http://www.cplusplus.com/reference/stl/vector/

like image 40
Gavin Haynes Avatar answered Sep 18 '22 12:09

Gavin Haynes