Permutacje po polsku

https://xpil.eu/8nkMe

Niedawno pokaza艂em jak z bazy s艂贸w j臋zyka polskiego powyci膮ga膰 s艂owa z unikalnymi ko艅c贸wkami. Dzisiaj kontynuuj臋 zabaw臋 z t膮 sam膮 baz膮 s艂贸w, tym razem jednak poka偶臋 jak znale藕膰 wszystkie permutacje siedmioliterowe nale偶膮ce do s艂ownika. Innymi s艂owy, taki dopalacz do gry w Scrabble / Literaki, pomagaj膮cy znale藕膰 wszystkie siedmioliterowe (a wi臋c wysoko punktowane) s艂owa z danego zestawu liter.

Dla uproszczenia przyj膮艂em brak myde艂 (czyli pustych p艂ytek zwanych te偶 "blankami" lub "jokerami").

W pierwszej kolejno艣ci nale偶y przygotowa膰 sobie baz臋 ze s艂贸wkami, wed艂ug zalece艅 z tego wpisu. Nast臋pnie tworzymy pust膮 tabel臋, do kt贸rej b臋dziemy generowa膰 wszystkie permutacje siedmioliterowe (b臋dzie ich zawsze 5040). Tablica nazywa si臋 [permutacje] i tworzymy j膮 o tak:

CREATE TABLE permutacje(s char(7) NOT NULL);

Nast臋pnie deklarujemy i inicjalizujemy zmienn膮 reprezentuj膮c膮 s艂owo, kt贸re b臋dziemy permutowa膰:

DECLARE @s VARCHAR(7)= 'niemowa';

W kolejnym kroku zerujemy tabel臋 z permutacjami:

TRUNCATE TABLE permutacje;

No i teraz samo g臋ste, czyli wype艂niamy tabel臋 [permutacje] wszystkimi siedmioliterowymi permutacjami liter s艂owa 'niemowa':

WITH

n AS

(SELECT 1 AS liczba UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7),

perm AS

(SELECT

CAST(SUBSTRING(@s, liczba, 1) AS VARCHAR(7)) AS anagram,

CAST('.'+CAST(liczba AS CHAR(1))+'.' AS VARCHAR(13)) AS uklad,

CAST(1 AS INT) AS poziom

FROM n

UNION ALL

SELECT

CAST(anagram+SUBSTRING(@s, liczba, 1) AS VARCHAR(7)),

CAST(uklad+CAST(liczba AS CHAR(1))+'.' AS VARCHAR(13)),

p.poziom + 1

FROM

perm p

JOIN n

ON p.uklad NOT LIKE '%.'+CAST(liczba AS CHAR(1))+'.%'

AND p.poziom < 7

)

INSERT permutacje

SELECT DISTINCT anagram

FROM perm

WHERE poziom = 7

ORDER BY anagram;

W ostatnim kroku wy艣wietlamy wynik, czyli te permutacje, kt贸re s膮 s艂owami j臋zyka polskiego:

SELECT slowo FROM words JOIN permutacje ON words.slowo=permutacje.s;

Ca艂o艣膰 wykonuje si臋 bardzo szybko (poni偶ej jednej sekundy).

Wyniki: aminowe, emanowi, manowie, miewano, moweina, namowie, niemowa.

Je偶eli kt贸rykolwiek z Czytelnik贸w dotar艂 a偶 do tego miejsca bez b贸lu g艂owy, a jeszcze, nie daj Billu, zrozumia艂 spos贸b generowania permutacji, zapraszam do kolejnego wysi艂ku umys艂owego: jak do powy偶szej logiki doda膰 blanki? Przypominam, 偶e zar贸wno w Scrabble (TM) jak i w Literakach mo偶liwe s膮 maksymalnie dwa blanki.

https://xpil.eu/8nkMe

5 komentarzy

  1. je艣li blakni = char(32), to @s='nie mowa', rozszerzenie pól [zamian 7 na 8]. Od varcharów odchodzi膰 nie trzeba, bo blanki na ko艅cu si臋 nie licz膮.

    Aczkolwiek nie wiem, czy ostatni join tego nie wytnie.

    1. Nie mo偶e by膰 osiem – na stojaku zawsze jest siedem liter (z czego maksymalnie dwa blanki). W zale偶no艣ci od tego czy jest jeden blank czy dwa, ilo艣膰 mo偶liwych permutacji ro艣nie 32-krotnie lub 1024-krotnie (a wi臋c w najgorszym przypadku mamy troch臋 ponad 5 milionów permutacji).

      Mam ju偶 dzia艂aj膮ce rozwi膮zanie, ale strasznie si臋 艣limaczy. 22 sekundy na wyszukanie wszystkich "legalnych" s艂ówek z dwoma blankami i jakie艣 3 sekundy z jednym.

      1. Nie gram w Scramble czy inne sudoku z ca艂kami [jak mówi Kowalski], wi臋c musisz bardziej 艂opatologicznie wy艂o偶y膰 problem. Blank mo偶e zast膮pi膰 dowoln膮 liter臋?
        Je艣li tak, to wynik bez blanków potraktowa艂bym jako materia艂 wej艣ciowy do kolejnej p臋tli a tam [x:1-7; dla ka偶dego z wyników]
        SELECT slowo FROM words
        where words.slowo like
        permutacje ON like left(permutacje.s,x)+'_'+right(permutacje.s,6-x);

Leave a Comment

Komentarze mile widziane.

Je偶eli chcesz do komentarza wstawi膰 kod, u偶yj sk艂adni:
[code]
tutaj wstaw sw贸j kod
[/code]

Je偶eli zrobisz liter贸wk臋 lub zmienisz zdanie, mo偶esz edytowa膰 komentarz po jego zatwierdzeniu.