A missão
Como é sabido, o material genético de todas as criaturas conhecidas na Terra é codificado no DNA; usando os quatro nucleotídeos adenina, timina, citosina e guanina. (Comumente representado pela ATGC).
É claro que um bioinformaticista que deseja armazenar um genoma inteiro não deseja armazená-lo como ASCII, porque cada opção pode ser representada por meros dois bits!
A especificação
Sua missão, se você aceitar, é escrever um par de programas, funções ou métodos para converter uma representação ASCII em uma representação binária e vice-versa; representando A
como b00
, T
como b01
, G
como b10
e C
como b11
(doravante "unidades").
Além disso, os bits altos de cada byte devem conter a contagem de unidades no byte, fazendo com que cada byte represente um trio.
Por exemplo: "GATTACCA"
torna - se b11 100001 b11 010011 b10 1100xx
.
No ASCII para entrada binária, espaços, tabulações e novas linhas devem ser ignoradas. Qualquer caractere que não esteja no conjunto de [ \r\n\tATGC]
é um erro e pode ser ignorado ou encerrar o processamento.
Na entrada binária para ASCII, os bytes cujos dois bits altos são b00
podem ser ignorados.
A saída ASCII pode conter espaços em branco; mas nunca deve ter mais que 4 vezes o tamanho da entrada binária mais um byte e deve terminar com uma nova linha.
A saída binária pode conter um número arbitrário de b00xxxxxx
bytes de "controle"; mas nunca deve ser maior que a entrada ASCII.
Cada programa de conversão deve suportar entrada de comprimento arbitrário; e deve concluir a codificação ou decodificação em tempo aproximadamente linear.
A torção
Infelizmente para o bioinformaticista para quem você está realizando essa tarefa, ele de alguma forma prejudicou você, em um nível pessoal, mas talvez mesquinho.
Talvez ele tenha saído com sua irmã uma vez e nunca mais a tenha ligado. Talvez ele tenha pisado no rabo do seu cachorro. Os detalhes não são realmente importantes.
O importante é que você tenha uma chance de retorno!
Os detalhes
Cada conversão deve apresentar uma pequena taxa de erro; na ordem de um erro por dez mil a um milhão de unidades processadas.
Um erro pode ser um dos seguintes:
- Erros de duplicação:
"GAT TAC CA"
torna - se"GAT TAA CCA"
- Erros de exclusão:
"GAT TAC CA"
torna - se"GAT TAC A"
- Erros de tradução:
"GAT TAC CA"
torna - se"GTA TAC CA"
- Duplicações Triplet:
"GAT TAC CA"
torna-se"GAT TAC TAC CA"
- Deslizamentos triplos:
"GAT TAC CA"
torna - se"TAC GAT CA"
- Reversões de trigêmeos:
"GAT TAC CA"
torna - se"GAT CAT CA"
É claro que os erros serão introduzidos não devem ser imediatamente óbvios no código; e independentemente do comprimento da entrada; a conversão deve apresentar pelo menos um erro.
Duas execuções com entradas idênticas não devem necessariamente produzir saídas idênticas.
O truque
O vil bioinformaticista é um codificador moderadamente competente; e, como tal, algumas construções serão descobertas automaticamente e, como tal, são banidas:
- Ele descobrirá automaticamente todas as chamadas para geradores de números aleatórios do sistema, como rand (), random () ou leitura de / dev / urandom ou / dev / random (ou qualquer que seja o idioma equivalente).
- Ele também notará variáveis supérfluas, contadores ou loops.
A pontuação
O codificador e o decodificador serão pontuados individualmente.
Cada um deles será executado três vezes em um conjunto de 100 arquivos de entrada gerados aleatoriamente, cada arquivo com um tamanho da ordem de 3 milhões de unidades.
Os dados para os casos de teste do codificador serão criados aproximadamente da seguinte maneira:
for (l = 1 => bigNum)
for (t = 1 => 20)
random_pick(3,ATGC)
t == 20 ? newline : space
Os dados para os casos de teste do decodificador serão criados aproximadamente da seguinte maneira:
for (u = 1 => bigNum)
for (t = 1 => 20)
random_byte() | 0b11000000
0x00
O codificador
- Cada byte ausente do comprimento mínimo esperado no comprimento real receberá -1 pontos, até um máximo de -1000. (O comprimento mínimo esperado é
ceil(count(ATGC) / 3)
.)
O decodificador
- Cada byte sobre o comprimento máximo esperado no comprimento real receberá -1 pontos, até um máximo de -1000. (O comprimento máximo esperado é
size(input) * 4 + 1
.)
Ambos
- Cada tipo de erro que pode ser produzido terá 100 pontos; para um total de 600 pontos possíveis para cada um, 1200 no total.
- Cada caso de teste para o qual o codificador produz mais de 30% mais ou menos erros do que sua própria média será penalizado em -5 pontos.
- Cada caso de teste para o qual o codificador produz menos que 15% mais ou menos erros do que sua própria média receberá 5 pontos.
- Cada caso de teste em que as três execuções produzem saídas idênticas será penalizado por -10 pontos.
Requisitos difíceis
Uma entrada será desqualificada se:
- Para qualquer entrada válida com mais de um trigêmeo, ela falha em produzir um único erro.
- Seu desempenho é tal que não pode concluir a luva de teste dentro de aproximadamente uma hora.
- Em média, produz mais de um erro em cada dez mil unidades.
- Em média, produz menos de um erro em cada milhão de unidades.
A interface
Os participantes devem aceitar entrada na entrada padrão e saída para a saída padrão.
Se a entrada for um programa com dupla função; os comutadores -e
e -d
deve definir o programa para codificação e decodificação, respectivamente.
Invocações de exemplo:
$ encoder <infile.txt >outfile.bin
$ decoder <infile.bin >outfile.txt
$ recoder -e <infile.txt >outfile.bin
O vencedor
O vencedor é a entrada com a maior pontuação; o máximo teórico sendo 1200 para tipos de erros mais 3000 pontos para estabilidade na taxa de geração de erros.
No improvável evento de empate; o vencedor será determinado pela contagem de votos.
As notas adicionais
Para fins de execução da luva de teste, cada entrada deve incluir instruções de execução ou compilação.
Todas as entradas devem, de preferência, ser executáveis em uma máquina Linux sem o X.
fonte
Respostas:
Perl 5.10
Fico feliz em apresentar minha solução em Perl.
Quando iniciei o desafio, tinha certeza de que Perl ficaria bem abaixo do limite de 1 hora.
Para fins de teste, desenvolvi um gerador de amostra simples e um gerador de amostra codificado.
Depois, desenvolvi o codificador que teve um esforço maior e produziu um código mais longo. O codificador funciona da seguinte maneira:
A saída binária codificada é formatada como "linhas" terminadas em nova linha de 20 octetos, em que cada octeto codifica um tripleto, com dois caracteres de prefixo (como um número de linha cíclico).
por exemplo, a entrada mais curta de três bytes:
deve fornecer a saída mais curta de três bytes mais a nova linha.
isso é
e
deve dar o seguinte binário.
Deve por causa da pequena taxa de erro: Para a menor entrada, o script apresenta 1 erro.
Para um arquivo de três milhões de trigêmeos, o codificador apresenta 11 erros.
Desde que o script seja dnacodec3.pl, a execução é invocada no prompt de comando, como de costume:
O decodificador funciona da seguinte maneira:
Eu preparei um arquivo de teste de amostra de 3 milhões de trigêmeos (cerca de 12MByte) e testei o tempo. Usando meu laptop com um Intel Core i5 vPro a 2,6 GHz, a execução do codificador 3M sempre leva menos de 20 segundos. Durante a execução, são necessários 200-220 MByte de RAM. Que desperdício!
A execução da decodificação leva menos de 10 segundos. Não pode introduzir erros ... por enquanto.
Novamente, para a execução da decodificação
Aqui está o código
E aqui está o gerador de amostra:
fonte