PostgreSQLUncategorized

Jogando Termo com Postgres

Esses dias, no meio do happy hour da Timbira, estava comentando da última partida de Termo, que virou mania recentemente. Aí uma colega perguntou qual a palavra você utiliza para começar o jogo? Após ver que o nosso expert Guedes já pegou o dicionário para brincar no banco de dados, resolvi responder à pergunta com um pouco de SQL e brincar também!

Preparação

Vejamos como começar… o jogo Termo tem uma página onde ele diz que utiliza um dicionário com licença livre, disponível aqui. Então, basta baixar o dicionário e importar no seu banco de dados (aqui estou fazendo com PostgreSQL, mas com algumas diferenças, você pode fazer em outros bancos de dados, claro):

CREATE TABLE palavras (p text);
COPY palavras(p) FROM '/tmp/palavras.txt' ;

Ou seja, criei uma tabela chamada palavras com uma única coluna chamada p e importei os dados nela. Simples e rápido.

Depois resolvi filtrar apenas as palavras com 5 letras:
SELECT p FROM palavras WHERE length(unaccent(p)) = 5;
Notem aqui que eu utilizei a função unaccent, pois palavras acentuadas podem contar como mais de 1 byte.

Brincando

Agora como seria saber quais palavras começam com TOR e terminam com A?

SELECT p 
FROM palavras
WHERE
    length(unaccent(p)) = 5 AND
    unaccent(p) LIKE 'tor_a';

p
-----
torda
torba
torga
torma
torna
torra
torsa
torta
torva
torça
tória
(11 rows)

Já dá pra ver que é possível brincar bastante com isso.

Agora uma contribuição do nosso colega Guedes que eu tomei a liberdade de adaptar para o meu exemplo aqui. Quais são as letras mais utilizadas na primeira posição da palavra?

SELECT 
    substring(unaccent(p) FROM 1 FOR 1) letra,
    count() qt, 
    repeat('█', (count()/40)::int) "%"
FROM palavras
WHERE length(unaccent(p)) = 5
GROUP BY 1
ORDER BY 2 DESC;

l |  qt  | %
--+------+------------------------------------------------------------
a | 2255 | ████████████████████████████████████████████████████████
c | 1623 | ████████████████████████████████████████
p | 1354 | █████████████████████████████████
m | 1347 | █████████████████████████████████
b | 1156 | ████████████████████████████
t | 1151 | ████████████████████████████
s | 1127 | ████████████████████████████
r | 1007 | █████████████████████████
f | 929  | ███████████████████████
l | 869  | █████████████████████
g | 86 7 | █████████████████████
e | 746  | ██████████████████
d | 690  | █████████████████
v | 613  | ███████████████
o | 610  | ███████████████
i | 598  | ██████████████
n | 575  | ██████████████
u | 413  | ██████████
j | 361  | █████████
z | 271  | ██████
h | 259  | ██████
x | 160  | ████
q | 82   | ██
k | 11   |
w | 5    |
y | 3    |
(26 rows)

Melhor palavra para começar

E agora, para responder à pergunta da minha colega… eu quero saber primeiro quais são as 5 letras mais utilizadas no dicionário?

SELECT l, count(1) AS q
FROM
    palavras,
    (SELECT CHR(i) AS l FROM generate_series(97,122) AS l(i)) AS letra
WHERE p ~ l
GROUP BY l
ORDER BY q DESC
LIMIT 5;

l | q
---+--------
a | 942848
e | 808949
r | 720964
s | 714080
i | 703338
(5 rows)


Agora que eu já sei que são as letras A, E, R, S e I, vou procurar palavras que tenham apenas estas 5 letras:

SELECT p
FROM palavras
WHERE
    length(unaccent(p)) = 5
AND unaccent(p) LIKE '%a%'
AND unaccent(p) LIKE '%e%'
AND unaccent(p) LIKE '%i%'
AND p LIKE '%r%'
AND p LIKE '%s%'
;
p-----aires
areis
eiras
erais
reais
ieras
rasei
raies
sairé
sarei
áries
seira
seria
érias
(14 rows)

E aí, vamos jogar?

SELECT p
FROM palavras
WHERE
    length(unaccent(p)) = 5
and unaccent(p) LIKE 'cai_a%'
and p not like '%s%'
and p not like '%r%'
and p not like '%n%'
and p not like '%g%'
and p not like '%m%'
and p not like '%t%'
and p not like '%p%'
and p not like '%l%'
and p not like '%f%'
and p not like '%x%'
and p not like '%b%';
    p
---------
 caída
 caiuá
 caiçá
 caíva
(4 rows)

Leave a Reply

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.