De mens is al eeuwenlang op zoek naar geheime boodschappen die verborgen zitten in boeken, achterwaarts afgespeelde muziek, vreemd uitziende plateau's op Mars1, of andere dingen. Sommigen geloven bijvoorbeeld stellig dat er verborgen boodschappen in de Bijbel zitten die niet op toeval kunnen berusten — ze moeten er wel moedwillig in aangebracht zijn door niemand minder dan God de Vader zelf.
De zoektocht naar verborgen boodschappen werd nieuw leven ingeblazen door de publicatie van het boek The Bible Code2. Het is geschreven door journalist Michael Drosnin, die beweert dat de Hebreeuwse Bijbel een zeer complexe code bevat die gebeurtenissen onthult die plaatsvonden duizenden jaren nadat de Bijbel werd geschreven. Volgens Drosnin is het dan ook logisch dat er in de Bijbel boodschappen verborgen moeten zitten die iets te vertellen hebben over onze toekomst.
Om verborgen boodschappen te vinden, maakt Drosnin gebruik van een eenvoudige techniek: start bij een bepaalde letter in een tekst, en spring daarna telkens een vast aantal letters vooruit of achteruit. Op die manier valt bijvoorbeeld in bijbelvers Genesis 31:28 (King James versie) "And hast not suffered me to kiss my sons and my daughters? Thou hast now done foolishly in so doing." het woord Roswell te lezen door te starten vanaf de R in daughters, vier letters vooruit te springen naar de O in thou, nog vier letters vooruit te springen naar de S in hast, enzoverder. In datzelfde vers lees je ook het woord UFO door te starten vanaf de U in thou, en daarna telkens 12 letters vooruit te springen. En dat kan toch zeker geen toeval zijn?
De bewering dat de verborgen boodschappen in de Bijbel onmogelijk aan toeval toe te schrijven zijn, werd echter vanuit allerlei hoeken in vraag gesteld. Sommige critici van Drosnin zeggen dat de journalist niets anders doet dan data mining: in elke willekeurige tekst vallen met de gebruikte techniek en een gezonde dosis creativiteit een groot aantal verborgen boodschappen te vinden. Michael Drosnin reageerde in Newsweek op de kritiek door te stellen dat "When my critics find a message about the assassination of a prime minister encrypted in Moby Dick, I'll believe them". Wiskundige Brendan McKay van de Australian University nam de handschoen op, en toonde aan dat dat helemaal geen probleem3 bleek te zijn.
Eiwitten bestaan uit polymere ketens van aminozuren. De eiwitten die aangemaakt worden in cellen van levende organismen zijn opgebouwd uit 20 verschillende aminozuren, die elk voorgesteld worden door een hoofdletter (enkel de hoofdletters B, J, O, U, X en Z corresponderen niet met een aminozuur). Omdat de eiwitten die gecodeerd zitten in het menselijk genoom op die manier kunnen voorgesteld worden als strings van hoofdletters, kunnen we de methode van Drosnin ook toepassen om op zoek te gaan naar geheime boodschappen die gecodeerd zitten in de mens zelf.
De Latijnse spreuk alea iacta est (de teerling is geworpen) kennen we vooral omdat ze in 49 voor Christus door Julius Caesar werd uitgesproken, toen die met een staand leger de Rubicon overstak om een staatsgreep te plegen in Rome. De woorden van deze zin zitten bijvoorbeeld verborgen in de eiwitsequentie
HGLAVPFRTTHPSLECGRTSWARWSLDIAEFWLAWEASDCITDEDTKFQGDAVVAQM
die deel uitmaakt van een complexe reeks eiwitten die er samen voor zorgen dat we kunnen ruiken. Als we starten op positie 21, en telkens 4 posities vooruit springen, dan lezen we het woord ALEA. Dit zelfde woord lees je door op dezelfde positie te starten, en telkens 11 posities vooruit te springen. Je kunt ook starten op positie 36, en telkens 11 posities achteruit springen om het woord ALEA nog een derde keer terug te vinden in het eiwit. Onderstaande tabel geeft aan dat er in het eiwit ook nog twee voorkomens van het woord IACTA en twee voorkomens van het woord EST te vinden zijn.
start | stap | lengte | woord |
0 | 1 | 57 | HGLAVPFRTTHPSLECGRTSWARWSLDIAEFWLAWEASDCITDEDTKFQGDAVVAQM |
21 | 4 | 4 | A L E A |
21 | 11 | 4 | A L E A |
36 | -11 | 4 | A E L A |
27 | -6 | 5 | A T C A I |
27 | 6 | 5 | I A C T A |
29 | -10 | 3 | T S E |
29 | 8 | 3 | E S T |
Om dergelijke geheime boodschappen te vinden in een gegeven eiwitsequentie ga je als volgt te werk:
Schrijf een functie isaminowoord waaraan een string (str) moet doorgegeven worden. De functie moet een Booleaanse waarde (bool) teruggeven, die aangeeft of de gegeven string een aminowoord is. Een string is een aminowoord als het minstens lengte twee heeft en enkel bestaat uit letters die als afkorting voor aminozuren gebruikt worden (alle letters behalve B, J, O, U, X en Z). Om te bepalen of een string een aminowoord is, mag de functie geen onderscheid maken tussen hoofdletters en kleine letters.
Schrijf een functie posities waaraan twee strings (str) moeten doorgegeve worden: een eiwitsequentie en een letter. De functie moet een lijst (list) teruggeven met alle posities in de gegeven eiwitsequentie waar de gegeven letter terug te vinden is. Bij het zoeken naar letters in een eiwitsequentie mag de functie geen onderscheid maken tussen hoofdletters en kleine letters.
Schrijf een functie eiwitcode waaraan vier argumenten moeten doorgegeven worden. Het eerste argument moet een eiwitsequentie (str) zijn. De volgende drie argumenten moeten getallen (int) zijn: $$p \in \mathbb{N}$$, $$s \in \mathbb{Z}$$ en $$l \in \mathbb{N}$$. De functie moet het woord (str) van lengte $$l$$ teruggeven dat kan uitgelezen worden uit de gegeven eiwitsequentie, door te starten op positie $$p$$ en telkens $$s$$ posities vooruit (of achteruit als $$s$$ negatief is) te springen. Als het niet mogelijk is om op de aangegeven manier een woord van lengte $$l$$ uit het eiwit te lezen — omdat de startpositie niet binnen de grenzen van het eiwit ligt, of omdat je bij het springen voorbij de grenzen van het eiwit springt — dan moet de functie de lege string (str) teruggeven.
Gebruik de vorige functies om een functie eiwitzoeker te schrijven waaraan een eiwitsequentie (str) en een string (str) moeten doorgegeven worden. Als de gegeven string geen aminowoord is (volgens de definitie van de functie aminowoord), dan moet de functie een AssertionError opwerpen met de boodschap ongeldig aminowoord. Anders moet de functie een lijst (list) teruggeven met alle manieren waarop het aminowoord uit de eiwitsequentie kan gelezen worden. Een manier van uitlezen wordt voorgesteld als een tuple ($$p$$, $$s$$), waarbij $$p$$ de startpositie (int) aangeeft vanaf waar men start met lezen, en $$s$$ hoeveel posities (int) er telkens vooruit of achteruit moet gesprongen worden. De tuples moeten in oplopende volgorde voorkomen in de lijst die wordt teruggegeven. Implementeer de volgende procedure om alle manieren te vinden waarop een gegeven aminowoord uit een gegeven eiwitsequentie kan gelezen worden:
zoek alle posities in het eiwit waarop de eerste letter van het aminowoord voorkomt
zoek alle posities in het eiwit waarop de tweede letter van het aminowoord voorkomt
elke combinatie van een mogelijke positie van de eerste en de tweede letter legt vast hoeveel posities je vooruit of achteruit moet springen om de tweede letter te bereiken vanaf de eerste letter
ga voor elke combinatie na of je het gegeven aminowoord kunt uitlezen door te starten vanaf de positie van de eerste letter en herhaaldelijk het berekende aantal posities vooruit of achteruit te springen
Bij het zoeken naar voorkomens van het gegeven aminowoord in de eiwitsequentie, mag de functie geen onderscheid maken tussen hoofdletters en kleine letters. De functie eiwitzoeker heeft ook nog een optionele parameter maxstap waaraan een natuurlijk getal kan doorgegeven worden. Als er een waarde aan deze parameter wordt doorgegeven, dan geeft die het maximaal aantal posities aan dat mag vooruit of achteruit gesprongen worden bij het zoeken naar voorkomens van het gegeven aminowoord.
>>> isaminowoord('ALEA')
True
>>> isaminowoord('iacta')
True
>>> isaminowoord('Proline')
False
>>> eiwit = 'HGLAVPFRTTHPSLECGRTSWARWSLDIAEFWLAWEASDCITDEDTKFQGDAVVAQM'
>>> posities(eiwit, 'A')
[3, 21, 28, 33, 36, 51, 54]
>>> posities(eiwit, 'l')
[2, 13, 25, 32]
>>> eiwitcode(eiwit, 21, 11, 4)
'ALEA'
>>> eiwitcode(eiwit, 27, -6, 5)
'IACTA'
>>> eiwitcode(eiwit, 29, 8, 3)
'EST'
>>> eiwitcode(eiwit, 0, 25, 6)
''
>>> eiwitzoeker(eiwit, 'ALEA')
[(21, 4), (21, 11), (36, -11)]
>>> eiwitzoeker(eiwit, 'iacta')
[(27, -6), (27, 6)]
>>> eiwitzoeker(eiwit, 'EST')
[(29, -10), (29, 8)]
>>> eiwitzoeker(eiwit, 'EST', maxstap=8)
[(29, 8)]
>>> eiwitzoeker(eiwit, 'Proline')
Traceback (most recent call last):
AssertionError: ongeldig aminowoord