Maak een stapel met evenveel rode als zwarte kaarten. Schud de kaarten willekeurig door elkaar. Deel de kaarten door telkens de twee bovenste kaarten van de stapel te trekken. Als de twee kaarten rood zijn dan leg je ze bovenop de rode stapel. Als de twee kaarten zwart zijn dan leg je ze bovenop de zwarte stapel. Als er één rode en één zwarte kaart is (volgorde speelt geen rol) dan gooi je ze weg.

kaarten delen
Deel een kaartspel per twee kaarten. Als de twee kaarten rood zijn dan leg je ze in de rode stapel. Als de twee kaarten zwarte zijn dan leg je ze in de zwarte stapel. Als er een rode en een zwarte kaart gedeeld wordt, dan gooi je de twee kaarten weg.

Als je alle kaarten van de stapel gedeeld hebt dan zal je merken dat de rode stapel altijd evenveel kaarten bevat als de zwarte stapel. Kan je dit verklaren?

Opgave

Een standaard kaartspel bestaat uit 52 verschillende kaarten die onderverdeeld worden in vier soorten van elk 13 kaarten: 13 klaveren (), 13 ruiten (), 13 harten () en 13 schoppen (). Klaveren en schoppen zijn zwart, ruiten en harten zijn rood. Van elke soort 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.

Elke kaart van een standaard kaartspel wordt voorgesteld als een string (str) die bestaat uit de rang van de kaart, gevolgd door de soort van de kaart:

Zo stelt AS bijvoorbeeld schoppenaas voor, 10H hartentien en KC klaverenheer.

Een reeksvoorstelling van een stapel kaarten bestaat uit een lijst (list) of een tuple (tuple) met de voorstellingen van de opeenvolgende kaarten uit de stapel, waarbij de bovenste kaart van de stapel het eerste element is. Een stapel hoeft niet noodzakelijk alle 52 kaarten van een kaartspel te bevatten, maar elke kaart kan hoogstens één keer in de stapel voorkomen.

Definieer een klasse Stapel die kan gebruikt worden om stapels kaarten voor te stellen. Bij het instantiëren van objecten van de klasse Stapel moet de reeksvoorstelling van een stapel kaarten doorgegeven worden. Hierbij moet expliciet gecontroleerd worden dat de gegeven stapel voldoet aan de volgende voorwaarden:

Als de gegeven stapel niet aan deze voorwaarden voldoet dan moet een AssertionError opgeworpen worden met de boodschap ongeldige stapel.

Als er een object van de klasse Stapel wordt doorgegeven aan de ingebouwde functie len dan moet het aantal kaarten in de stapel (int) teruggegeven worden. Als er een object van de klasse Stapel wordt doorgegeven aan de ingebouwde functie str dan moet een string (str) teruggegeven worden die bestaat uit de stringvoorstelling van de individuele kaarten in de stapel, opgelijst van boven naar beneden en telkens van elkaar gescheiden door een spatie. Als er een object van de klasse Stapel wordt doorgegeven aan de ingebouwde functie repr dan moet een string (str) teruggegeven worden met een Python expressie die een nieuw object van de klasse Stapel aanmaakt met dezelfde toestand als die van het gegeven object. Hierbij moet de stapel kaarten voorgesteld worden als een lijst (list). Voorts moet de klasse Stapel minstens de volgende methoden ondersteunen:

Zorg er ook voor dat de + operator kan gebruikt worden om twee stapels (Stapel) samen te voegen. Het resultaat is een nieuwe stapel (Stapel) waarbij de kaarten van de eerste stapel (het linkerlid van de + operator) bovenop de kaarten van de tweede stapel (het rechterlid van de + operator) liggen. De + operator mag de samenstelling van de oorspronkelijke stapels niet wijzigen.

Voorbeeld

>>> stapel = Stapel(('5S', 'QC', '8S', 'QD', 'JC', '10C', '4H', '4S', '2D', '7S', '3S', '3C', '4D', '7H', '3H', '5H', 'KD', '6C', '2S', '9C'))
>>> len(stapel)
20
>>> stapel.trekken(3)
Stapel(['5S', 'QC', '8S'])
>>> stapel
Stapel(['QD', 'JC', '10C', '4H', '4S', '2D', '7S', '3S', '3C', '4D', '7H', '3H', '5H', 'KD', '6C', '2S', '9C'])
>>> len(stapel)
17
>>> stapel.trekken(5)
Stapel(['QD', 'JC', '10C', '4H', '4S'])
>>> print(stapel)
2D 7S 3S 3C 4D 7H 3H 5H KD 6C 2S 9C
>>> len(stapel)
12
>>> stapel.trekken(42)
Traceback (most recent call last):
AssertionError: ongeldig aantal kaarten

>>> rode_stapel, zwarte_stapel = stapel.delen()
>>> rode_stapel
Stapel(['3H', '5H', '4D', '7H'])
>>> zwarte_stapel
Stapel(['2S', '9C', '3S', '3C'])
>>> stapel
Stapel([])
>>> len(rode_stapel) == len(zwarte_stapel)
True

>>> rode_stapel + zwarte_stapel
Stapel(['3H', '5H', '4D', '7H', '2S', '9C', '3S', '3C'])
>>> rode_stapel + rode_stapel
Traceback (most recent call last):
AssertionError: ongeldige stapel

Epiloog

Als je nog steeds aan het nadenken bent waarom er altijd evenveel kaarten zijn in de rode en de zwarte stapel, dan kun je het op de volgende manier bekijken. Omdat er altijd evenveel rode en zwarte kaarten opzij gelegd worden (er wordt telkens één rode en één zwarte kaart opzij gelegd), moeten de resterende kaarten ook evenredig verdeeld zijn over rood en zwart. Als alle kaarten gedeeld zijn, moeten er dus wel evenveel kaarten in de rode en de zwarte stapel liggen.

Dezelfde redenering geeft je het antwoord op het volgende alcoholprobleem. Vul een glas met wijn en een glas met water. Breng een koffielepel wijn over van het eerste naar het tweede glas. Breng daarna een koffielepel van het mengsel in het tweede glas over naar het eerste glas. Is er dan meer wijn in het water of meer water in de wijn?

alcohol problem
Fill one glass with wine and another with water. Transfer a teaspoonful of wine from the first glass into the second. Then transfer a teaspoonful of that mixture back into the first glass. Now, is there more wine in the water or water in the wine?

De meeste mensen denken het eerste, maar in feit zijn de verhoudingen altijd hetzelfde. Zie je waarom?

Bronnen