Röntgendiffractie is een techniek die gebruikt wordt om de structuur van vaste stoffen te bepalen. Als de techniek toegepast wordt op kristallen, dan kan daarmee de kristalstructuur zeer nauwkeurig bepaald worden. Uit het diffractiepatroon — de verstrooiing van de röntgenstralen — is het immers mogelijk om de positie van de atomen in de moleculen te reconstrueren. In de vroege jaren '50 begonnen wetenschappers deze techniek toe te passen op biologische moleculen zoals DNA en eiwitten. De techniek wordt ook gebruikt voor het bepalen van de structuur van mineralen, eenvoudige en meer complexe organische verbindingen.
Röntgendiffractie is een zeer nauwkeurige microscopische techniek. Waar atoomkrachtmicroscopie op dit ogenblik maar net toelaat om individuele atomen te zien, kan de positie van de atomen met röntgendiffractie nog 100-1000 maal nauwkeuriger bepaald worden.
We modelleren de verstrooiing van röntgenstralen die botsen tegen de atomen van een vlakke molecule, door het rechthoekig gebied dat wordt ingenomen door de molecule onder te verdelen in $$m$$ rijen en $$n$$ kolommen ($$m, n \in \mathbb{N}_0$$). Elk atoom van de molecule ligt in een cel van dit rechthoekig rooster, en cellen bevatten nooit meer dan één atoom.
De röntgenstralen die we laten invallen op de molecule zijn steeds gericht naar het noorden (N), oosten (O), zuiden (Z) of westen (W). Daarom stellen we een richting voor als een hoofdletter (String) zoals aangegeven in de voorgaande zin.
Op basis van de manier waarop ze invallende röntgenstralen afbuigen, worden atomen onderverdeeld in drie categorieën. Atomen zonder reflectie buigen röntgenstralen niet af. Atomen met voorwaartse reflectie buigen röntgenstralen die naar het oosten gericht zijn af naar het noorden (en vice versa) en buigen röntgenstralen die naar het zuiden gericht zijn af naar het westen (en vice versa). Atomen met een achterwaartse reflectie buigen röntgenstralen die naar het oosten gericht zijn af naar het zuiden (en vice versa) en buigen röntgenstralen die naar het noorden gericht zijn af naar het westen (en vice versa).
Om te kunnen verwijzen naar specifieke cellen in het rooster, nummeren we de rijen oplopend van noord naar zuid en de kolommen van west naar oost, waarbij we steeds beginnen te nummeren vanaf nul (grijze getallen op onderstaande figuur). We kunnen de positie van een cel in het rooster dan voorstellen door een array $$[r, k]$$ (Array), waarbij $$r$$ het nummer (Number) van de rij en $$k$$ het nummer (Number) van de kolom is waarop de cel gelegen is. Een röntgenstraal die invalt op een molecule beschrijven we aan de hand van de positie van de cel waar de straal op de molecule invalt, samen met de richting waarnaar de straal gericht is. Je opdracht bestaat erin om voor een invallende röntgenstraal te bepalen waar en in welke richting hij de molecule zal verlaten.
Hieronder tonen we enkele voorbeelden van röntgenstralen die invallen op een molecule en door de atomen met voorwaartse en achterwaartse reflectie afgebogen worden. De linkse molecule heeft bijvoorbeeld een atoom met voorwaartse reflectie op positie [0, 2] en een atoom met achterwaartse reflectie op positie [1, 1]. Zoals aangegeven door de groene lijn zal een röntgenstraal die naar het zuiden gericht is en invalt op positie [0, 1] door het atoom op positie [1, 1] afgebogen worden naar het oosten en de molecule in die richting verlaten op positie [1, 4].
Definieer een klasse Atoom waarmee atomen kunnen voorgesteld worden die röntgenstralen kunnen afbuigen. Als er bij het aanmaken van een atoom (Atoom) geen argumenten doorgegeven worden, dan moet je een atoom zonder reflectie krijgen. Als er bij het aanmaken van een atoom (Atoom) een Booleaanse waarde true (Boolean) wordt doorgegeven, dan moet je een atoom met achterwaartse reflectie krijgen. Als er bij het aanmaken van een atoom (Atoom) een Booleaanse waarde false (Boolean) wordt doorgegeven, dan moet je een atoom met voorwaartse reflectie krijgen. Een atoom $$A$$ (Atoom) moet minstens de volgende methoden ondersteunen:
Een methode toString waaraan geen argumenten moeten doorgegeven worden. De methode moet de stringvoorstelling (String) van atoom $$A$$ teruggeven. Dit is één enkel karakter dat het soort reflectie van het atoom voorstelt: een punt (.) voor atomen zonder reflectie, een slash (/) voor atomen met voorwaartse reflectie en een backslash (\) voor atomen met achterwaartse reflectie.
Een methode afbuigen waaraan een string $$r$$ (String) moet doorgegeven worden. Als $$r$$ geen geldige richting voorstelt, dan moet er een AssertionError opgeworpen worden met de boodschap ongeldige richting. Anders moet voor een röntgenstraal die vanuit richting $$r$$ invalt op atoom $$A$$ teruggegeven worden in welke richting de röntgenstraal afgebogen wordt.
Definieer ook nog een klasse Molecule waarmee vlakke moleculen in de vorm van een rechthoekig $$m \times n$$ rooster kunnen voorgesteld worden. Bij het aanmaken van een molecule (Molecule) moet het aantal rijen $$m \in \mathbb{N_0}$$ (Number) en het aantal kolommen $$n \in \mathbb{N_0}$$ (Number) van het rooster doorgegeven worden. Elke cel van het rooster bevat een atoom met een bepaald soort reflectie. Na initialisatie zijn dit nog allemaal atomen zonder reflectie. Een molecule $$M$$ (Molecule) moet minstens de volgende methoden ondersteunen:
Een methode toString waaraan geen argumenten moeten doorgegeven worden. De methode moet de stringvoorstelling van molecule $$M$$ teruggeven. Daarin vormt elke rij van het rooster een afzonderlijke regel. Een rij wordt voorgesteld door de stringvoorstellingen van de atomen op die rij, die telkens door een spatie van elkaar gescheiden worden.
Een methode plaats waarmee één of meer atomen met dezelfde soort reflectie in het rooster van molecule $$M$$ kunnen geplaatst worden. Het eerste argument dat aan de methode moet doorgegeven worden, is een atoom $$A$$ (Atoom) dat het soort reflectie aangeeft van de atomen die in het rooster moeten geplaatst worden. Daarna kunnen aan de methode ook nog één of meer posities in het rooster doorgegeven worden (als afzonderlijke argumenten), waarop atomen met de reflectie van atoom $$A$$ moeten geplaatst worden. Als één van de gegeven posities buiten het rooster valt, dan moet een AssertionError opgeworpen worden met de boodschap ongeldige positie, en mag de oorspronkelijke configuratie van molecule $$M$$ niet wijzigen.
Een methode afbuiging waaraan twee argumenten moeten doorgegeven worden, die de coördinaten van een invallende röntgenstraal voorstellen: i) de positie van de cel waar de straal op de molecule $$M$$ invalt en ii) de richting waarnaar de straal gericht is. De methode moet een array (Array) van posities in het rooster van molecule $$M$$ teruggeven die de volgorde aangeeft van de cellen waarlangs de röntgenstraal passeert bij zijn doortocht doorheen de molecule. Hierbij wordt de straal door de atomen afgebogen zoals beschreven in de inleiding van de opgave.
Een methode diffractie waaraan dezelfde twee argumenten (met dezelfde betekenis) moeten doorgegeven worden als aan de methode afbuiging. De methode moet een array (Array) teruggeven die twee elementen bevat: i) de positie van de cel waar de invallende röntgenstraal de molecule $$M$$ terug verlaat, en ii) de richting waarin de straal de molecule $$M$$ verlaat.
> const atoom = new Atoom(false);
> atoom.toString()
"/"
> atoom.afbuigen("N")
"O"
> atoom.afbuigen("W")
"Z"
> atoom.afbuigen("X")
AssertionError: ongeldige richting
> const molecule = new Molecule(5, 5);
> console.log(molecule.toString());
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
> console.log(molecule.plaats(new Atoom(false), [0, 2]).toString());
. . / . .
. . . . .
. . . . .
. . . . .
. . . . .
> console.log(molecule.plaats(new Atoom(true), [1, 1]).toString());
. . / . .
. \ . . .
. . . . .
. . . . .
. . . . .
> molecule.afbuiging([0, 1], "Z")
[[0, 1], [1, 1], [1, 2], [1, 3], [1, 4]]
> molecule.diffractie([0, 1], "Z")
[[1, 4], "O"]
> console.log(molecule.plaats(new Atoom(false), [4, 4]).plaats(new Atoom(true), [3, 2], [3, 4]).toString());
. . / . .
. \ . . .
. . . . .
. . \ . \
. . . . /
> molecule.afbuiging([4, 2], "N")
[[4, 2], [3, 2], [3, 1], [3, 0]]
> molecule.diffractie([4, 2], "N")
[[3, 0], "W"]
> console.log(molecule.plaats(new Atoom(true), [0, 3], [2, 3], [4, 1]).toString())
. . / \ .
. \ . . .
. . . \ .
. . \ . \
. \ . . /
> molecule.afbuiging([1, 0], "O")
[[1, 0], [1, 1], [2, 1], [3, 1], [4, 1], [4, 2], [4, 3], [4, 4], [3, 4], [3, 3], [3, 2], [2, 2], [1, 2], [0, 2], [0, 3], [1, 3], [2, 3], [2, 4]]
> molecule.diffractie([1, 0], "O")
[[2, 4], "O"]
> molecule.plaats(new Atoom(), [6, 6])
AssertionError: ongeldige positie