In het begin van onze jaartelling vestigden de Maya zich in Centraal-Amerika. Ze waren in vele opzichten veruit de meest ontwikkelde en fascinerende beschaving van hun tijd. Wielen en trekdieren waren hen dan wel onbekend, toch beheersten ze als geen ander de kunst van het weven, de architectuur en het pottenbakken. Maar echt adembenemend waren hun verwezenlijkingen op het vlak van wiskunde en sterrenkunde. Terwijl Europa zich door de donkere Middeleeuwen aan het slepen was, berekenden de Maya het zonnejaar op 365,242 dagen (volgens moderne berekeningen 365,242198 dagen) en de maancyclus op 29,5302 dagen (volgens moderne berekening 29,53059 dagen). Zo'n verbluffend accurate berekeningen waren nauwelijks mogelijk geweest zonder het krachtige talstelsel dat de Maya hanteerden.

Mayapriesters en sterrenkundigen gebruikten een talstelsel met basis 20. Daarin worden de cijfers (0-19) voorgesteld aan de hand van drie symbolen: nul (vorm van een schelp), één (een punt) en vijf (een horizontale streep). Zo wordt negentien (19) bijvoorbeeld geschreven als vier punten horizontaal achter elkaar, boven drie horizontale strepen die bovenop elkaar gestapeld worden. De concepten 'cijfer' en 'nul' waren vrij ongebruikelijk voor die tijd, en nog totaal onbekend in Europa.

mayacijfers
De twintig mayacijfers.

Voor mayagetallen bestaande uit meerdere mayacijfers — dus getallen met waarde groter dan 19 — worden de mayacijfers verticaal bovenop elkaar geschreven. Hierbij staat het cijfer met de hoogste getalwaarde bovenaan. Het getal drieëndertig (33) wordt bijvoorbeeld geschreven als een punt (bovenste mayacijfer), met daaronder drie punten bovenop twee horizontale strepen (onderste mayacijfer). Het eerste punt stelt "één twintig" of $$1 \times 20$$ voor, waarbij drie punten en twee horizontale strepen (dus 13) opgeteld worden. Bijgevolg krijg je $$(1 \times 20) + 13 = 33$$.

eenheid 33 389 4645 66876
7200      

mayacijfer 9

360  

mayacijfer 1

mayacijfer 12

mayacijfer 5

20

mayacijfer 1

mayacijfer 1

mayacijfer 16

mayacijfer 13

1

mayacijfer 13

mayacijfer 9

mayacijfer 5

mayacijfer 16

Vreemd genoeg heeft in het Maya-talstelsel het cijfer op de derde positie (geteld vanaf onder) niet als getalwaarde $$20 \times 20 = 400$$, maar $$18 \times 20 = 360$$. Vermoedelijk omdat 360 ongeveer gelijk is aan het aantal dagen in een kalenderjaar. Alle mayacijfers boven de derde positie (geteld vanaf onder) hebben terug een normale getalwaarde volgens het 20-tallig stelsel, dus voor het vierde cijfer $$360 \times 20 = 7200$$, voor het vijfde cijfer $$7200 \times 20 = 144000$$, enzoverder. Op die manier geeft bovenstaande tabel bijvoorbeeld aan dat \[ 12 \times 360 + 16 \times 20 + 5 = 4645 \] en dat \[ 9 \times 7200 + 5 \times 360 + 13 \times 20 + 16 = 66876 \]

Opgave

De stringvoorstelling van een mayagetal is een string (str) die bestaat uit de mayacijfers van het mayagetal, opgelijst van boven naar onder en van elkaar gescheiden door een spatie. Hierbij wordt het mayacijfer met waarde nul genoteerd met de letter S. De andere mayacijfers worden genoteerd als nul of meer punten (.; waarde 1) gevolgd door nul of meer koppeltekens (-; waarde 5). Op die manier wordt het mayagetal met decimale waarde 66876 voorgesteld als de string ....- - ...-- .---.

Definieer een klasse Maya waarmee mayagetallen kunnen voorgesteld worden in Python. Zorg ervoor dat mayagetallen (Maya) zowel kunnen aangemaakt worden met hun decimale waarde $$d$$ (int; $$0 \leq d$$), met hun stringvoorstelling of met een ander mayagetal. Als er een mayagetal (Maya) wordt aangemaakt op basis van een ongeldig object, dan moet een AssertionError opgeworpen worden met de boodschap ongeldig mayagetal.

De conversie van een mayagetal (Maya) naar een string (str) — bekomen met de ingebouwde functies str en repr — bevat telkens de stringvoorstelling (str) van het mayagetal (uit onderstaand voorbeeld kan je het verschil afleiden qua resultaat dat beide ingebouwde functies teruggeven) en de conversie naar een integer (int) — bekomen met de ingebouwde functie int — geeft de decimale waarde (int) van het mayagetal terug.

Zorg ervoor dat de binaire bewerkingen voor de optelling (+), aftrekking (-), vermenigvuldiging (*), gehele deling (//), modulo (%) en machtsverheffing (**) telkens een nieuw mayagetal (Maya) opleveren als beide operandi mayagetallen (Maya) zijn of als één van beide operandi een mayagetal (Maya) is en het ander een integer (int). Het resultaat van die bewerkingen moet dezelfde decimale waarde hebben als het resultaat dat deze bewerkingen opleveren voor twee integer operandi met dezelfde decimale waarde. Als de bewerking geen geldig mayagetal oplevert, dan moet een AssertionError opgeworpen worden met de boodschap ongeldig mayagetal.

Voorbeeld

>>> a = Maya('..')
>>> int(a)
2
>>> b = Maya(33)
>>> str(b)
'. ...--'
>>> c = a + b
>>> c
Maya('. ---')
>>> print(c)
. ---
>>> int(c)
35
>>> a - b
Traceback (most recent call last):
AssertionError: ongeldig mayagetal
>>> b - a
Maya('. .--')
>>> a * b
Maya('... .-')
>>> int(a * b)
66
>>> b // a
Maya('.---')
>>> b % a
Maya('.')
>>> int(b ** a)
1089
>>> Maya('... .- . ..') + 89343
Maya('--- ....-- .... -')
>>> int(74837 - Maya('.... --- ...- ....--'))
40463
>>> Maya('....- ..-- ....-') * 2478
Maya('... S S --- ..--- ..')
>>> Maya(34783 // Maya('. .- ..-'))
Maya('... .--')
>>> Maya('..- -- ..--') % 89
Maya('... ..')
>>> Maya('..-- -') ** 7
Maya('....-- ..- ....- ..- ..- - .--- . ..-- .--- ...-- ..-- -')

>>> Maya('xxx')
Traceback (most recent call last):
AssertionError: ongeldig mayagetal
>>> Maya('SS ..--')
Traceback (most recent call last):
AssertionError: ongeldig mayagetal
>>> Maya('.....--')
Traceback (most recent call last):
AssertionError: ongeldig mayagetal
>>> Maya('..-- .- ...--- ...---')
Traceback (most recent call last):
AssertionError: ongeldig mayagetal