4

Such problem was given me at my university, maybe someone will have interesting algorithm how to solve the problem. There're several solutions for it on stackoverflow, but none of them is ok (because they're looping for all possibilities).

Problem: Find all possible combinations for allocating given words into given table, grid ( rectangular, see input below ). There should be no free cells and word can be located from left to right or up to down. Words can't be located word after word in a row (column).

Input: rectangular area, example:

+-----+
|  *  | 
|     |
+-----+

or

+-----+
|   * |
|     |
|    *|
|   * |
+-----+

Then after that different words are typed ( next input data ) to fill that grid such as:

cdi
zobxzst
tdxic
r
sc
zro
and etc ...

Number is initially unknown but inputs until end of stdin - active EOF.

Output: if one solution exists then output that possible solution within filled grid. If no solution or number of solutions then output 0 or that exact number.

Example:

(table inputted)

+-----+
|   * |
|     |
|    *|
|   * |
|  * *|
|  *  |
|     |
+-----+

Then words cdi zobxzst tdxic r sc zro rgfvacd oikf df x c r xvf ogish za sh fc hh h bfkh

(Each as input, but here separated by spaces.)

Output ( 1 solution only ):

+-----+
|zro*h|
|ogish|
|bfkh*|
|xvf*r|
|za*c*|
|sc*df|
|tdxic|
+-----+

Important note: The inputted grid is limited by 16 (!) cells only, number of words is less than 60. I wrote an algorithm which search through all possible combinations but it didn't work for me as execution time is limited (by 10 sec I guess) and this problem couldn't be solved with rough algorithm ( e.g. 15 on 15 grid and about 60! possible or more possible permutations which can be processed about 1 day? on ordinary 2GHz PC ).

Maybe there exists another unique solution. Maybe this problem is more mathematic then programming, maybe possible to use some left-right combos compared with up-down? or maybe weighted cells?

P.S. I have 3 weeks to solve that problem, if not, I can post solution here after 3 weeks ( good news ) ;)

NGix
  • 2,542
  • 8
  • 28
  • 39
  • 1
    These "words" you're using, `cdi`, `zobxzst`, `tdxic`, I do not think they mean what you think they mean. :) – James Kolpack Nov 13 '12 at 00:26
  • 2
    @JamesKolpack Inconceivable! – Eitan T Nov 13 '12 at 00:30
  • 1
    @luiges90 It marks a space on the grid where you're not allowed to place any word. – ChrisW Nov 13 '12 at 00:33
  • I would separate the words in, n, n-1 n-2, ... 1 size groups where n represents the max length allowed by the rectangle (heights), all the words with more than n letters are excluded from the list. After that step the combinations starts I can't think in anything else than brute force – Alberto Bonsanto Nov 13 '12 at 00:43
  • Also the worst case here has far more than 15! possibilities. When the words are {a, a, b, b, c, c, ..., z, z} and the grid is just 26 isolated cells, there are 26! ~= 4e26 solutions. You get slightly more if you pad the word list out to sixty words with 4 extra single letter word pairs and have 30 cells, but I can't be bothered doing the math. :) – verdesmarald Nov 13 '12 at 00:44
  • 2
    @Ir0nm The "ordinary 2Hz PC" made my day ;) Greetings Time Traveller! – das_weezul Nov 13 '12 at 00:59
  • Omg Lool ;)) should leave it for fun.) – NGix Nov 13 '12 at 01:08
  • Gee, a fellow CTU FIT student. Gradually reducing the number of possible word placements for every crossword field through some sort of constraint propagation might be the key here, that's what I'm going to try. The space complexity of such a tree might be prohibitive though. Oh and by the way, I find this attempt to get outside help on a contest problem despicable. – Daniel Maly Dec 08 '12 at 10:45

2 Answers2

2

There're several solutions for it on stackoverflow, but none of them is ok (because they're looping for all possibilities).

My idea is probably wrong as well then: but here's an idea off the top of my head.

I wrote an algorithm which search through all possible combinations

If there are too many, then the problem is probably that you are also searching/looping through impossible combinations as well as possible combination.

For example when you place a word like "zro" in the top-left corner, there are very few "possible" combinations which can be placed in the vertical words below it:

  1. the first vertical word must begin with 'z'
  2. the second vertical word must begin with 'r'
  3. the third vertical word must begin with 'o'
  4. The combinations of letters on the second row (resulting from placing the vertical words) must itself be a valid word
  5. etc.

Therefore:

  1. Pick any word and place it in the top-left corner
  2. Find existing words which satisfy the constraints above
  3. If you find one or more such words, then continue in this way to see whether you can solve the whole thing; or if you fail, then try again using a different initial word

Summary:

  • Don't generate every complete grid, and then test it to see whether it satisfies all constraints
  • Instead use the constraints as you build the grid, to reduce the number of possibilities that you test

I'm suggesting that you solve the grid, starting from an initial word.

Instead of testing each words in the top-left corner, a better (e.g. because it moe quickly eliminates impossibilities) way to generate the starting position[s] is:

  • Find the longest word (e.g. rgfvacd)
  • Find all possible combinations of words which cross/join it
  • Try to place each of those valid combinations on the grid
ChrisW
  • 54,973
  • 13
  • 116
  • 224
  • Yes it's like set theory, when the program tries a word in a row or column the possible other words in other positions is reduced, so in fact the problem is not to find several solutions is to find a solution which fits the cross-board by my point of view. – Alberto Bonsanto Nov 13 '12 at 01:20
  • @AlbertoBonsanto the field/area of mathematics might (I'm not sure) be called "combinatorics with constraints". – ChrisW Nov 13 '12 at 01:26
1

I suggest that you first should see what lengths of words you have to fill, in your example:

+-----+
|   * |
|     |
|    *|
|   * |
|  * *|
|  *  |
|     |
+-----+

you have two 7 letter words, three 1 letter word, etc.

you should sort this list according to the count and first try with the wrod lengths with the lowest count, in the next iteration you should make a list of what word you need to find for example - three 4 letter words that start with 'a' - you should count how many of these words you have left in your word list, and then choose the one with the least words in it - if it's 0 then return.

hope it makes sense.

zenpoy
  • 19,490
  • 9
  • 60
  • 87