¿Cómo reescribir un código de una línea (o un código de menos líneas en la línea de comando) de este código en Perl?

StackOverflow https://stackoverflow.com/questions/5402405

  •  28-10-2019
  •  | 
  •  

Pregunta

Tengo un código como ese:

#!/usr/bin/perl
use strict;
use warnings;      
my %proteins = qw/
    UUU F UUC F UUA L UUG L UCU S UCC S UCA S UCG S UAU Y UAC Y UGU C UGC C UGG W
    CUU L CUC L CUA L CUG L CCU P CCC P CCA P CCG P CAU H CAC H CAA Q CAG Q CGU R CGC R CGA R CGG R
    AUU I AUC I AUA I AUG M ACU T ACC T ACA T ACG T AAU N AAC N AAA K AAG K AGU S AGC S AGA R AGG R
    GUU V GUC V GUA V GUG V GCU A GCC A GCA A GCG A GAU D GAC D GAA E GAG E GGU G GGC G GGA G GGG G
    /;
open(INPUT,"<dna.txt");
while (<INPUT>) {    
    tr/[a,c,g,t]/[A,C,G,T]/;
    y/GCTA/CGAU/;    
    foreach my $protein (/(...)/g) {
        if (defined $proteins{$protein}) {
        print $proteins{$protein};
        }
}
}
close(INPUT);

Este código está relacionado con la respuesta de mi otra pregunta: ADN a ARN y obtención de proteínas con Perl

La salida del programa es:

SIMQNISGREAT

¿Cómo puedo reescribir ese código con Perl, se ejecutará en la línea de comando y se reescribirá con menos código (si es posible, código de una línea)?

PD 1: dna.txt es así:

TCATAATACGTTTTGTATTCGCCAGCGCTTCGGTGT

PD 2: Si el código será de menos líneas, se acepta escribir el my %proteins variable en un archivo.

¿Fue útil?

Solución

Alguien (@kamaci) dijo mi nombre en otro hilo.Esto es lo mejor que se me ocurre mientras mantengo la tabla de proteínas en la línea de comando:

perl -nE'say+map+substr("FYVDINLHL%VEMKLQL%VEIKLQFYVDINLHCSGASTRPWSGARTRP%SGARTRPCSGASTR",(s/GGG/GGC/i,vec($_,0,32)&101058048)%63,1),/.../g' dna.txt

(Citas de Shell, para intercambio de citas de Windows ' y " caracteres).Esta versión marca codones no válidos con %, probablemente puedas solucionarlo agregando =~y/%//d en un lugar apropiado.

Pista:Esto selecciona 6 bits de la codificación ASCII sin procesar de un triple de ARN, dando 64 códigos entre 0 y 101058048;Para obtener un índice de cadena, reduzco el resultado en módulo 63, pero esto crea un mapeo doble que lamentablemente tuvo que codificar dos proteínas diferentes.El s/GGG/GGC/i asigna uno de ellos a otro que codifica la proteína correcta.

Tenga en cuenta también los paréntesis antes del % operador que ambos aislar el , operador de la lista de argumentos de substr y fijar la precedencia de & vs %.Si alguna vez usas eso en el código de producción, eres una mala, mala persona.

Otros consejos

Los únicos cambios que recomendaría hacer son simplificar su while bucle:

while (<INPUT>) {
    tr/acgt/ACGT/;
    tr/GCTA/CGAU/;
    foreach my $protein (/(...)/g) {
        if (defined $proteins{$protein}) {
            print $proteins{$protein};
        }
    }
}

Desde y y tr son sinónimos, sólo debes utilizar uno de ellos.Creo tr se lee mejor que y, así que elegí tr.Además, las llamaste de manera muy diferente, pero esto debería tener el mismo efecto y solo menciona las letras que realmente cambias.(Todos los demás personajes estaban siendo transpuestos a sí mismos.Eso lo hace mucho Es más difícil ver lo que realmente se está cambiando.)

Es posible que desee eliminar el open(INPUT,"<dna.txt"); y correspondiente close(INPUT); líneas, ya que hacen que sea mucho más difícil usar su programa en canalizaciones de shell o con diferentes archivos de entrada.Pero eso depende de usted, si el archivo de entrada siempre ser dna.txt y nunca nada diferente, esto está bien.

#!/usr/bin/perl
%p=qw/UUU F UUC F UUA L UUG L UCU S UCC S UCA S UCG S UAU Y UAC Y UGU C UGC C UGG W
CUU L CUC L CUA L CUG L CCU P CCC P CCA P CCG P CAU H CAC H CAA Q CAG Q CGU R CGC R CGA R CGG R
AUU I AUC I AUA I AUG M ACU T ACC T ACA T ACG T AAU N AAC N AAA K AAG K AGU S AGC S AGA R AGG R
GUU V GUC V GUA V GUG V GCU A GCC A GCA A GCG A GAU D GAC D GAA E GAG E GGU G GGC G GGA G GGG G/;
$_=uc<DATA>;y/GCTA/CGAU/;map{print if$_=$p{$_}}/(...)/g
__DATA__
TCATAATACGTTTTGTATTCGCCAGCGCTTCGGTGT

Uf.Lo mejor que se me ocurre, al menos tan rápido.Si está seguro de que la entrada siempre está en mayúsculas, también puede soltar la uc guardando otros dos personajes.O si la entrada es siempre la misma, puedes asignarla a $_ inmediatamente en lugar de leerlo desde cualquier lugar.

Supongo que no necesito decir que este código debería no utilizarse en entornos de producción o en cualquier otro lugar que no sea pura diversión.Cuando se realiza programación real, la legibilidad casi siempre gana a la compacidad.

Algunas otras versiones que mencioné en los comentarios:

Lectura de %p y el ADN de archivos:

#!/usr/bin/perl
open A,"<p.txt";map{map{/(...)/;$p{$1}=chop}/(... .)/g}<A>;
open B,"<dna.txt";$_=uc<B>;y/GCTA/CGAU/;map{print if$_=$p{$_}}/(...)/g

De concha con perl -e:

perl -e 'open A,"<p.txt";map{map{/(...)/;$p{$1}=chop}/(... .)/g}<A>;open B,"<dna.txt";$_=uc<B>;y/GCTA/CGAU/;map{print if$_=$p{$_}}/(...)/g'

La mayoría de las cosas ya se han señalado, especialmente la importancia de la legibilidad.No intentaría reducir el programa más de lo que sigue.

use strict;
use warnings;
# http://stackoverflow.com/questions/5402405/
my $fnprot = shift || 'proteins.txt';
my $fndna  = shift || 'dna.txt';
# build protein table
open my $fhprot, '<', $fnprot or die "open $fnprot: $!";
my %proteins = split /\s+/, do { local $/; <$fhprot> };
close $fhprot;
# process dna data
my @result;
open my $fhdna, '<', $fndna or die "open $fndna: $!";
while (<$fhdna>) {
    tr/acgt/ACGT/;
    tr/GCTA/CGAU/;
    push @result, map $proteins{$_}, grep defined $proteins{$_}, m/(...)/g;
}
close $fhdna;
# check correctness of result (given input as per original post)
my $expected = 'SIMQNISGREAT';
my $got = join '', @result;
die "@result is not expected" if $got ne $expected;
print "@result - $got\n";

La única cosa "de una sola línea" que agregué es la push map grep m//g en el bucle while.Tenga en cuenta que Perl 5.10 agrega el operador "definido o": // - que te permite escribir:

push @result, map $proteins{$_} // (), m/(...)/g;

Ah vale, el open do local $/ El modismo de extracción de archivos es útil para sorber archivos pequeños en la memoria.Espero que lo encuentres un poco inspirador.:-)

Si escribe datos de proteínas en otro archivo, delimitados por espacios y sin salto de línea.Por lo tanto, puede importar datos leyendo el archivo una vez.

#!/usr/bin/perl
use strict;
use warnings;      

open(INPUT, "<mydata.txt");
open(DATA, "<proteins.txt");
my %proteins = split(" ",<DATA>);

while (<INPUT>) {
    tr/GCTA/CGAU/;
    while(/(\w{3})/gi) {print $proteins{$1} if (exists($proteins{$1}))};
}
close(INPUT);
close(DATA);

Puede eliminar la línea de código " tr / a, c, g, t / A, C, G, T / " porque el operador de coincidencia tiene la opción para el casoinsensible (opción i ).Y el bucle foreach original se puede optimizar como el código anterior.$1 aquí es el resultado del patrón coincidente entre paréntesis de la operación de coincidencia /(\w{3})/gi

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top