Esses dias, no meio do happy hour, 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:
Notem aqui que eu utilizei a função unaccent, pois palavras acentuadas podem contar como mais de 1 byte.
SELECT p FROM palavras WHERE length(unaccent(p)) = 5;
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)