La mission
Comme cela est bien connu, le matériel génétique de toutes les créatures connues sur Terre est codé dans l'ADN; en utilisant les quatre nucléotides adénine, thymine, cytosine et guanine. (Communément représenté par ATGC).
Un bioinformaticien souhaitant stocker un génome entier ne voudra bien sûr pas le stocker en ASCII, car chaque choix peut être représenté par seulement deux bits!
La spécification
Votre mission, si vous l'acceptez, est d'écrire une paire de programmes, de fonctions ou de méthodes pour convertir une représentation ASCII en représentation binaire et inversement; représentant A
comme b00
, T
comme b01
, G
comme b10
et C
comme b11
(désormais "unités").
De plus, les bits de poids fort de chaque octet doivent contenir le nombre d'unités de l'octet, ce qui fait que chaque octet représente un triplet.
Par exemple: "GATTACCA"
devient b11 100001 b11 010011 b10 1100xx
.
Dans l'entrée ASCII vers binaire, les espaces, les tabulations et les retours à la ligne doivent être ignorés. Tout caractère ne figurant pas dans l'ensemble de [ \r\n\tATGC]
est une erreur et peut être ignoré ou terminer le traitement.
Dans l'entrée binaire vers ASCII, les octets dont les deux bits de poids fort sont b00
ignorés.
La sortie ASCII peut contenir des espaces; mais ne doit jamais dépasser 4 fois la taille de l'entrée binaire plus un octet de long et doit se terminer par une nouvelle ligne.
La sortie binaire peut contenir un nombre arbitraire d' b00xxxxxx
octets de "contrôle"; mais ne doit jamais être plus longue que l'entrée ASCII.
Chaque programme de conversion doit prendre en charge des entrées de longueur arbitraire; et devrait terminer le codage ou le décodage en un temps approximativement linéaire.
La torsion
Malheureusement pour le bioinformaticien pour lequel vous effectuez cette tâche, il vous a en quelque sorte fait du tort, à un niveau personnel mais peut-être mesquin.
Peut-être est-il sorti une fois avec votre sœur et ne l'a plus jamais appelée. Peut-être qu'il a marché sur la queue de votre chien. Les détails ne sont pas vraiment importants.
Ce qui est important, c'est que vous ayez une chance de récupération!
Les détails
Chaque conversion doit introduire un petit taux d'erreur; de l'ordre d'une erreur par dix mille à un million d'unités traitées.
Une erreur peut être l'une des suivantes:
- Erreurs de duplication:
"GAT TAC CA"
devient"GAT TAA CCA"
- Erreurs de suppression:
"GAT TAC CA"
devient"GAT TAC A"
- Erreurs de traduction:
"GAT TAC CA"
devient"GTA TAC CA"
- Duplications en triplets:
"GAT TAC CA"
devient"GAT TAC TAC CA"
- Glissements de triplets:
"GAT TAC CA"
devient"TAC GAT CA"
- Inversion de triplet:
"GAT TAC CA"
devient"GAT CAT CA"
Le fait que des erreurs soient introduites ne doit bien sûr pas être immédiatement évident dans le code; et quelle que soit la longueur de l'entrée; la conversion doit introduire au moins une erreur.
Deux passages avec des entrées identiques ne devraient pas nécessairement produire des sorties identiques.
L'astuce
Le vil bioinformaticien est un codeur moyennement compétent; et en tant que tel, certaines constructions seront automatiquement découvertes et sont en tant que telles interdites:
- Il découvrira automatiquement tous les appels aux générateurs de nombres aléatoires du système, tels que rand (), random (), ou lisant dans / dev / urandom ou / dev / random (ou quel que soit l'équivalent linguistique).
- Il remarquera également toutes les variables, compteurs ou boucles superflus.
La notation
L'encodeur et le décodeur seront notés individuellement.
Chacun sera exécuté 3 fois contre un ensemble de 100 fichiers d'entrée générés aléatoirement, chaque fichier ayant une taille de l'ordre de 3 millions d'unités.
Les données pour les cas de test de l'encodeur seront créées approximativement comme suit:
for (l = 1 => bigNum)
for (t = 1 => 20)
random_pick(3,ATGC)
t == 20 ? newline : space
Les données pour les cas de test du décodeur seront créées approximativement comme suit:
for (u = 1 => bigNum)
for (t = 1 => 20)
random_byte() | 0b11000000
0x00
L'encodeur
- Chaque octet manquant de la longueur minimale attendue dans la longueur réelle marquera -1 points, jusqu'à un maximum de -1000. (La longueur minimale attendue est
ceil(count(ATGC) / 3)
.)
Le décodeur
- Chaque octet sur la longueur maximale attendue dans la longueur réelle marquera -1 point, jusqu'à un maximum de -1000. (La longueur maximale attendue est
size(input) * 4 + 1
.)
Tous les deux
- Chaque type d'erreur qui peut être produit marquera 100 points; pour un total de 600 points possible pour chacun, 1200 au total.
- Chaque cas de test pour lequel l'encodeur produit plus de 30% d'erreurs en plus ou en moins que sa propre moyenne sera pénalisé de -5 points.
- Chaque cas de test pour lequel l'encodeur produit moins de 15% d'erreurs en plus ou en moins que sa propre moyenne recevra 5 points.
- Chaque cas de test où les trois séries produisent des sorties identiques sera pénalisé de -10 points.
Exigences strictes
Une inscription sera disqualifiée si:
- Pour toute entrée valide de plus d'un triplet, elle ne produit même pas une erreur.
- Ses performances sont telles qu'il ne peut pas terminer le gant de test dans environ une heure.
- Il produit en moyenne plus d'une erreur sur dix mille unités.
- Il produit en moyenne moins d'une erreur par million d'unités.
L'interface
Les participants doivent accepter l'entrée sur l'entrée standard et la sortie sur la sortie standard.
Si l'entrée est un programme à double fonction; les commutateurs -e
et -d
devraient définir le programme pour le codage et le décodage, respectivement.
Exemples d'appels:
$ encoder <infile.txt >outfile.bin
$ decoder <infile.bin >outfile.txt
$ recoder -e <infile.txt >outfile.bin
Le gagnant
Le gagnant est l'entrée avec le score le plus élevé; le maximum théorique étant de 1200 pour les types d'erreur plus 3000 points pour la stabilité du taux de génération d'erreur.
Dans le cas peu probable d'un match nul; le gagnant sera déterminé par le décompte des voix.
Les notes supplémentaires
Aux fins de l'exécution du test gant, chaque entrée doit inclure des instructions d'exécution ou de compilation.
Toutes les entrées doivent de préférence être exécutables sur une machine Linux sans X.
la source
Réponses:
Perl 5.10
Je suis heureux de présenter ma solution en Perl.
Quand j'ai commencé le défi, j'étais sûr que Perl resterait bien en dessous de la limite de 1 heure.
À des fins de test, j'ai développé un générateur d'échantillons simple et un générateur d'échantillons codés.
Ensuite, j'ai développé l'encodeur qui a demandé plus d'efforts et produit un code plus long. L'encodeur fonctionne comme suit:
La sortie binaire codée est ainsi formatée en "lignes" terminées par une nouvelle ligne de 20 octets où chaque octet code un triplet, avec deux caractères de préfixe (comme un numéro de ligne cyclique).
par exemple, l' entrée de trois octets la plus courte :
devrait donner la sortie la plus courte de trois octets plus une nouvelle ligne.
C'est
et
devrait donner le binaire suivant.
Devrait à cause du petit taux d'erreur: Pour la plus petite entrée, le script introduit 1 erreur.
Pour un fichier de 3 millions de triplets, l'encodeur introduit 11 erreurs.
À condition que le script soit dnacodec3.pl, l'exécution est invoquée à l'invite de commande comme d'habitude:
Le décodeur fonctionne comme suit:
J'ai préparé un échantillon de 3 millions de triplets (environ 12 Mo) et testé le timing. En utilisant mon ordinateur portable avec un Intel Core i5 vPro à 2,6 GHz, le fonctionnement de l'encodeur 3M prend toujours moins de 20 secondes. Pendant l'exécution, il faut 200 à 220 Mo de RAM. Quel gâchis!
Le cycle de décodage prend moins de 10 secondes. Il ne peut pas introduire d'erreurs ... pour l'instant.
Encore une fois, pour le décodage
Voici le code
Et voici le générateur d'échantillons:
la source