Víctor López Ferrando

Entenimentadament: la paraula més llarga del Paraulògic

28 d’octubre de 2022

Fa un any que es va publicar el Paraulògic, i s'ha convertit en el joc de referència de l'internet en català.

Paraulògic del 25 d'octubre de 2022

Cada dia ens proposen un joc nou, i les normes són senzilles:

  • Cal formar paraules amb aquestes lletres. Les lletres es poden repetir.
  • La lletra del mig és obligatòria.
  • Les paraules han de tenir un mínim de 3 lletres.

A més, hi ha una particularitat:

  • Cada joc inclou almenys un 'tuti' en què s'usen totes les lletres.

Com a participant habitual del Paraulògic, sovint m'he preguntat sobre els límits del joc:

  1. Quants Paraulògics diferents hi ha?
  2. Quin Paraulògic té més tutis?
  3. Quina és la paraula que dona més punts?
  4. Quants tutis de només 7 lletres hi ha?
  5. Quin Paraulògic té menys paraules?
  6. Quin Paraulògic té més paraules? I quin dona més punts?

Com a bon informàtic, he escrit un programa que respon totes aquestes preguntes.

A continuació comparteixo alguns retalls del codi en Python que he escrit. El codi complet és públic a aquesta llibreta de Google Colab. Allà podeu executar-lo vosaltres mateixos.

Prèvia 1: Obtenir la llista de paraules

La part més farragosa de l'anàlisi que volem fer és la d'obtenir una llista de totes les paraules del DIEC. Estalviaré els detalls, però podeu descarregar la llista aquí: paraules.txt.

Comencem, per tant, llegint les paraules:

diec = open("paraules.txt").read().splitlines()

El primer que hem de fer és normalitzar les paraules, és a dir, fer tot un seguit de simplificacions:

  • Treure els accents i dièresis: ànec → anec, roïna → roina.
  • Treure el punt volat i guions: al·lot → allot, ziga-zaga → zigazaga.
  • Treure els sufixos -re, -se: cruspir-se → cruspir.
  • Treure els prefixos "en ", "a ", "de ": en vist → vist, de sotamà → sotama.

Ho podem fer amb la següent funció:

def normalitza(s):
    taula_normalitzacio = str.maketrans("àèòéíóúäïöüî", "aeoeiouaioui")
    return (
        s.translate(taula_normalitzacio)
        .replace('-se', '')
        .replace('en ', '')
        .replace('al ', '')
        .replace('de ', '')
        .replace('a ', '')
        .replace('·', '')
        .replace('-', '')
        .replace(' ', '')
    )

A continuació, apliquem aquesta funció a totes les paraules del diccionari:

normalitzades = set(map(normalitza, diec))

Com que el Paraulògic no admet paraules de menys de 3 lletres, ni tampoc aquelles que tenen més de 7 lletres diferents, les excloem de la nostra llista:

paraules = sorted([
    p for p in normalitzades if len(set(p)) <= 7 and len(p) >= 3])

Ara ja comptem amb una llista de paraules amb què treballar.

Prèvia 2: Com trobar les solucions d'un Paraulògic

Per representar un Paraulògic emprarem un format molt senzill, separant la lletra central de les altres sis amb un signe positiu. Per exemple, f+andorg.

Trobar totes les paraules que podem formar amb aquest Paraulògic és fàcil. Ho podem fer amb aquesta funció:

def solucions(paraulogic):
    return [
        paraula
        for paraula in paraules
        if paraulogic[0] in paraula and set(paraulogic).issuperset(paraula)
    ]

Provem amb un exemple:

solucions("f+andorg")

afanada, afanador, afanadora, afanar, afogar, àfon, àfona, afonar,
aforada, aforador, aforadora, aforar, agafada, agafador, agafadora,
agafar, agarrofar-se, àgraf, àgrafa, anàfora, andròfor, fada, fadador,
fadadora, fadar, fador, fan, fandango, fanfara, fanfarró, fanfarrona,
fanfarronada, fang, fanga, fangada, fangador, fangadora, fangar,
far, farad, faraó, faraona, farda, fàrfara, farga, fargar, faró,
farro, fofa, fofo, fogar, fogó, fogona, fogonada, fogor, fon, fona,
fonador, fonadora, fonar, fonda, fondo, fong, fongo, fonó, fonògraf,
fora o forà, forada, foradada, foradador, foradadora, foradar,
forana, forn, fornada, forra, forro, fra, fraga, fragor, frarada,
fraró, fronda, gafa, gafarda, gafarró, garrafa, garrafó, garrofa,
garrofó, gofrar, gonfanó, graf, nafra, nafrar, en off

Noteu que aquesta llista de paraules està desnormalitzada (apareixen accents). El codi per obtenir aquesta llista és una mica més elaborat i he preferit ometre algunes parts per facilitar-ne la comprensió. Com he comentat abans, podeu trobar el codi complet aquí.

Un cop hem aconseguit solucionar el Paraulògic, passem a respondre les preguntes que hem plantejat inicialment.

1. Quants Paraulògics diferents hi ha?

Els Paraulògics estan limitats pel nombre de tutis, ja que necessitem que n'hi hagi un entre les solucions. Calcular quants tutis hi ha és molt fàcil:

>>> tutis = [p for p in paraules if len(set(p)) == 7]
>>> f"Hi ha {len(tutis):3,} tutis."

Hi ha 17,828 tutis.

Però molts d'aquests tutis compartiran les mateixes lletres. Vegem quantes combinacions diferents de 7 lletres formen:

>>> tutis_diferents = set(frozenset(t) for t in tutis)
>>> f"Que formen {len(tutis_diferents):3,} combinacions de 7 lletres"

Que formen 6,800 combinacions de 7 lletres

Per últim, tindrem 7 Paraulògics diferents per cadascuna d'aquestes 6.800 combinacions, car podem triar quina de les 7 lletres volem que sigui la central:

>>> f"Per tant, hi ha {7*len(tutis_diferents):3,} Paraulògics diferents"

Per tant, hi ha 47,600 Paraulògics diferents

Així, hi ha 47.600 Paraulògics diferents, és a dir, en tenim un al dia per més de 130 anys. Qui s'avorreix és perquè vol.

2. Quin Paraulògic té més tutis?

Els tutis són al centre del Paraulògic, i ja he comentat que sempre en cal un per tal que la tria de lletres del Paraulògic sigui vàlida.

Llavors, ens sorgeix la pregunta: a quina combinació de lletres li sobren tutis? Quin Paraulògic té més tutis?

Amb aquest petit codi trobem el top 10:

>>> from collections import Counter
>>> print("Els conjunts de lletres amb què es poden formar més tutis són:")
>>> comptador = Counter(map(frozenset, tutis))
>>> for lletres, n in comptador.most_common(10):
>>>     print('-', ''.join(sorted(lletres)) + ':', n)

Els conjunts de lletres amb què es poden formar més tutis són:
- aceinrt: 46
- aceirst: 40
- acenort: 39
- acdinor: 37
- acemnrt: 36
- aeimnrt: 36
- aceinst: 36
- acimort: 34
- acdenor: 33
- aeimnst: 31

El rècord és per les lletres aceinrt, amb les quals podem formar els 46 tutis següents:

>>> [tuti for tuti in tutis if set(tuti) == set("aceinrt")]

acientar, anticrètic, anticrètica, cantaire, cantiner, cantinera,
cantirer, cantirera, cartenir, catenària, caterina, centenari, centenària,
cèntrica, ceratina, cinerita, cinerítica, cintaire, cintera, cinteria,
creatina, creatinina, cretina, encanteri, encaterinar, encintar,
encrinat, entèrica, entrecriar, incerta, increat, inerràtic, inerràtica,
neàrtic, neàrtica, nectari, nectària, nectarina, nectariner, nerítica,
reactància, renitència, reticència, retinència, terciana, tercina

3. Quina és la paraula que dona més punts?

Si mai has tingut la satisfacció d'introduir un tuti com "subratllar" o "morfofonema", potser t'has preguntat quin és el tuti que dona més punts.

Repassem com es puntuen les paraules segons les normes del Paraulògic:

  • Les paraules de 3 lletres donen 1 punt. Les de 4 lletres, 2 punts.
  • A partir de 5 lletres, tants punts com lletres tingui la paraula.
  • Cada joc inclou almenys un "tuti" en què s'usen totes les lletres. Amb cada tuti obteniu 10 punts extra!

Cosa que podem traduir en el codi següent:

def punts(paraula):
    if len(paraula) <= 4:
        return len(paraula) - 2
    if len(set(paraula)) == 7:
        return len(paraula) + 10
    return len(paraula)

Amb tota aquesta feina feta, trobar la paraula que dona més punts és directe:

>>> punts_maxims = max(map(punts, paraules))
>>> print(f"Com a màxim, podem obtenir {punts_maxims} punts, amb la paraula:")
>>> for p in paraules:
>>>     if punts(p) == punts_maxims:
>>>         print("-", p)

Com a màxim, podem obtenir 27 punts, amb la paraula:
- entenimentadament

Així doncs, la paraula que més punts dona és entenimentadament.

En segona posició, tenim dinou paraules que ens donarien 25 punts:

acetilsalicilic, aclimatabilitat, antiparasitaria, antitranspirant,
associacionista, emmagatzemament, empantanegament, esllavissadissa,
fotoheterotrofa, impertinentment, inalienabilitat, incontinentment,
independentment, inhabitabilitat, instantaniament, intelligentment,
intransitivitat, parallelepipede, territorialitat

4. Quants tutis de només 7 lletres hi ha?

Ja hem trobat quins són els tutis més llargs. Per simetria, seria lògic preguntar-nos: hi ha molts tutis de tan sols 7 lletres?

La resposta és que sí:

>>> tutis_curts = [t for t in tutis if len(t) == 7]
>>> print(f"Hi ha {len(tutis_curts):3,} tutis de 7 lletres. Per exemple:")
>>> print(", ".join(tutis_curts[:16]))
>>> print("...")
>>> print(", ".join(tutis_curts[-16:]))

Hi ha 2,534 tutis de 7 lletres. Per exemple:
abdomen, ablució, abluent, abonyec, abortiu, abrupte, absolut, abstemi,
abundor, abundós, acèrvul, acompte, acritud, acrogen, acrogin, acrònim
...
xifreda, xilòfag, ximplet, xiquesa, xiqueta, xisclar, xisclet, xuclera,
xuetona, xuflera, xutador, yperita, zelador, zenital, zigurat, zimogen

5. Quin Paraulògic té menys paraules?

Continuant amb les preguntes existencials: seria possible que un dia introduint només quatre o cinc paraules hàgim arribat al paó? I encara més, seria possible aconseguir el paó amb una sola paraula?

Aquesta és una pregunta una mica més complicada. Per respondre-la, hem de resoldre tots els Paraulògics, els 47.600.

Ara seria el moment d'emprar la funció solucions() del principi, i és quan ens adonem que aquest mètode és una mica lent.

Farem una nova funció, més eficient, convenientment anomenada solucions_rapid(), que usarà la llibreria NumPy de càlcul numèric:

import string
import numpy as np

LLETRES = string.ascii_lowercase + 'ç'

AMB = {c: np.array([c in p for p in paraules]) for c in LLETRES}
SENSE = {c: np.array([c not in p for p in paraules]) for c in LLETRES}

def solucions_rapid(p):
    a = np.logical_and.reduce(
        [AMB[p[0]]] + [SENSE[c] for c in set(LLETRES) - set(p)]
    )
    return [paraules[s[0]] for s in np.transpose(a.nonzero())]

Si ara generem una llista amb tots els Paraulògics, podem calcular totes les seves solucions en qüestió de segons:

paraulogics = sorted(
    [
        lletra + '+' + ''.join(sorted(lletres - set(lletra)))
        for lletres in set(frozenset(tuti) for tuti in tutis)
        for lletra in lletres
    ]
)
solucions = {p: solucions_rapid(p) for p in paraulogics}

Ara ja estem preparats per esbrinar quin és el Paraulògic amb menys solucions. Resulta que n'hi ha un grapat que només tenen una solució:

print("Paraulògics amb una sola solució:")
for paraulogic, sols in solucions.items():
    if len(sols) == 1:
        print(f" - {paraulogic}: {sols[0]}")

Paraulògics amb una sola solució:
 - k+dilnop: kilopond
 - w+eiortz: zwitterió
 - y+abcklp: playback
 - y+aeiprt: yperita
 - ç+einqsu: esquinç
 - ç+eintuv: invençut

El dia que toqui un d'aquests Paraulògics, acabarem aviat:

6. Quin Paraulògic té més paraules? I quin dona més punts?

Si bé el dia del zwitterió o l'yperita acabarem aviat, quin serà el que se'ns farà més llarg?

Vegem quin és el que té més paraules:

>>> paraulogic, sols = max(solucions.items(), key=lambda item: len(item[1]))
>>> print(f"El Paraulògic amb més paraules és: {paraulogic}.")
>>> print(f"Té {len(sols)} solucions.")

El Paraulògic amb més paraules és: a+ceinrt.
 869 solucions.

El Paraulògic a+ceinrt té, ni més ni menys que 869 paraules. Resulta que aquest és també el Paraulògic que més punts dona:

>>> paraulogic, sols = max(solucions.items(), key=lambda item: sum(map(punts, item[1])))
>>> print(f"El Paraulògic amb més punts és: {paraulogic}.")
>>> print(f"Les seves solucions sumen {sum(map(punts, sols))} punts.")

El Paraulògic amb més punts és: a+ceinrt.
Les seves solucions sumen 5912 punts.

I quines són les 869 solucions que sumen 5.912 punts? Aquestes:

acàcia, acanar, acant, acantaci, acantàcia, acantita, acarar, acariciar,
acarrerar, acatar, acatarrar-se, accent, acci, àccia, acer, acerar,
acerat, acereria, acetat, acètic, acètica, ací, acientar, acin,
acinet, acinètic, acinètica, acne, acneic, acneica, acràcia, acrània,
àcrata, acràtic, acràtica, acre, acrític, acrítica, acta, actant,
acte, actina, actini, actínia, actínic, actínica, aeri, aèria, aerinita,
ai-ai, ain, aïnar, aïrar, aire, airina, anant, anar, anartra, anartre,
anatèctic, anatèctica, anca, ancat, ancià, anciana, ancianitat,
ànec, anet o ànet, aní, anit, ànnera, ant, anta, antàrtic, antàrtica,
antec, anteca, antena, antenat, antera, antiaeri, antiaèria, antiartrític,
antiartrítica, antic, anticrètic, anticrètica, antina, antitetànic,
antitetànica, antitètic, antitètica, antitrinitari, antitrinitària,
antracè, antràcic, antràcica, antracita, antracític, antracítica,
antre, ara, arc, arca o arcà, arcaic, arcaica, arcana, arcar, arcat,
arè, àrea, arec, areca, arena, arenaci, arenàcia, arenar, arener,
arenera, arenita, aret, ari, ària, ariet, arieta, arn, arna, arnar,
arnat, arner, arnera, arniar, àrnica, arniet, arraià, arran, arranar,
arrancar, arrear, arrecerar, arreic, arreica, arrencar, arrencat,
arrere, arri, arrià, arriana, arriar, arrienc, arrienca, arrier,
arrieria, arriet, art, artaire, artanenc, artanenca, artec, arter,
artera, arteria o artèria, artet, artètica, àrtic, àrtica, artrític,
artrítica, atac, atacant, atacar, atacat, atàctic, atàctica, ataràctic,
ataràctica, atarantar, atarterar, atea, atècnic, atècnica, atenenc,
atenenca, atenir-se, atent, atenta, aterià, ateriana, aterrar, aterrat,
aterrir, atiaire, atiar, àtic, àtica, atirantar, atracar, atraient,
atrètic, atrètica, atri, atrit, atrita, caca, cacera, cacic, cacicat,
cai, caiac, caient, caïnita, cairar, cairat, caire, caireta, can,
cana, canac, canaca, canana, cananea, canar, canari, canària, canat,
canca, cancan, cancaneta, càncer, canera, canet, caní, canic, canície,
canina, cant, cantaire, cantant, cantar o càntar, cantata, cànter,
cantera o càntera, canterera, càntic, cantina, cantiner, cantinera,
càntir, cantirer, cantirera, cantiri, car, cara, caracarà, caràcter,
caraïta, carat, carca, càrcer, carcera, carcerari, carcerària, carei,
carena, carenar, carenat, carència, carener, carenera, careta, cària,
cariar-se, carícia, carina, carinar, caritat, caritater, carn, carner,
carnera, carnet, carni, càrnia, carrac, carraca, carranc, carranca,
carrar, carrat, càrrec, carrer, carrera, carrereta, carret, carreta,
carreter, carretera, carric, carta, cartaci, cartàcia, cartaire,
cartenir, carter o càrter, cartera, carteria, cartra, cartre, cat,
catacrac, càtar, càtara, cataracta, catàrtic, catàrtica, catena,
catenària, caterètic, caterètica, caterina, catet, catèter, catre,
catric-catrac, cena, centena, centenar, centenari, centenària, centrar,
cèntrica, cera, cerat, ceratina, ceratit, cerca, cercar, cercària,
cerera, cereria, cereta o ceretà, ceretana, cèria, cèrica, cerra,
certa, cetrària, cia, cian, cianat, ciànic, ciànica, cianina, cianita,
ciar, ciati, ciàtic, ciàtica, ciència, cínara, cinc-centena, cinerari,
cinerària, cinèria, cinerita, cinerítica, cinètica, cínica, cinta,
cintaire, cintar, cintera, cinteria, cintra, cintrar, cintrat, cirater,
ciratera, circa, circinat, cirenaic, cirenaica, cirera, cirerar,
cirereta, cita, citar, cítara, citrat, cítrica, citrina, crac, cracant,
cran, cranar, cranc, cranca, crani, cranià, craniana, craniat, crater
o cràter, crear, creatina, creatinina, crenat, creta, cretaci, cretàcia,
cretàcic, cretàcica, cretenca, cretina, cria, criar, criat, crica,
cric-crac, crina, crinera, crítica, criticaire, criticar, ecètica,
eia, eina, ena, enarcar, enartar, encant, encantar, encantat, encanteri,
encara, encarar, encarcarar, encarcarat, encarcerar, encarir, encarnar,
encarnat, encàrrec, encarrerar, encartar, encaterinar, encenaire,
encerar, encerat, encercar, encerrar, encertant, encertar, encertat,
encetar, encinta, encintar, encirar-se, enciriar, encrinat, ennierat,
enraiar, enrancir, enrarir, enretirar, entat, entecar, entera, enterca,
entercar, entèrica, enterrar, enterrat, entinar, entintar, entitat,
entrant, entrar, entreacte, entrecara, entrecriar, entrenar, entretancar,
entretant, era, erari, erecta, erera, ererar, ereta, ericaci, ericàcia,
erina, eritrea, eritrina, eritrita, erra, errant, errar, errat,
errata, erràtic, erràtica, erta, eta o età, etarra, etcètera, etèria,
eterna, eternitat, ètica, etnarca, ètnia, ètnica, etnicitat, iac,
iacetà, iacetana, iai, iaia, iar, iàtric, iàtrica, ica, icac, icnita,
ictèrica, icterícia, inanitat, inca, incaic, incaica, incerta, incinerar,
incitant, incitar, increat, inèrcia, inerrància, inerrant, inerràtic,
inerràtica, inerta, ínia, iniciar, innat, innata, intacta, intacte,
intentar, interina, interinitat, interna, internar, internat, intina,
intricat, ira, iranià, iraniana, irànic, irànica, irat, irenarca,
irritant, irritar, iterar, itinerant, itinerari, itinerària, ítria,
ítrica, nacra, nacrat, nacre, nacta, nacte, naia, nan, nana, nannar,
narceïna, narrar, narratari, narratària, nat, nata, neàrtic, neàrtica,
nècia, nèctar, nectari, nectària, nectarina, nectariner, nena, nènia,
neretar, nerita, nerítica, neta, niacina, niar, nícia, nictitant,
niera, nina, nineta, nitrar, nitrat, nitratina, nitrera, nítrica,
raca, raent, rai, raier, raiera, ran, ranc, ranca, ranci, rància,
ranera, raní, rar, rara, raritat, rat, rata, ratània, ratar, ratat,
rater, ratera, rateria, rateta, ratina, ratinar, rea, reactància,
reactant, reat, recar, recàrrec, recerca, recercar, recercat, reciari,
recitar, recitat, recrear, recria, recriar, recta, reencarnar, reina
o reïna, reineta, reiterar, renà, renana, reneta, renitència, rentar,
rentat, rètica, reticència, retina, retinència, retinina, retintar,
retirar, retirat, retractar, retracte, retranca, retrat, retratar,
retreta, retria, retriar, ria, rica, ricar, ríccia, ricínica, ric-rac,
riera, rierenca, tac, taca, tacaé, tacar, tacat, tàcit, tàcita,
tacte, tàctic, tàctica, tacticitat, taenita, tai, tan, tana, tanc,
tanca, tancar, tancat, taní, tannat, tànnic, tànnica, tant, tanta,
tàntric, tàntrica, tar, tara, tarannà, taranta, tarar, tararà, tararí,
tarranc, tàrrec, tartà, tartana, tartaner, tartanera, tàrtar, tàrtara,
tartàric, tartàrica, tarter, tartera, tartrà, tartrat, tàrtric,
tàrtrica, tat, tatà, tàtar, tàtara, teatí, teatina, teatre, teatrí,
teca, tècnica, tectita, teia, teiera, teïna, tenacitat, tènar, tenca,
tènia, tennantita, tercera, terceria, tèrcia, terciaire, terciana,
terciari, terciària, tercina, terna, ternari, ternària, ternat,
terra, terraire, terranc, terrari, terrat, terratinent, terrena,
terrenca, terrera, terreta, terretita, tèrria, terrina, teta, tètan,
tetània, tetànic, tetànica, tetanina, tetera, tetina, tetrarca,
tetrarcat, tètrica, tia, tiara, tic-tac, tina, tinència, tinenta,
tinta, tintar, tira o tirà, tiracrín, tirana, tirania, tirànic,
tirànica, tirant, tirar, tirat, tiratac, tira-tira, tireta, tiretera,
tireteria, tirià o tíria, tiriana, tirrena, tírria, tita o tità,
titanat, titani, titànic, titànica, titanita, títera, titeta, titina,
traca, traceria, traci, tràcia, tractant, tractar, tractat, tracte,
trair, trairar, traire, tranc, trena, trenar, trenat, trenca, trencant,
trencar, trencat, trenta, trentena, trentenari, trentenària, trentina,
treta, tria, triac, triar, triat, tric-trac, trina, trinar, trinat,
trinca, trincar, trinitari, trinitària, trinitat, trita, tritiat,
tritícia

Quasi res.


Gràcies a Pere Orga, creador del Paraulògic per ajudar-me a obtenir la llista de paraules, i també per crear el joc!