In 1987 nam de Portugese dichter Alberto Pimenta het sonnet Transforma-se o amador na cousa amada van de 16e-eeuwse dichter Luís de Camões, en maakte er een nieuw sonnet van door de letters op elke regel te herschikken: Ousa a forma cantor! Mas se da namorada.

Transforma-se o amador na cousa amada,
Por virtude do muito imaginar;
Não tenho logo mais que desejar,
Pois em mim tenho a parte desejada.

Se nela está minha alma transformada,
Que mais deseja o corpo de alcançar?
Em si sómente pode descansar,
Pois consigo tal alma está liada.

Mas esta linda e pura semideia,
Que, como o acidente em seu sujeito,
Assim co'a alma minha se conforma,

Está no pensamento como ideia;
[E] o vivo e puro amor de que sou feito,
Como matéria simples busca a forma.

— Luís de Camões (16e eeuw)

ousa a forma cantor! mas se da namorada
nua d'imagem, tido rio por vir tu
não tens, oh rola joga, sem que ide
ia e mente passem, admito, d'harpejo,

nada, terno mar, falsamente ilhas. amas
desejando amor que cale cio, parcas
rimas e os desencantos pedem
odi et amo, caos, sigla. ali plantas

setas em ideia, ainda mel, puras,
semente que caído sujeito como eu,
a lama minha informam. com acessos

te penso e cato o mínimo. Se nada
muda, vê que frio e pó e riso e voto ou
ímpio amor mat'o ser e busca famas.

— L.C. (Alberto Pimenta, 1987)

Dit is een vertaling van het originele gedicht van Luís de Camões, dat met het bovenstaande in het achterhoofd merkwaardig toepasselijk blijkt te zijn:

De minnaar wordt hetgeen waar hij van houdt,
dankzij veel verbeeldingskracht;
want waar ik naar verlang heb ik al in mij,
en dus heb ik binnenkort niets meer te wensen.

Als mijn ziel de geliefde wordt,
wat verlangt mijn lichaam dan nog meer?
Alleen op zichzelf kan ze rust vinden,
want mijn lichaam en ziel zijn met elkaar verbonden.

Maar deze pure en eerlijke halfgodin
die met mijn ziel in overeenstemming is
zoals het toeval met zijn onderwerp,

bestaat in mijn hoofd slechts als idee;
de levende en zuivere liefde waarvan ik gemaakt ben
zoekt, net als eenvoudige materie, vorm.

Carlota Simões en Nuno Coelho van de Universiteit van Coimbra (Portugal) berekenden dat de letters in het sonnet van Camões binnen hun regels op $$5.3 \times 10^{312}$$ mogelijke manieren kunnen herschikt worden. Het interessante is dat ze ook vaststelden dat er in Pimenta's anagrammen twee letters ontbreken: L en C, de initialen van de oorspronkelijke dichter Luís de Camões. Ze zeiden daarover:

Het lijkt alsof Luís de Camões op een mysterieuze en magische manier ook het auteurschap van het tweede gedicht kwam opeisen.

Opgave

Een anagram is een woord dat of een zin die gevormd wordt uit de letters van een ander woord of een andere zin, maar in een andere volgorde. Bij anagrammen wordt enkel gekeken naar de letters en het aantal keer dat ze voorkomen. Andere karakters die voorkomen in de woorden of zinnen worden genegeerd. Er wordt ook geen onderscheid gemaakt tussen hoofdletters en kleine letters. Zo is

An Eagle lands on Earth's moon, making a first small permanent footprint.

bijvoorbeeld een anagram van

That's one small step for a man, one giant leap for mankind. — Neil Armstrong

Daarmee beschouwen we de letters van een woord of een zin dus als een multiset: een veralgemening van het concept verzameling, waarbij een element van een multiset meer dan één keer in een multiset kan voorkomen, in tegenstelling tot een verzameling waarin elk element precies één keer voorkomt.

Het aantal keer dat eenzelfde element $$e$$ voorkomt in een multiset $$X$$, wordt de multipliciteit van dat element genoemd (genoteerd als $$m_X(e)$$). In de multiset $$X = \{a, a, b, b, c, b\}$$ hebben de elementen bijvoorbeeld als multipliciteit $$m_X(a) = 2$$, $$m_X(b) = 3$$ en $$m_X(c) = 1$$. De multipliciteit $$m_X(d)$$ van een element $$d$$ dat niet tot de multiset $$X$$ behoort, is per definitie gelijk aan $$0$$. De kardinaliteit van een multiset $$X$$ (genoteerd als $$|X|$$) wordt berekend als de som van de multipliciteiten van al zijn elementen. De multiset $$X = \{a, a, b, b, c, b\}$$ heeft bijvoorbeeld kardinaliteit $$|X| = 6$$.

Definieer een klasse Multiset waarmee multisets kunnen voorgesteld worden waarvan de elementen bestaan uit de letters van een woord of een zin. Het woord of de zin (str) moet doorgegeven worden bij het aanmaken van een multiset (Multiset). Multisets zijn onveranderelijk (immutable).

Elke multiset $$X$$ (Multiset) moet een eigenschap letters hebben die verwijst naar een dictionary (dict) die elke letter $$e$$ (str; in hoofdletters) uit het woord of de zin afbeeldt op het aantal keer (int) dat die letter in het woord of de zin voorkomt (dat is dus de multipliciteit $$m_X(e)$$). Deze dictionary mag nooit sleutels met multipliciteit nul bevatten.

Elke multiset $$X$$ (Multiset) moet een methode multipliciteit hebben waaraan een letter $$e$$ (str) kan doorgegeven worden. De methode moet de multipliciteit $$m_X(e)$$ teruggeven. Daarbij mag geen onderscheid gemaakt worden tussen hoofdletters en kleine letters.

Als er een multiset $$X$$ (Multiset) wordt doorgegeven aan de ingebouwde functie str, dan moet een beschrijving (str) teruggegeven worden van de multipliciteit $$m_X(e)$$ van elke letter $$e$$ in $$X$$. Daarbij moeten de letters in alfabetische volgorde opgelijst worden. Bekijk onderstaand voorbeeld om te zien hoe de beschrijving moet opgemaakt worden.

Als er een multiset $$X$$ (Multiset) wordt doorgegeven aan de ingebouwde functie repr, dan moet een stringvoorstelling (str) teruggegeven worden die leest als een Python expressie waarmee een nieuwe multiset (Multiset) aangemaakt wordt met dezelfde letters en multipliciteiten als $$X$$. Daarbij moeten de letters in alfabetische volgorde achter elkaar gezet worden (in hoofdletters).

Als er een multiset $$X$$ (Multiset) wordt doorgegeven aan de ingebouwde functie len, dan moet de kardinaliteit $$|X|$$ teruggegeven worden.

Voor twee multisets $$X$$ en $$Y$$ (Multiset) moeten de zes vergelijkingsoperatoren de volgende betekenis krijgen:

operator betekenis
X == Y $$m_X(e) = m_Y(e)$$ voor elke letter $$e$$ in $$X$$ of in $$Y$$
X != Y $$m_X(e) \neq m_Y(e)$$ voor minstens één letter $$e$$ in $$X$$ of in $$Y$$
X <= Y $$m_X(e) \leq m_Y(e)$$ voor elke letter $$e$$ in $$X$$ of in $$Y$$
X < Y $$m_X(e) \leq m_Y(e)$$ voor elke letter $$e$$ in $$X$$ of in $$Y$$ en $$X \neq Y$$
X > Y $$m_X(e) \geq m_Y(e)$$ voor elke letter $$e$$ in $$X$$ of in $$Y$$ en $$X \neq Y$$
X >= Y $$m_X(e) \geq m_Y(e)$$ voor elke letter $$e$$ in $$X$$ of in $$Y$$

De som $$X + Y$$ van twee multisets $$X$$ en $$Y$$ (Multiset) moet een nieuwe multiset $$Z$$ (Multiset) opleveren, waarvoor geldt dat $$m_Z(e) = m_X(e) + m_Y(e)$$ voor elke letter $$e$$ in $$X$$ of in $$Y$$.

Het verschil $$X - Y$$ van twee multisets $$X$$ en $$Y$$ (Multiset) moet een nieuwe multiset $$Z$$ (Multiset) opleveren, waarvoor geldt dat $$m_Z(e) = m_X(e) - m_Y(e)$$ voor elke letter $$e$$ in $$X$$ of in $$Y$$. Daarbij moet steeds gelden dat $$m_X(e) - m_Y(e) \geq 0$$ voor elke letter $$e$$ in $$X$$ of in $$Y$$. Als dat niet het geval is, dan moet bij het uitvoeren van de bewerking een AssertionError opgeworpen worden met de boodschap ongeldige bewerking.

Voorbeeld

>>> multiset = Multiset('ELECTION RESULTS')
>>> multiset.letters
{'E': 3, 'L': 2, 'C': 1, 'T': 2, 'I': 1, 'O': 1, 'N': 1, 'R': 1, 'S': 2, 'U': 1}
>>> multiset.multipliciteit('T')
2
>>> multiset.multipliciteit('e')
3
>>> multiset.multipliciteit('X')
0
>>> multiset
Multiset('CEEEILLNORSSTTU')
>>> print(multiset)
C x 1, E x 3, I x 1, L x 2, N x 1, O x 1, R x 1, S x 2, T x 2, U x 1
>>> len(multiset)
15

>>> Multiset('ELECTION RESULTS') == Multiset("lies - let's recount")
True
>>> Multiset('ELECTION RESULTS') != Multiset('illegal votes')
True
>>> Multiset('REELECTIONS') <= Multiset('ELECTION RESULTS')
True
>>> Multiset('candidate') < Multiset('DECONTAMINATED')
True
>>> Multiset('bacteriological') > Multiset('BALLOT')
True
>>> Multiset('swing state') >= Multiset('GIANTESS')
True

>>> Multiset('ELECTION') + Multiset('RESULTS')
Multiset('CEEEILLNORSSTTU')
>>> Multiset('ELECTION') + Multiset('RESULTS') == Multiset("LIES - LET'S RECOUNT")
True
>>> Multiset('misinterpreted') - Multiset('president')
Multiset('EIMRT')
>>> Multiset('misinterpreted') - Multiset('president') == Multiset('merit')
True
>>> Multiset('REPUBLICANS') - Multiset('DEMOCRATS')
Traceback (most recent call last):
AssertionError: ongeldige bewerking

Epiloog

In 2014 daagde Nuno Coelho zijn studenten multimedia uit om de transformatie vorm te geven die Alberto Pimenta maakte van het gedicht van Luís de Camões. Dit is was Joana Rodrigues indiende:

Bronnen