Het oog van Leonard Gordon viel op een interessant patroon. De Engelse namen van de eerste acht strikt positieve natuurlijke getallen (ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT) bevatten in totaal 32 letters. Het kleinste rechthoekig rooster waarin ze woordzoeker-gewijs kunnen verpakt worden, is een $$5 \times 5$$ rooster. De 32 letters passen in de 25 cellen van het rooster omdat sommige cellen dubbel gebruikt worden. De verhouding van deze waarden is \[ \frac{32}{25} = 1.28 \] Deze verhouding blijft nagenoeg dezelfde naarmate de lijst met getallen uitgebreid wordt. Hier zijn de roosters voor de eerste acht, negen, tien, elf en twaalf getallen:

E I G H T   O N E E R H T   E I G H T F   E L E V E N S   S E V E N O W T
F O U R W   S E V E N I N   F   X   W O   I   F S O I E   F I V E E R H T
X I S   O   E I G H T W O   N I N E O U   G   O I T N V   O G X N E N I N
S E V E N   F O U R X I S   S E V E N R   H W U X V E E   U H E V L E W T
T H R E E                   T H R E E     T H R E E E N   R T N E V E L E

 8 getallen  9 getallen     10 getallen   11 getallen     12 getallen
32 letters  36 letters      39 letters    45 letters      51 letters
25 cellen   28 cellen       30 cellen     35 cellen       40 cellen
(1.28)      (1.29)          (1.30)        (1.29)          (1.28)

Helaas is het laatste rooster niet optimaal, merkt Gordon op. De getallen ONE tot en met TWELVE passen in een kleiner rooster

T W E L V E
F N E X S L
O F I V E E
U S G N V V
R T H R E E
O W T E N N

… en dat drijft de compactheid op naar 1.42 letters per cel.

Opgave

We stellen een rooster met letters voor als een lijst (list) met de rijen van het rooster, opgelijst van boven naar onder. Elke rij wordt zelf voorgesteld als een lijst (list) met de opeenvolgende letters (str) opgelijst van links naar rechts.

Om naar de cellen van een rooster met letters te kunnen verwijzen, worden de rijen van boven naar onder genummerd en de kolommen van links naar rechts, telkens vanaf nul. Op die manier kan de positie van een cel voorgesteld worden als een tuple $$(r, k)$$, waarbij $$r$$ het rijnummer aanduidt en $$k$$ het kolomnummer.

In het rooster kunnen woorden horizontaal, verticaal en diagonaal in acht mogelijk richtingen uitgelezen worden. Elke richting wordt voorgesteld als een string (str) met één of twee hoofdletters, overeenkomstig de windrichtingen. Bijvoorbeeld de richting W voor woorden die naar het westen uitgelezen worden (van rechts naar links), of de richting NO voor woorden die naar het noordoosten uitgelezen worden (van linksonder naar rechtsboven).

richtingen
Net zoals in een woordzoeker kunnen de woorden horizontaal, verticaal en diagonaal in acht verschillende richtingen uitgelezen worden.

Als we in onderstaand rooster bijvoorbeeld drie letters uitlezen vanaf cel $$(0, 5)$$ in westelijke richting (W), dan krijgen we de letters van het woord ONE. Als we drie letters uitlezen vanaf cel $$(4, 1)$$ in noordoostelijke richting (NO), dan krijgen we de letters van het woord TEN.

woorden
Als we in dit rooster drie letters uitlezen vanaf de cel $$(0, 5)$$ in westelijke richting (W), dan krijgen we de letters van het woord ONE. Als we drie letters uitlezen vanaf de cel $$(4, 1)$$ in noordoostelijke richting (NO), dan krijgen we de letters van het woord TEN.

Gevraagd wordt:

Alle functies mogen ervan uitgaan dat er enkel geldige argumenten aan doorgegeven worden, zonder dat dit expliciet moet gecontroleerd worden.

Voorbeeld

>>> rooster = verpak('EIGHTFOURWXISMOSEVENTHREE', 5)
>>> rooster
[['E', 'I', 'G', 'H', 'T'], ['F', 'O', 'U', 'R', 'W'], ['X', 'I', 'S', 'M', 'O'], ['S', 'E', 'V', 'E', 'N'], ['T', 'H', 'R', 'E', 'E']]

>>> letters(3, (2, 4), 'Z', rooster)
'ONE'
>>> letters(3, (0, 4), 'Z', rooster)
'TWO'

>>> voorkomens('ONE', rooster)
{'2,4Z'}
>>> voorkomens('TWO', rooster)
{'0,4Z'}
>>> voorkomens('THREE', rooster)
{'4,0O'}
>>> voorkomens('FOUR', rooster)
{'1,0O'}
>>> voorkomens('FIVE', rooster)
{'1,0ZO'}
>>> voorkomens('SIX', rooster)
{'2,2W'}
>>> voorkomens('SEVEN', rooster)
{'3,0O'}
>>> voorkomens('EIGHT', rooster)
{'0,0O'}
>>> voorkomens('NINE', rooster)
set()
>>> voorkomens('EN', rooster)
{'3,3O', '4,3NO', '4,4N'}

>>> compactheid(['ONE', 'TWO', 'THREE', 'FOUR', 'FIVE', 'SIX', 'SEVEN', 'EIGHT'], rooster)
1.28
>>> compactheid(['ONE', 'TWO', 'THREE', 'FOUR', 'FIVE', 'SIX', 'SEVEN', 'EIGHT', 'NINE'], rooster)
-1.0

Bronnen