In het laboratorium gebruikt men centrifuges om vloeibare mengsels op basis van dichtheid te scheiden. In een centrifuge zitten gaten waarin reageerbuizen kunnen geplaatst worden. Door de reageerbuizen met hoge snelheid te laten ronddraaien, zorgt de middelpuntvliedende kracht1 (centrifugale kracht) voor de scheiding. Dit is bijvoorbeeld een centrifuge met 20 gaten, waarvan er 8 met reageerbuizen gevuld zijn:
Voor een centrifuge met $$n$$ gaten die op gelijke afstand rond een cirkel liggen, voeren we een coördinatenstelsel in waarbij de X-as en de Y-as elkaar snijden in het middelpunt van die cirkel. Er is altijd een gat waarvan het middelpunt op de positieve X-as ligt. De gaten worden in tegenwijzerzin genummerd vanaf 0, te beginnen bij dit gat waarvan het middelpunt op de positieve X-as ligt.
Een configuratie die beschrijft welke gaten van een centrifuge gevuld zijn met reageerbuizen, stellen we voor als een array (Array) met de nummers (Number) van de gevulde gaten. Daarbij maakt het niet uit in welke volgorde de nummers van de gevulde gaten opgelijst worden. Als in bovenstaande figuur de vier oranje gaten met reageerbuizen gevuld zijn en de twee donkergrijze gaten leeg zijn, dan kunnen we die configuratie bijvoorbeeld voorstellen als de array [4, 1, 3, 0].
Een centrifuge kan in wijzerzin of in tegenwijzerzin roteren. Bij één rotatiestap schuiven alle gaten (en reageerbuizen) één nummer door in wijzerzin of in tegenwijzerzin, zodat er telkens een gat met middelpunt op de positieve X-as blijft liggen. Dit wordt geïllustreerd in onderstaande figuur, waarbij we alle gaten van de centrifuge gevuld hebben met reageerbuizen die elk een unieke kleur hebben.
Bij het spiegelen van een centrifuge wordt de configuratie van haar reageerbuizen gespiegeld ten opzichte van de X-as. Als we een gespiegelde centrifuge nog eens spiegelen, dan krijgen we terug de oorspronkelijke configuratie van de centrifuge.
Definieer een klasse Centrifuge waarmee centrifuges kunnen voorgesteld worden waarvan sommige gaten met reageerbuizen gevuld zijn. Bij het aanmaken van een centrifuge (Centrifuge) moeten twee argumenten doorgegeven worden: i) het aantal gaten $$n$$ (int) en ii) een configuratie die beschrijft welke gaten van de centrifuge gevuld zijn met reageerbuizen.
Op een centrifuge $$c$$ (Centrifuge) moeten minstens de volgende methoden kunnen aangeroepen worden:
Een methode toString waaraan geen argumenten moeten doorgegeven worden. De methode moet een stringvoorstelling (String) van centrifuge $$c$$ teruggeven die leest als een expressie waarmee een nieuwe centrifuge (Centrifuge) aangemaakt wordt met hetzelfde aantal gaten en dezelfde configuratie van gevulde gaten als centrifuge $$c$$. Hierbij moet de configuratie voorgesteld worden als een oplopend gesorteerde array (Array) van nummers (Number).
Een methode roteer met een optionele parameter wijzerzin waaraan een Booleaanse waarde (Boolean) kan doorgegeven worden die aangeeft of er in wijzerzin (true) of in tegenwijzerzin (false; standaardwaarde) moet geroteerd worden. De methode moet zorgen dat alle reageerbuizen van centrifuge $$c$$ één rotatiestap in wijzerzin of in tegenwijzerzin doorschuiven, en moet een verwijzing naar centrifuge $$c$$ teruggeven.
Een methode spiegel waaraan geen argumenten moeten doorgegeven worden. De methode moet zorgen dat de configuratie van centrifuge $$c$$ gespiegeld wordt ten opzichte van de X-as, en moet een verwijzing naar centrifuge $$c$$ teruggeven.
Een methode isGelijk waaraan een centrifuge $$d$$ (Centrifuge) moet doorgegeven worden. De methode moet een Booleaanse waarde (Boolean) teruggeven die aangeeft of de twee centrifuges $$c$$ en $$d$$ gelijk zijn. Dat is het geval als beide centrifuges evenveel gaten hebben en als één van de centrifuges over een aantal stappen kan geroteerd worden zodat beide centrifuges dezelfde gevulde gaten hebben, eventueel na spiegeling van één van beide centrifuges. De methode isGelijk mag de toestand van centrifuges $$c$$ en $$d$$ niet wijzigen.
Een methode vul waaraan een centrifuge $$d$$ (Centrifuge) moet doorgegeven worden. De methode moet alle gaten die gevuld zijn in centrifuge $$d$$ opvullen in centrifuge $$c$$ en moet een verwijzing naar centrifuge $$c$$ teruggeven. Hierbij mag de toestand van centrifuge $$d$$ niet wijzigen. Als centrifuges $$c$$ en $$d$$ niet evenveel gaten hebben of als er een gevuld gat is in centrifuge $$d$$ dat ook al gevuld is in centrifuge $$c$$, dan mag de toestand van centrifuge $$c$$ niet wijzigen en moet er een AssertionError opgeworpen worden met de boodschap gaten kunnen niet gevuld worden.
Een methode leeg waaraan een centrifuge $$d$$ (Centrifuge) moet doorgegeven worden. De methode moet alle gaten die gevuld zijn in centrifuge $$d$$ leegmaken in centrifuge $$c$$ en moet een verwijzing naar centrifuge $$c$$ teruggeven. Hierbij mag de toestand van centrifuge $$d$$ niet wijzigen. Als centrifuges $$c$$ en $$d$$ niet evenveel gaten hebben of als er een gevuld gat is in centrifuge $$d$$ dat leeg is in centrifuge $$c$$, dan mag de toestand van centrifuge $$c$$ niet wijzigen en moet er een AssertionError opgeworpen worden met de boodschap gaten kunnen niet geleegd worden.
> let centrifuge = new Centrifuge(6, [4, 1, 3, 0]);
> centrifuge.toString()
"Centrifuge(6, [0, 1, 3, 4])"
> centrifuge.roteer().toString()
"Centrifuge(6, [1, 2, 4, 5])"
> centrifuge.roteer(wijzerzin=true).toString()
"Centrifuge(6, [0, 1, 3, 4])"
> centrifuge.spiegel().toString()
"Centrifuge(6, [0, 2, 3, 5])"
> centrifuge.spiegel().toString()
"Centrifuge(6, [0, 1, 3, 4])"
> centrifuge = new Centrifuge(6, [2, 0, 5]);
> centrifuge.isGelijk(new Centrifuge(6, [2, 4, 5]))
true
> centrifuge.isGelijk(new Centrifuge(6, [3, 4, 5]))
false
> centrifuge.toString()
"Centrifuge(6, [0, 2, 5])"
> centrifuge.roteer().roteer().spiegel().toString()
"Centrifuge(6, [2, 4, 5])"
> centrifuge.spiegel().roteer(true).roteer(true).toString()
"Centrifuge(6, [0, 2, 5])"
> centrifuge.vul(new Centrifuge(6, [1, 4])).toString()
"Centrifuge(6, [0, 1, 2, 4, 5])"
> centrifuge.vul(new Centrifuge(6, [1, 4, 2])).toString()
AssertionError: gaten kunnen niet gevuld worden
> centrifuge.leeg(new Centrifuge(6, [1, 4])).toString()
"Centrifuge(6, [0, 2, 5])"
> centrifuge.leeg(new Centrifuge(6, [1, 5])).toString()
AssertionError: gaten kunnen niet geleegd worden