Zeshonderd jaar geleden ontwikkelden mensen op het Frans-Polynesische eiland Mangareva1 een telsysteem dat binaire en decimale componenten combineert om te kunnen tellen van 1 tot en met 799.

Mangareva
Kaart van Mangareva die dateert van 1938.

Het systeem laat niet toe om het getal nul voor te stellen. De cijfers 1 tot en met 9 hebben hun normale decimale waarde. De cijfers K (takau), P (paua), T (tataua) en V (varu) hebben respectievelijk de waarden 10, 20, 40 en 80, en lopen dus binair op. Een waarde $$n$$ wordt voorgesteld als \[ n = a_{80}\text{V} + a_{40}\text{T} + a_{20}\text{P} + a_{10}\text{K} + a_1 \] waarbij de factoren $$a_i\ (i \in \{1, 10, 20, 40, 80\})$$ voldoen aan volgende voorwaarden:

Op die manier wordt het getal 73 in het Mangarevaans telsysteem voorgesteld als de string TPK3, wordt 219 voorgesteld als de string 2VTK9 en wordt 799 voorgesteld als de string 9VTPK9. Uit onderzoek2 blijkt dat dit telsysteem toeliet om bewerkingen zoals optelling, aftrekking, vermenigvuldiging en deling snel uit het hoofd te berekenen: 1VPK9 + 1 = 1VT en 3VPK3 + 2VTK9 = 6VK2.

Opgave

Definieer een klasse Mangarevaans waarmee Mangarevaanse getallen kunnen voorgesteld worden in Python. Nieuwe objecten van deze klasse moeten zowel geïnitialiseerd kunnen worden met een integerwaarde $$i$$ (waarbij geldt dat $$1 \leq i \leq 799$$) als met een stringvoorstelling $$s$$ die voldoet aan de omschrijving uit de inleiding. Voor andere waarden moet bij initialisatie een AssertionError opgeworpen worden met de boodschap ongeldige waarde.

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

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

Voorbeeld

>>> getal = Mangarevaans('TPK3')
>>> int(getal)
73
>>> str(getal)
'TPK3'
>>> getal
Mangarevaans('TPK3')

>>> getal = Mangarevaans(219)
>>> int(getal)
219
>>> str(getal)
'2VTK9'
>>> getal
Mangarevaans('2VTK9')

>>> Mangarevaans(42) + Mangarevaans(16)
Mangarevaans('TK8')
>>> Mangarevaans(42) - Mangarevaans(16)
Mangarevaans('P6')
>>> Mangarevaans(42) * Mangarevaans(16)
Mangarevaans('8VPK2')
>>> Mangarevaans(42) // Mangarevaans(16)
Mangarevaans('2')
>>> Mangarevaans(42) % Mangarevaans(16)
Mangarevaans('K')
>>> Mangarevaans(12) ** Mangarevaans(2)
Mangarevaans('1VTP4')

>>> Mangarevaans(42) + 16
Mangarevaans('TK8')
>>> Mangarevaans(42) - 16
Mangarevaans('P6')
>>> Mangarevaans(42) * 16
Mangarevaans('8VPK2')
>>> Mangarevaans(42) // 16
Mangarevaans('2')
>>> Mangarevaans(42) % 16
Mangarevaans('K')
>>> Mangarevaans(12) ** 2
Mangarevaans('1VTP4')

>>> 42 + Mangarevaans(16)
Mangarevaans('TK8')
>>> 42 - Mangarevaans(16)
Mangarevaans('P6')
>>> 42 * Mangarevaans(16)
Mangarevaans('8VPK2')
>>> 42 // Mangarevaans(16)
Mangarevaans('2')
>>> 42 % Mangarevaans(16)
Mangarevaans('K')
>>> 12 ** Mangarevaans(2)
Mangarevaans('1VTP4')

>>> Mangarevaans('C3P0')
Traceback (most recent call last):
AssertionError: ongeldige waarde
>>> Mangarevaans(1234)
Traceback (most recent call last):
AssertionError: ongeldige waarde
>>> Mangarevaans({1, 2, 3})
Traceback (most recent call last):
AssertionError: ongeldige waarde

Bronnen