Bij het spelletje Dr. Eureka zijn alle spelers assistent-wetenschappers. Ze moeten proberen om sneller dan hun medespelers de gekleurde ballen in de voorgeschreven volgorde in de proefbuizen te krijgen. Daarbij mogen de ballen niet uit de buizen vallen of met de handen aangeraakt worden.

Dr. Eureka
Een speler van het spelletje Dr. Eureka heeft de materialen op de juiste volgorde in de proefbuizen gekregen, zoals voorgeschreven op de opdrachtkaart.

Als alle spelers klaar zijn om eraan te beginnen, wordt de bovenste opdrachtkaart omgedraaid. Dan proberen alle spelers zo snel mogelijk de gekleurde ballen van de ene in de andere buis te krijgen, zodat ze de volgorde krijgen die op de opdrachtkaart staat. Daarbij gelden de volgende regels:

opdracht
Een opdracht kan voltooid worden met alle reageerbuizen rechtopstaand (A) of door één buis omgekeerd neer te zetten (B).

De volgorde van de proefbuizen doet er niet toe (van links naar rechts). Enkel de volgorde van de gekleurde ballen in de proefbuizen (van boven naar onder). Als het helpt mogen de proefbuizen met de hand van plaats verwisseld worden.

Als een speler een bal met de hand raakt, een bal uit een buis laat vallen, of onterecht aankondigt dat de opdracht bereikt werd, dan doet de speler die ronde niet meer mee (dus totdat de anderen deze opdracht af hebben).

Het spel wordt gespeeld met een vast aantal proefbuizen. De proefbuizen hebben een maximale capaciteit die aangeeft hoeveel ballen er maximaal in elke buis passen.

De eerste speler die zijn ballen in de voorgeschreven volgorde in zijn proefbuizen heeft, roept "Eureka!". Als de andere spelers het er mee eens zijn dat hij de opdracht op een correcte manier voltooid heeft, dan krijgt hij de opdrachtkaart die 1 punt waard is.

De spelers laten de ballen in hun proefbuizen zoals ze na de vorige ronde zaten. De ballen worden dus niet opnieuw in een bepaalde startpositie geplaatst. Alle buizen moeten echter rechtop gezet worden voordat een nieuwe opdrachtkaart wordt omgekeerd. Als alle spelers klaar zijn, begint de volgende ronde met het omdraaien van een nieuwe opdrachtkaart. De eerste speler die 5 punten heeft, wint het spel.

Opgave

Definieer een klasse Eureka waarmee kan gesimuleerd worden hoe de spelers van Dr. Eureka de gekleurde ballen over hun proefbuizen kunnen verdelen. Om te kunnen verwijzen naar de verschillende proefbuizen, worden de buizen van links naar rechts genummerd vanaf 0.

Bij het aanmaken van een simulatie (Eureka) moet een string (str) doorgegeven worden die de configuratie beschrijft van de gekleurde ballen over de verschillende proefbuizen. Daarin wordt elke bal voorgesteld als een hoofdletter die de kleur van de bal aangeeft (dezelfde letters stellen ballen met dezelfde kleur voor). Elke proefbuis wordt beschreven door de opeenvolging van de ballen die erin zitten (opgelijst van onder naar boven). De opeenvolgende proefbuizen worden telkens van elkaar gescheiden door een komma (,). Zo stelt PG,GR,PR bijvoorbeeld de configuratie van drie proefbuizen voor die te zien is in de eerste afbeelding in de inleiding, waarbij de hoofdletter P een paarse bal voorstelt, G een groene bal en R een rode bal.

Aan de optionele parameter maximum kan de maximale capaciteit (int) van de proefbuizen doorgegeven worden (standaardwaarde: 4). Als één van de proefbuizen in de gegeven configuratie de maximale capaciteit overschrijdt, dan moet er een AssertionError opgeworpen worden met de boodschap ongeldige configuratie.

Aan de optionele parameter omgekeerd kan het volgnummer (int) doorgegeven worden van een proefbuis die omgekeerd staat. Standaard staan alle proefbuizen rechtop. Als er een ongeldig volgnummer wordt doorgegeven, dan moet er een AssertionError opgeworpen worden met als boodschap ongeldige configuratie.

Als er een simulatie (Eureka) wordt doorgegeven aan de ingebouwde functie repr, dan moet een stringvoorstelling (str) teruggegeven worden die leest als een Python expressie waarmee een nieuwe simulatie kan aangemaakt worden met dezelfde configuratie als het object dat aan de functie repr wordt doorgegeven. Daarbij moet de maximale capaciteit van de proefbuizen altijd expliciet worden doorgegeven aan de parameter maximum. Enkel wanneer er een proefbuis omgekeerd is, moet diens volgnummer doorgegeven worden aan de parameter omgekeerd.

Als er een simulatie (Eureka) wordt doorgegeven aan de ingebouwde functie str dan moet een stringvoorstelling (str) van de opstelling van de proefbuizen teruggegeven worden, waarvan het formaat kan afgeleid worden uit onderstaand voorbeeld. Daarbij geven de bovenkant (= =) en de onderkant (===) van elke proefbuis aan of de buis rechtop of omgekeerd staat. De proefbuizen worden in de stringvoorstelling telkens van elkaar gescheiden door één enkele spatie.

Daarnaast moet de klasse Eureka minstens de volgende methoden ondersteunen:

Twee simulaties $$r$$ en $$s$$ (Eureka) zijn gelijk (r == s) als de gekleurde ballen in dezelfde volgorde in de proefbuizen liggen (van boven naar onder). Daarbij speelt de volgorde van de proefbuizen (van links naar rechts) geen rol. Ook het omkeren van proefbuizen en de maximale capaciteit van de proefbuizen speelt geen rol.

Voorbeeld

>>> spel = Eureka('RPG,G,PR')
>>> spel
Eureka('RPG,G,PR', maximum=4)
>>> print(spel)
= = = = = =
| | | | | |
|G| | | | |
|P| | | |R|
|R| |G| |P|
=== === ===
>>> spel.verplaatsen(0, 1, 1)
Eureka('RP,GG,PR', maximum=4)
>>> print(spel)
= = = = = =
| | | | | |
| | | | | |
|P| |G| |R|
|R| |G| |P|
=== === ===
>>> spel.verplaatsen(1, 2, 2)
Eureka('RP,,PRGG', maximum=4)
>>> print(spel)
= = = = = =
| | | | |G|
| | | | |G|
|P| | | |R|
|R| | | |P|
=== === ===
>>> spel.verplaatsen(0, 1, 1)
Eureka('R,P,PRGG', maximum=4)
>>> print(spel)
= = = = = =
| | | | |G|
| | | | |G|
| | | | |R|
|R| |P| |P|
=== === ===
>>> spel.verplaatsen(2, 1, 1).verplaatsen(2, 0, 1)
Eureka('RG,PG,PR', maximum=4)
>>> print(spel)
= = = = = =
| | | | | |
| | | | | |
|G| |G| |R|
|R| |P| |P|
=== === ===
>>> spel.omkeren(2)
Eureka('RG,PG,RP', maximum=4, omgekeerd=2)
>>> print(spel)
= = = = ===
| | | | | |
| | | | | |
|G| |G| |P|
|R| |P| |R|
=== === = =
>>> spel == Eureka('RP,RG,PG')
True
>>> spel == Eureka('PR,RG,PG')
False

>>> spel.omkeren(100)                # verkeerde positie van buis
Traceback (most recent call last):
AssertionError: ongeldige zet
>>> spel.omkeren(0)                  # er is al een andere buis omgekeerd
Traceback (most recent call last):
AssertionError: ongeldige zet
>>> spel.verplaatsen(0, 1)           # er is een buis omgekeerd
Traceback (most recent call last):
AssertionError: ongeldige zet

>>> spel.omkeren(2)
Eureka('RG,PG,PR', maximum=4)
>>> print(spel)
= = = = = =
| | | | | |
| | | | | |
|G| |G| |R|
|R| |P| |P|
=== === ===
>>> spel.verplaatsen(0, 100)         # verkeerde positie van buis
Traceback (most recent call last):
AssertionError: ongeldige zet
>>> spel.verplaatsen(100, 0)         # verkeerde positie van buis
Traceback (most recent call last):
AssertionError: ongeldige zet
>>> spel.verplaatsen(0, 0)           # buis kan je niet in zichzelf overgieten
Traceback (most recent call last):
AssertionError: ongeldige zet
>>> spel.verplaatsen(0, 1)
Eureka(',PGGR,PR', maximum=4)
>>> print(spel)
= = = = = =
| | |R| | |
| | |G| | |
| | |G| |R|
| | |P| |P|
=== === ===
>>> spel.verplaatsen(2, 1)           # buis 1 zit al vol
Traceback (most recent call last):
AssertionError: ongeldige zet
>>> spel.verplaatsen(0, 1)
Eureka(',PGGR,PR', maximum=4)
>>> print(spel)
= = = = = =
| | |R| | |
| | |G| | |
| | |G| |R|
| | |P| |P|
=== === ===