Je wordt geblinddoekt en krijgt daarna een stapel kaarten in je hand. Dit moeten niet noodzakelijk alle 52 kaarten uit een standaard kaartspel zijn. Sommige kaarten van die stapel liggen met hun beeldzijde naar boven, de andere met hun beeldzijde naar onder. Als we je nu vertellen dat de stapel exact $$b$$ kaarten bevat die met hun beeldzijde naar boven liggen, hoe kan je hem dan in twee verdelen zodat beide stapels evenveel kaarten bevatten die met hun beeldzijde naar boven liggen? Beide stapels moeten niet noodzakelijk evenveel kaarten bevatten.

een stapel kaarten
Terwijl je geblinddoekt bent, krijg je een stapel kaarten in de hand waarvan sommige kaarten met hun beeldzijde naar boven liggen en de andere met hun beeldzijde naar onder. Hoe kan je die stapel in twee splitsen, zodat elke stapel evenveel kaarten heeft die met hun beeldzijde naar boven liggen?

Ook al zouden we geblinddoekt het aantal kaarten in de stapel kunnen tellen, we hoeven eigenlijk zelfs niet te weten hoeveel kaarten er in de oorspronkelijke stapel liggen. Maar laten we zeggen dat de stapel uit $$n$$ kaarten bestaat. Dan liggen er $$b$$ kaarten met hun beeldzijde naar boven en $$n - b$$ kaarten met hun beeldzijde naar onder. We verdelen nu de oorspronkelijke stapel in twee, waarbij de eerste stapel bestaat uit de eerste $$b$$ kaarten, en de tweede stapel uit de resterende $$n - b$$ kaarten.

Als de eerste stapel $$m$$ kaarten bevat die met hun beeldzijde naar boven liggen, dan bevat de tweede stapel de resterende kaarten die met hun beeldzijde naar boven liggen en dat zijn er $$b - m$$. Dat laatste is ook exact het aantal kaarten van de eerste stapel die met hun beeldzijde naar onder liggen. Als we dus de eerste stapel volledig omdraaien, dan hebben beide stapels nu $$b - m$$ kaarten die met hun beeldzijde naar boven liggen. Voila!

Concreet, stel dat we een stapel met 16 kaarten krijgen, waarvan er 7 met hun beeldzijde naar boven liggen. We verdelen die stapel dan in twee, waarbij de eerste stapel bestaat uit de eerste 7 kaarten en de tweede stapel uit de laatste 9 kaarten. Als er in de eerste stapel 3 kaarten met hun beeldzijde naar boven liggen, dan moeten er in de tweede stapel $$7 - 3 = 4$$ kaarten met hun beeldzijde naar boven liggen. In de eerste stapel liggen er ook $$7 - 3 = 4$$ kaarten met hun beeldzijde naar onder. Als we alle kaarten in die stapel omdraaien, dan liggen er in de eerste stapel nu dus 4 kaarten met hun beeldzijde naar boven, net als in de tweede stapel.

Opgave

Een standaard kaartspel bestaat uit 52 verschillende kaarten die onderverdeeld worden in vier kleuren van elk 13 kaarten: 13 klaveren (), 13 ruiten (), 13 harten () en 13 schoppen (). Klaveren en schoppen zijn zwart, ruiten en harten zijn rood, maar het zijn niet deze fysieke kleuren, maar de soorten die met de term kleur aangeduid worden. Van elke kleur zijn er telkens kaarten met een rang van 2 tot en met 10, een boer, een vrouw, een heer en een aas. Daarnaast bevat een spel soms twee of drie jokers, maar die laten we hier even buiten beschouwing.

We stellen elk van de 52 kaarten van een standaard kaartspel voor als een string die bestaat uit de rang van de kaart, gevolgd door de kleur van de kaart:

Zo stelt AS bijvoorbeeld schoppenaas voor, 10H hartentien en KC klaverenheer. Bovendien leggen we vast dat de voorstelling van een kaart die met zijn beeldzijde naar boven ligt gebruikmaakt van hoofdletters (bijvoorbeeld AS of 10H), en dat de voorstelling van een kaart die met zijn beeldzijde naar onder ligt gebruikmaakt van kleine letters (bijvoorbeeld as of 10h). Merk op dat het laatste karakter van de voorstelling altijd een hoofdletter of een kleine letter is (geen cijfer) die de kleur van de kaart aanduidt.

De lijstvoorstelling van een stapel kaarten bestaat uit een lijst met de voorstellingen van de opeenvolgende kaarten uit de stapel, waarbij de bovenste kaart van de stapel het eerste element van de lijst is. Een stapel hoeft niet noodzakelijk alle 52 kaarten van een kaartspel te bevatten.

Definieer een klasse Stapel die kan gebruikt worden om stapels kaarten voor te stellen, waarbij sommige kaarten met hun beeldzijde naar boven en de andere met hun beeldzijde naar onder liggen. Bij het instantiëren van objecten van de klasse Stapel moet de lijstvoorstelling van de stapel kaarten doorgegeven worden. De klasse mag ervan uitgaan dat de gegeven lijstvoorstelling geldig is, zonder dat dit expliciet moet gecontroleerd worden. Voorts moet de klasse Stapel minstens de volgende methoden ondersteunen:

De conversie van een object $$o$$ van de klasse Stapel naar een string — bekomen met de ingebouwde functies repr en str — bevat een voorstelling van de stapel kaarten zoals aangegeven in onderstaande voorbeeldsessie. De voorstelling die de functie repr teruggeeft, is een Python expressie die een nieuw object van de klasse Stapel aanmaakt met dezelfde toestand als de huidige toestand van object $$o$$. De voorstelling die de functie str teruggeeft, bestaat uit de voorstellingen van de opeenvolgende kaarten van de stapel (van boven naar onder), telkens van elkaar gescheiden door een spatie. Hierbij wordt een kaart die met zijn beeldzijde naar boven ligt op de standaard manier voorgesteld. Een kaart die met zijn beeldzijde naar onder ligt wordt voorgesteld door twee sterretjes (**).

Zorg er ook voor dat de ingebouwde operator == kan gebruikt worden om te bepalen of twee objecten van de klasse Stapel gelijk zijn. Dit is het geval als de twee stapels evenveel kaarten bevatten die met hun beeldzijde naar boven liggen.

Voorbeeld

>>> kaarten = Stapel(['AH', '3S', 'KC', '4H', '3D', '10H', '8D', '5D', '7C', 'QS', 'JC', '3H', 'KS', '4C', 'KD', '8S'])
>>> print(kaarten)
AH 3S KC 4H 3D 10H 8D 5D 7C QS JC 3H KS 4C KD 8S
>>> kaarten
Stapel(['AH', '3S', 'KC', '4H', '3D', '10H', '8D', '5D', '7C', 'QS', 'JC', '3H', 'KS', '4C', 'KD', '8S'])
>>> kaarten.beeldzijdeBoven()
16
>>> kaarten.omdraaien()
Stapel(['ah', '3s', 'kc', '4h', '3d', '10h', '8d', '5d', '7c', 'qs', 'jc', '3h', 'ks', '4c', 'kd', '8s'])
>>> kaarten.omdraaien(1).omdraaien(4).omdraaien([5, 9]).omdraaien((10, 11, 13))
Stapel(['ah', '3S', 'kc', '4h', '3D', '10H', '8d', '5d', '7c', 'QS', 'JC', '3H', 'ks', '4C', 'kd', '8s'])
>>> print(kaarten)
** 3S ** ** 3D 10H ** ** ** QS JC 3H ** 4C ** **
>>> kaarten.beeldzijdeBoven()
7

>>> kaarten1, kaarten2 = kaarten.splitsen(4)
>>> print(kaarten1)
** 3S ** **
>>> kaarten1
Stapel(['ah', '3S', 'kc', '4h'])
>>> kaarten1.beeldzijdeBoven()
1
>>> print(kaarten2)
3D 10H ** ** ** QS JC 3H ** 4C ** **
>>> kaarten2
Stapel(['3D', '10H', '8d', '5d', '7c', 'QS', 'JC', '3H', 'ks', '4C', 'kd', '8s'])
>>> kaarten2.beeldzijdeBoven()
6
>>> kaarten1 == kaarten2
False

>>> kaarten3, kaarten4 = kaarten.splitsen()
>>> print(kaarten3)
** 3S ** ** 3D 10H **
>>> kaarten3
Stapel(['ah', '3S', 'kc', '4h', '3D', '10H', '8d'])
>>> kaarten3.beeldzijdeBoven()
3
>>> print(kaarten4)
** ** QS JC 3H ** 4C ** **
>>> kaarten4
Stapel(['5d', '7c', 'QS', 'JC', '3H', 'ks', '4C', 'kd', '8s'])
>>> kaarten4.beeldzijdeBoven()
4
>>> kaarten3 == kaarten4
False

>>> kaarten3.omdraaien()
Stapel(['AH', '3s', 'KC', '4H', '3d', '10h', '8D'])
>>> print(kaarten3)    
AH ** KC 4H ** ** 8D
>>> kaarten3.beeldzijdeBoven()
4
>>> kaarten3 == kaarten4
True

De opeenvolgende statements uit bovenstaande voorbeeldsessie komen overeen met het voorbeeld van de kaartentruc zoals die gegeven werd op het einde van inleiding van deze opgave. Klik op onderstaande afbeelding voor een visuele voorstelling van de opeenvolgende stappen van de kaartentruc.

kaartentruc
kaarten = Stapel(['AH', '3S', 'KC', '4H', '3D', '10H', '8D', '5D', '7C', 'QS', 'JC', '3H', 'KS', '4C', 'KD', '8S'])
kaarten.omdraaien()
kaarten.omdraaien(1)
kaarten.omdraaien(4)
kaarten.omdraaien([5, 9])
kaarten.omdraaien((10, 11, 13))
kaarten3, kaarten4 = kaarten.splitsen()
kaarten3.omdraaien()