#ifndef SEQPOINTER_H // voorkom dat dit bestand meerdere keren #define SEQPOINTER_H // ge-include wordt #include "variant.h" #include "deletie.h" #include "insertie.h" #include "inversie.h" #include "delinsertie.h" #include "substitutie.h" #include #include #include #include template class Vakje { public: Vakje* vorige; Vakje* volgende; T data; int rest; Vakje(); }; template Vakje::Vakje():vorige(nullptr), volgende(nullptr), data(T()), rest(0) { } template class SeqPointer { private: // Pointer die naar het eerste Vakje van de SeqPointer wijst Vakje *ingang; // Pointer die naar het laatste Vakje van de SeqPointer wijst Vakje *uitgang; // Hoeveel Vakjes de SeqPointer bevat int aantalVakjes; // Maximaal aantal bits dat in T past int grootte; // Maximale aantal symbolen die in T past int maxGrootte; // Zet de string seq om in een variabele van type T en zet in // rest hoeveel rest er over is T vakjeMaken(std::string seq, int &rest) const; // Vult een Vakje "vakje" aan met een Vakje "nieuw" void aanvullen(Vakje *vakje, Vakje *nieuw) const; // Retourneert het Vakje van plek "position" Vakje* vindVakje(int const position) const; // Voegt een nieuw Vakje achteraan de SeqPointer toe void voegachter(T const nieuwVakje, int const rest0); // Verwijdert het voorste Vakje van de SeqPointer void voorVerwijderen(); public: // Constructor voor een lege SeqPointer SeqPointer(); // Constructor die van een string een SeqPointer maakt SeqPointer(std::string const sequentie); // Copy constructor van SeqPointer SeqPointer(SeqPointer const &seqpointer); // Destructor die alle Vakjes verwijderd ~SeqPointer(); // Retourneert de waarde van de private variabele aantalVakjes int getaantalVakjes() const; // Retourneert de waarde van de private variabele ingang Vakje* getIngang() const; // Verwijdert alle Vakjes uit de SeqPointer void vernietig(); // Retourneert de SeqPointer waarmee de functie is aangeroepen SeqPointer copy() const; // Kopieert de SeqPointer sequentie in de SeqPointer waarmee de functie // is aangeroepen void copy2(SeqPointer const &sequentie); // Drukt de symbolen af die in SeqPointer zijn opgeslagen void drukAf() const; // Maakt de Vakjes uit een gegeven string void seqpointerMaken(std::string const &sequentie); // Retourneert hoeveel symbolen zijn opgeslagen in de SeqPointer int length() const; // Retourneert het character dat op position staat char char_at(int const position) const; // Kijkt of de meegegeven SeqPointer gelijk is aan de SeqPointer waarmee // de functie is aangeroepen bool equal(SeqPointer const &sequentie) const; // Geeft een nieuwe SeqPointer met de symbolen [start, end) SeqPointer slice(int const start, int const end) const; // Geeft een nieuwe SeqPointer waarbij de SeqPointer waarmee de functie is // aangeroepen en other zijn geconcateneerd SeqPointer concat(SeqPointer const &other) const; // Retourneert de reverse complement van inside SeqPointer inverse(SeqPointer const inside) const; // Past de meegegeven varianten toe op de SeqPointer waarmee de functie is // aangeroepen en retourneert de nieuwe SeqPointer SeqPointer apply(std::vector varianten) const; }; // Constructor voor een lege SeqPointer template SeqPointer::SeqPointer():ingang(nullptr), uitgang(nullptr), aantalVakjes(0), grootte(sizeof(T)*8), maxGrootte(grootte / 2) { } // SeqPointer::SeqPointer // Copy constructor van de klasse template SeqPointer::SeqPointer(SeqPointer const &seqpointer): SeqPointer() { vernietig(); Vakje * hulp = seqpointer.ingang; while(hulp != nullptr) { voegachter(hulp->data, hulp->rest); hulp = hulp->volgende; } // Kopieer de hele pointerlijst } // SeqPointer::SeqPointer // Constructor voor als een string is meegegeven template SeqPointer::SeqPointer(std::string const sequentie): SeqPointer() { seqpointerMaken(sequentie); } //SeqPointer::SeqPointer // Retourneert de private variabele aantalVakjes template int SeqPointer::getaantalVakjes() const { return aantalVakjes; } // SeqPointer::getaantalVakjes // Retourneert de private variabele ingang template Vakje* SeqPointer::getIngang() const { return ingang; } // SeqPointer::getIngang // Retourneert de lengte in symbolen van de SeqPointer waarmee // de functie is aangeroepen template int SeqPointer::length() const { Vakje *hulp = ingang; int size = 0; // Hier komt de lengte in te staan while(hulp != nullptr) { if(hulp->rest == 0) { size += maxGrootte; // Vakje is vol } else { size += maxGrootte - (hulp->rest/2); // Rest moet eraf gehaald worden } hulp = hulp->volgende; } return size; } // SeqPointer::length // Zoekt het Vakje waarin het symbool op plek positie zich bevindt en retourneert // dat Vakje template Vakje* SeqPointer::vindVakje(int const position) const { Vakje *hulp = ingang; int vakje = position/maxGrootte; // Hoeveelste vakje het is if(position < 0 || position > length()) { vakje = -1; return nullptr; } // Positie is buiten de array for(int i = 0; i < vakje; i++) { if(hulp != nullptr) { hulp = hulp->volgende; } else { vakje = -1; return nullptr; } } return hulp; } // SeqPointer::vindVakje // Retourneert uit de SeqPointer het symbool dat op position staat template char SeqPointer::char_at(int const position) const { Vakje *hulp = vindVakje(position); int plek = 0; T extra = T(0); char kar = 'X'; if(vindVakje == nullptr) { std::cerr << "Position bevindt zich buiten de sequentie" << std::endl; return kar; } if(hulp != nullptr) { plek = (position % maxGrootte)*2; // plek van position in het vakje extra = hulp->data >> (grootte - plek - 2); switch(extra & 0b11) { case 0b00: kar = 'A'; break; case 0b01: kar = 'C'; break; case 0b10: kar = 'G'; break; case 0b11: kar = 'T'; } } return kar; } // SeqPointer::char_at // Deze functie retourneert true als de sequentie en de SeqPointer waarmee // de functie is aangeroepen gelijk zijn en anders false template bool SeqPointer::equal(SeqPointer const &sequentie) const { Vakje *hulp = ingang; Vakje *hulpSeq = sequentie.ingang; while(hulp != nullptr && hulpSeq != nullptr) { if(hulp->data ^ hulpSeq->data != T()) { return false; } // De sequenties zijn verschillend if(hulp->data ^ hulpSeq->data == T() && hulp->rest != hulpSeq->rest) { return false; } // De sequentie lijken op elkaar omdat de ene allemaal A's heeft aan het // einde en de ander korter is en met nullen is opgevuld maar ze zijn dan // wel verschillend hulp = hulp->volgende; hulpSeq = hulpSeq->volgende; } if(hulp != nullptr || hulpSeq != nullptr) { return false; } // Een van de sequenties is een of meer vakjes langer return true; } // SeqPointer::equal // Voegt een nieuw Vakje toe achteraan de SeqPointer waarmee de functie // is aangeroepen. In data komt nieuwVakje te staan en rest0 wordt de rest // van het nieuwe Vakje template void SeqPointer::voegachter(T const nieuwVakje, int const rest0) { Vakje *hulp = new Vakje; hulp->data = nieuwVakje; if(ingang == nullptr) { ingang = hulp; } // De SeqPointer is dan leeg else { uitgang->volgende = hulp; } hulp->vorige = uitgang; uitgang = hulp; hulp->volgende = nullptr; aantalVakjes++; hulp->rest = rest0; } // SeqPointer::voegachter // Verwijdert het voorste vakje van de SeqPointer // als die er is template void SeqPointer::voorVerwijderen() { Vakje *hulp = ingang; if(ingang != nullptr) { ingang = ingang->volgende; if(ingang != nullptr) { ingang->vorige = nullptr; } // Als er minstens twee vakjes zijn else { uitgang = nullptr; } // Als er één vakje is delete hulp; hulp = nullptr; aantalVakjes--; } // Er moet minstens één vakje zijn } // SeqPointer::voorVerwijderen // Verwijdert alle vakjes uit de SeqPointer template void SeqPointer::vernietig() { while(ingang != nullptr) { voorVerwijderen(); } // Zolang er nog vakjes zijn, doorgaan met verwijderen } // SeqPointer::vernietig // Destructor voor SeqPointer template SeqPointer::~SeqPointer() { vernietig(); } // SeQPointer::~SeqPointer // Aan de hand van de string seq wordt bepaald wat de data van het Vakje // moet zijn en wordt die data met type T geretourneerd. In rest komt te staan // wat de rest van het vakje wordt template T SeqPointer::vakjeMaken(std::string const seq, int &rest) const { int seqgrootte = seq.length(); int teller = 0; T info = T(); while(teller < seqgrootte) { info = info << 2; // Opschuiven zodat het nieuwe symbool kan worden gezet switch(seq.at(teller)) { case 'A': info = info | 0b00; // A = 00 break; case 'C': info = info | 0b01; // C = 01 break; case 'G': info = info | 0b10; // G = 10 break; case 'T': info = info | 0b11; // T = 11 } // Het nieuwe symbool zetten door eerst te kijken welke het is teller++; } rest = grootte - seqgrootte*2; info = info << rest; // Ervoor zorgen dat de rest aan de rechterkant van info zit return info; } // SeqPointer::vakjeMaken // Zet de string sequentie om in de Vakjes die worden toegevoegd aan de // SeqPointer waarmee de functie is aangeroepen template void SeqPointer::seqpointerMaken(std::string const &sequentie) { int sequentieSize = sequentie.size(); char kar; int teller = 0; // Telt hoeveel symbolen voorbij zijn gekomen int rest = 0; std::string seq = ""; // Hier komt de sequentie die in het Vakje zal worden gestopt T info = T(); for(int i = 0; i < sequentieSize; i++) { kar = sequentie.at(i); if(teller < maxGrootte) { if(kar == 'A' || kar == 'C' || kar == 'G' || kar == 'T') { seq += kar; teller++; } // Controleren of het wel een toegestaan symbool is else { std::cerr << "Geen geldige DNA-type in de string" << std::endl; vernietig(); return; } } if(teller == maxGrootte) { info = vakjeMaken(seq, rest); voegachter(info, rest); seq = ""; teller = 0; } // Het maximaal aantal symbolen om het Vakje te vullen, is dan bereikt } if(teller != 0) { info = vakjeMaken(seq, rest); voegachter(info, rest); } // Als de laatste Vakjes nog niet zijn toegevoegd is omdat het niet // een vol Vakje maakt } // SeqPointer::seqpointerMaken template void SeqPointer::drukAf() const { Vakje *hulp = ingang; T temp = T(); while(hulp != nullptr) { int tempsize = grootte-2; for(int i = tempsize; i >= 0; i--) { temp = hulp->data >> i; i--; switch(temp & 0b11) { case 0b00: std::cout << "A"; break; case 0b01: std::cout << "C"; break; case 0b10: std::cout << "G"; break; case 0b11: default: std::cout << "T"; break; } } hulp = hulp->volgende; } std::cout << std::endl; } // Vult de data van Vakje "vakje" aan met de data van Vakje "nieuw". De data van "nieuw" // die niet in "vakje" pas wordt naar links in de integer geschoven. De rest van beide Vakjes // wordt ook aangepast template void SeqPointer::aanvullen(Vakje *vakje, Vakje *nieuw) const { if(nieuw == nullptr) { return; } // Er hoeft dan niks te gebeuren else if(vakje == nullptr) { vakje = nieuw; nieuw->data = T(0); nieuw->rest = grootte; return; } // Als vakje een nullptr is, wordt alles van nieuw in vakje gezet int opschuiven = (grootte - vakje->rest); // Hoeveel de data in nieuw moet opschuiven T hulp = nieuw->data >> opschuiven; // Data van nieuw dat bij vakje gaat worden toegevoegd vakje->data |= hulp; vakje->rest -= (grootte - nieuw->rest); if(vakje->rest < 0) { nieuw->data = nieuw->data << (grootte - opschuiven); nieuw->rest = grootte + vakje->rest; vakje->rest = 0; } // Dan zijn er nog symbolen over die in nieuw blijven staan else { nieuw->data = T(0); nieuw->rest = grootte; } } // SeqPointer::aanvullen // Retourneert de SeqPointer waarmee de functie is aangeroepen template SeqPointer SeqPointer::copy() const { Vakje *hulp = ingang; SeqPointer resultaat; while(hulp != nullptr) { resultaat.voegachter(hulp->data, hulp->rest); hulp = hulp->volgende; } return resultaat; } // SeqPointer::copy // De meegegeven sequentie wordt gekopieerd in de SeqPointer waarmee de functie is aangeroepen template void SeqPointer::copy2(SeqPointer const &sequentie) { Vakje *hulp = sequentie.ingang; // Houdt de Vakjes van sequentie bij vernietig(); // Als er nog iets in zat dan moet dat eerst weg while(hulp != nullptr) { voegachter(hulp->data, hulp->rest); hulp = hulp->volgende; } } // SeqPointer::copy // Maakt een nieuwe SeqPointer resultaat waarbij de de SeqPointer other wordt geplakt // achter de SeqPointer waarmee de functie is aangeroepen template SeqPointer SeqPointer::concat(SeqPointer const &other) const { SeqPointer resultaat = copy(); SeqPointer ander(other); // Zodat other niet wordt aangepast Vakje *hulp = ander.ingang; while(resultaat.uitgang != nullptr && hulp != nullptr) { aanvullen(resultaat.uitgang, hulp); if(hulp->rest != grootte) { resultaat.voegachter(hulp->data, hulp->rest); } hulp = hulp->volgende; } return resultaat; } // SeqPointer::concat // Retouneert een nieuwe SeqPointer resultaat met een sequentie die van start // tot end loopt van de SeqPointer waarmee de functie is aangeroepen template SeqPointer SeqPointer::slice(int const start, int const end) const { SeqPointer resultaat; SeqPointer temp = copy(); int laatste = 0; Vakje *eersteVakje = temp.vindVakje(start); Vakje *endVakje = temp.vindVakje(end); Vakje *hulp = eersteVakje; T info = T(0); int plekEerst = (start % maxGrootte)*2; // Plek in het Vakje in resultaat van start int plekLaatst = ((end - start - 1) % maxGrootte)*2; // Plek in het Vakje in resultaat van end int rest = 0; laatste = (end - start - 1)/maxGrootte; // Wordt het laatste Vakje in resultaat if(eersteVakje == nullptr || endVakje == nullptr || start > end) { std::cerr << "Start en eind voldoen niet aan de eisen." << std::endl; return SeqPointer(); } if(start == end) { return SeqPointer(); } // Dan zitten er geen symbolen in de SeqPointer info = eersteVakje->data << plekEerst; rest = eersteVakje->rest + plekEerst; resultaat.voegachter(info, rest); // Eerste Vakje alvast toevoegen hulp = hulp->volgende; for(int i = 0; i < laatste; i++) { aanvullen(resultaat.uitgang, hulp); resultaat.voegachter(hulp->data, hulp->rest); hulp = hulp->volgende; } if((resultaat.length() % maxGrootte)*2 <= plekLaatst) { aanvullen(resultaat.uitgang, hulp); } info = resultaat.uitgang->data >> (grootte - plekLaatst - 2); // Vanaf end resultaat.uitgang->data = info << (grootte - plekLaatst - 2); // alles weghalen resultaat.uitgang->rest = grootte - ((end - start) % maxGrootte)*2; if(resultaat.uitgang->rest == grootte) { resultaat.uitgang->rest = 0; } // Anders zou rest = grootte zijn bij een vol Vakje while(resultaat.uitgang->rest < 0) { resultaat.uitgang->rest += grootte; } // Rest kan negatief zijn maar door herhaald grootte op te tellen // krijg je de goede rest return resultaat; } // SeqPointer::slice // Hulpfunctie voor inversie. // Maakt van de meegegeven SeqPointer een reverse complement SeqPointer. template SeqPointer SeqPointer::inverse(SeqPointer const inside) const{ SeqPointer resultaat; Vakje *nieuw = inside.uitgang; int teller = 0; // Teller voor de lengte van hoe veel er in een vakje is gestopt T hulp = T(); // Hulp T, waarin de nieuwe vakjes worden opgebouwd int tempSize = grootte - nieuw->rest; // Grootte van laatste vakje (houdt rekening met rest) int rest = 0; while(nieuw != nullptr) { T info = nieuw->data; if(nieuw == inside.uitgang) { info = info >> nieuw->rest; } for(int j = 0; j < tempSize; j += 2) { T temp = info >> j; hulp = hulp << 2; teller++; switch(temp & 0b11) { case 0b00: hulp = hulp | 0b11; break; case 0b01: hulp = hulp | 0b10; break; case 0b10: hulp = hulp | 0b01; break; case 0b11: default: hulp = hulp | 0b00; break; } // Complement van temp komt in hulp if(teller == maxGrootte) { resultaat.voegachter(hulp, 0); hulp = T(0); teller = 0; } // Hulp zit vol, dus komt in de vector en wordt gerest } // Gaat door elke vakje van achter naar voor in de sequentie (oftewel van voor naar achter) tempSize = grootte; // reset tempSize nieuw = nieuw->volgende; } // Gaat door elk vakje van achter naar voor if(teller != 0) { rest = (maxGrootte-teller)*2; hulp = hulp << rest; resultaat.voegachter(hulp, rest); } // Teller is nog niet 0, dus er is nog een rest over in hulp return resultaat; } // SeqPointer::inverse // Past de varianten in de meegegeven vector één voor één toe aan de sequentie // en retourneert uiteindelijk de resultaat sequentie-pointer template SeqPointer SeqPointer::apply(std::vector varianten) const { int vectorSize = varianten.size(); SeqPointer product = copy(); for(int k = 0; k < vectorSize; k++) { Variant const* var = varianten.at(k); // Variant op plek k if(var->get_eind() > product.length()) { std::cerr << "Deze variant komt buiten de grenzen van de sequentie" << std::endl; return SeqPointer(); } SeqPointer const prefix = product.slice(0, var->get_start()); SeqPointer const suffix = product.slice(var->get_eind(), product.length()); if(var->get_type() == "inv") { SeqPointer temp(prefix.concat(inverse(product.slice(var->get_start(), var->get_eind())))); // prefix + inverse product.copy2(temp.concat(suffix)); // temp + suffix } // inversie else { SeqPointer const insert(var->get_inserted()); SeqPointer temp = prefix.concat(insert); // prefix + insert product.copy2(temp.concat(suffix)); // temp + suffix } // Deletie, Deletie-Insertie, Insertie: kan allemaal methetzelfde algoritme delete var; } varianten.clear(); return product; } // SeqPointer::apply #endif