pmaher86 / blacksquare

A Python package for crossword creators.
MIT License
38 stars 13 forks source link

Incorrect numbering for words #19

Closed fra87 closed 10 months ago

fra87 commented 11 months ago

Hello

I found an issue with this library.

When there is a word followed by a black, a letter and a black (because that letter is part of a down word) then the word is not calculated correctly.

Here is a minimum example:

from blacksquare import *

grid = [['#', '#', '#', '#', 'A'],
        ['B', 'A', 'D', '#', 'C'],
        ['#', '#', '#', '#', 'E']]

xw =  Crossword(grid=grid)

xw.pprint(numbers=True)
xw.pprint()
for x in xw.iterwords(ACROSS):
    print(x)

This script outputs:


┌───┬───┬───┬───┬───┐
│███│███│███│███│1  │
├───┼───┼───┼───┼───┤
│2  │   │   │███│   │
├───┼───┼───┼───┼───┤
│███│███│███│███│   │
└───┴───┴───┴───┴───┘
┌───┬───┬───┬───┬───┐
│███│███│███│███│^A │
├───┼───┼───┼───┼───┤
│^B │ A │ D │███│ C │
├───┼───┼───┼───┼───┤
│███│███│███│███│ E │
└───┴───┴───┴───┴───┘
Word(Across 2: "BADC)"

As you can see, the library correctly numbers the words, but then assigns the 'C' letter to word Across 2.

In fact, this is because the _parse_grid function incorrectly labels the cells. This is the value of xw._across in the previous example:

[[0 0 0 0 0]
 [2 2 2 0 2]
 [0 0 0 0 0]]

This is even worse when not providing a pre-filled grid. For instance in this similar example:

xw = Crossword(3,9)
for x in [(0,0), (0,1), (0,2), (0,3), (1,3), (2,0), (2,1), (2,2), (2,3)]:
    xw[x] = BLACK
xw.pprint(numbers=True)

which generates this crossword:

┌───┬───┬───┬───┬───┬───┬───┬───┬───┐
│███│███│███│███│1  │███│███│███│███│
├───┼───┼───┼───┼───┼───┼───┼───┼───┤
│2  │   │   │███│   │███│3  │   │   │
├───┼───┼───┼───┼───┼───┼───┼───┼───┤
│███│███│███│███│   │███│███│███│███│
└───┴───┴───┴───┴───┴───┴───┴───┴───┘

In this case, you will not be able to ever write across 2. The word is a 4 chars one, since xw._words is

{(<Across>, 2): Word(Across 2: "????)", (<Across>, 3): Word(Across 3: "???)", (<Down>, 1): Word(Down 1: "???)"} 

so if I try to write xw[ACROSS, 2] = 'bad' I will get a ValueError in crossword.py, line 500 because the length mismatch. If I try to pad it with chars, however (for instance writing xw[ACROSS, 2] = 'badt' I will get an IndexError in crossword.py, line 104 (triggered from line 516 in the same file).

This is as far as I managed to dig in the code.

Do you think this can be solved?

pmaher86 commented 10 months ago

Thanks, will take a look at this. I suspect it's related to attempts to handle cryptic style numbering

pmaher86 commented 10 months ago

Thanks again for writing this up, it's now fixed