Die Mission
Bekanntlich ist das genetische Material aller bekannten Lebewesen auf der Erde in DNA kodiert; unter Verwendung der vier Nukleotide Adenin, Thymin, Cytosin und Guanin. (Gemeinsam vertreten durch ATGC).
Ein Bioinformatiker, der ein ganzes Genom speichern möchte, möchte dies natürlich nicht als ASCII speichern, da jede Auswahl durch nur zwei Bits dargestellt werden kann!
Die Spezifikation
Ihre Aufgabe ist es, ein Paar von Programmen, Funktionen oder Methoden zu schreiben, um eine ASCII-Darstellung in eine binäre Darstellung und zurück zu konvertieren. Darstellen A
als b00
, T
als b01
, G
als b10
und C
als b11
(fortan "Einheiten").
Außerdem sollten die High-Bits jedes Bytes die Anzahl der Einheiten im Byte enthalten, sodass jedes Byte ein Triplett darstellt.
Zum Beispiel: "GATTACCA"
wird b11 100001 b11 010011 b10 1100xx
.
Leerzeichen, Tabulatoren und Zeilenumbrüche sollten in der ASCII-zu-Binäreingabe ignoriert werden. Jedes Zeichen, das nicht im Satz von enthalten [ \r\n\tATGC]
ist, ist ein Fehler und kann entweder ignoriert oder die Verarbeitung abgebrochen werden.
In der Binär-zu-ASCII-Eingabe können Bytes, deren zwei hohe Bits sind b00
, ignoriert werden.
Die ASCII-Ausgabe kann Leerzeichen enthalten. sollte aber niemals mehr als das 4-fache der Größe des Binäreingangs plus ein Byte lang sein und muss mit einem Zeilenumbruch enden.
Der Binärausgang kann eine beliebige Anzahl von b00xxxxxx
"Steuerbytes" enthalten; darf aber nie länger sein als der ASCII-Eingang.
Jedes Konvertierungsprogramm muss Eingaben beliebiger Länge unterstützen. und sollte die Codierung oder Decodierung in ungefähr linearer Zeit abschließen.
Die Wendung
Unglücklicherweise für den Bioinformatiker, für den Sie diese Aufgabe ausführen, hat er Ihnen in gewisser Weise Unrecht getan, auf einer persönlichen, aber vielleicht kleinen Ebene.
Vielleicht ist er einmal mit deiner Schwester ausgegangen und hat sie nie wieder angerufen. Vielleicht ist er auf den Schwanz Ihres Hundes getreten. Die Einzelheiten sind nicht wirklich wichtig.
Wichtig ist, dass Sie eine Chance auf Rückzahlung haben!
Die Details
Bei jeder Konvertierung sollte eine kleine Fehlerrate auftreten. in der Größenordnung von einem Fehler pro zehntausend bis eine Million Einheiten verarbeitet.
Ein Fehler kann einer der folgenden sein:
- Kopierfehler:
"GAT TAC CA"
wird"GAT TAA CCA"
- Löschfehler:
"GAT TAC CA"
wird"GAT TAC A"
- Übersetzungsfehler:
"GAT TAC CA"
wird"GTA TAC CA"
- Triplettverdopplungen:
"GAT TAC CA"
werden"GAT TAC TAC CA"
- Drillingsschlupf:
"GAT TAC CA"
wird"TAC GAT CA"
- Triplettumkehrungen:
"GAT TAC CA"
werden"GAT CAT CA"
Dass Fehler eingeführt werden, sollte natürlich nicht sofort aus dem Code ersichtlich sein; und unabhängig von der Länge der Eingabe; Die Konvertierung sollte mindestens einen Fehler verursachen.
Zwei Läufe mit identischen Eingaben sollten nicht unbedingt identische Ausgaben erzeugen.
Der Trick
Der abscheuliche Bioinformatiker ist ein mäßig kompetenter Kodierer; Daher werden einige Konstrukte automatisch erkannt und sind als solche verboten:
- Er erkennt automatisch alle Aufrufe von System-Zufallszahlengeneratoren wie rand (), random () oder das Lesen aus / dev / urandom oder / dev / random (oder was auch immer das Sprachäquivalent ist).
- Er wird auch alle überflüssigen Variablen, Zähler oder Schleifen bemerken.
Die Wertung
Der Kodierer und der Dekodierer werden einzeln bewertet.
Jede wird dreimal mit einem Satz von 100 zufällig generierten Eingabedateien ausgeführt, wobei jede Datei eine Größe in der Größenordnung von 3 Millionen Einheiten hat.
Die Daten für die Encoder-Testfälle werden ungefähr so erstellt:
for (l = 1 => bigNum)
for (t = 1 => 20)
random_pick(3,ATGC)
t == 20 ? newline : space
Die Daten für die Decoder-Testfälle werden ungefähr so erstellt:
for (u = 1 => bigNum)
for (t = 1 => 20)
random_byte() | 0b11000000
0x00
Der Encoder
- Jedes Byte, das in der erwarteten Mindestlänge in der tatsächlichen Länge fehlt, wird mit -1 bis maximal -1000 Punkten bewertet. (Die erwartete Mindestlänge beträgt
ceil(count(ATGC) / 3)
.)
Der Decoder
- Jedes Byte über der erwarteten maximalen Länge in der tatsächlichen Länge wird mit -1 bis maximal -1000 Punkten bewertet. (Die erwartete maximale Länge beträgt
size(input) * 4 + 1
.)
Beide
- Für jede Art von Fehler, die erzeugt werden kann, werden 100 Punkte vergeben. Für jeweils 600 Punkte sind 1200 Punkte möglich.
- Jeder Testfall, bei dem der Encoder mehr als 30% mehr oder weniger Fehler als der eigene Durchschnitt erzeugt, wird mit -5 Punkten bestraft.
- Für jeden Testfall, bei dem der Encoder weniger als 15% mehr oder weniger Fehler als der eigene Durchschnitt erzeugt, werden 5 Punkte vergeben.
- Jeder Testfall, in dem alle drei Läufe zu identischen Ergebnissen führen, wird mit -10 Punkten bestraft.
Harte Anforderungen
Ein Eintrag wird disqualifiziert, wenn:
- Für jede gültige Eingabe, die länger als ein Triplett ist, wird kein einziger Fehler erzeugt.
- Die Leistung ist so, dass der Testhandschuh nicht innerhalb von ungefähr einer Stunde beendet werden kann.
- Es erzeugt durchschnittlich mehr als einen Fehler pro zehntausend Einheiten.
- Es erzeugt im Durchschnitt weniger als einen Fehler pro Million Einheiten.
Die Schnittstelle
Die Teilnehmer sollten Eingaben in die Standardeingabe und Ausgaben in die Standardausgabe akzeptieren.
Wenn der Eintrag ein Programm mit Doppelfunktion ist; Die Schalter -e
und -d
sollten das Programm für die Codierung bzw. Decodierung einstellen.
Beispielaufrufe:
$ encoder <infile.txt >outfile.bin
$ decoder <infile.bin >outfile.txt
$ recoder -e <infile.txt >outfile.bin
Der Gewinner
Der Gewinner ist der Beitrag mit der höchsten Punktzahl. Das theoretische Maximum ist 1200 für Fehlerarten plus 3000 Punkte für die Stabilität der Fehlererzeugungsrate.
Im unwahrscheinlichen Fall eines Unentschieden; Der Gewinner wird anhand der Stimmenzahl ermittelt.
Die zusätzlichen Hinweise
Zum Ausführen des Testhandschuhs sollte jeder Eintrag Anweisungen zum Ausführen oder Kompilieren enthalten.
Alle Einträge sollten vorzugsweise auf einem Linux-Computer ohne X ausführbar sein.
quelle
Antworten:
Perl 5.10
Ich bin froh, meine Lösung in Perl präsentieren zu können.
Als ich die Herausforderung startete, war ich mir ziemlich sicher, dass Perl deutlich unter dem Limit von 1 Stunde bleiben würde.
Zu Testzwecken habe ich einen einfachen Probengenerator und einen codierten Probengenerator entwickelt.
Dann entwickelte ich den Encoder, der einen größeren Aufwand und einen längeren Code produzierte. Der Encoder funktioniert wie folgt:
Die codierte Binärausgabe ist so formatiert, dass sie mit einem Zeilenumbruch abgeschlossene "Zeilen" mit 20 Oktetten enthält, wobei jedes Oktett ein Triplett mit zwei Präfixzeichen (wie eine zyklische Zeilennummer) codiert.
Zum Beispiel die kürzeste Drei-Byte-Eingabe:
sollte die kürzeste Ausgabe von drei Bytes plus New-Line ergeben.
das ist
und
sollte die folgende binäre geben.
Sollte wegen der geringen Fehlerrate: Für die kleinste Eingabe führt das Skript 1 Fehler ein.
Bei einem Dateilauf von 3 Millionen Triplets führt der Encoder 11 Fehler ein.
Vorausgesetzt, das Skript ist dnacodec3.pl, wird die Ausführung wie gewohnt an der Eingabeaufforderung aufgerufen:
Der Decoder arbeitet wie folgt:
Ich habe eine Testdatei mit 3 Millionen Triplets (ca. 12 MB) erstellt und auf Timing getestet. Wenn ich meinen Laptop mit einem Intel Core i5 vPro mit 2,6 GHz benutze, dauert die Ausführung des 3M-Encoders immer weniger als 20 Sekunden. Während des Laufs werden 200-220 MByte RAM benötigt. Was für eine Verschwendung!
Der Dekodierungslauf dauert weniger als 10 Sekunden. Es kann keine Fehler einführen ... vorerst.
Wieder für den Dekodierlauf
Hier ist der Code
Und hier ist der Sample Generator:
quelle