Come riscrivere il codice su una riga (o meno codice sulla riga di comando) di questo codice in Perl?

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

  •  28-10-2019
  •  | 
  •  

Domanda

Ho un codice del genere:

#!/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);

Questo codice è correlato alla risposta alla mia altra domanda: DNA in RNA e ottenere proteine ​​con Perl

L'output del programma è:

SIMQNISGREAT

Come posso riscrivere quel codice con Perl, verrà eseguito sulla riga di comando e verrà riscritto con meno codice (se possibile codice a riga)?

PS1: dna.txt è così:

TCATAATACGTTTTGTATTCGCCAGCGCTTCGGTGT

PS2: Se il codice sarà di meno righe è consentito scrivere il file my %proteins variabile in un file.

È stato utile?

Soluzione

Qualcuno (@kamaci) ha chiamato il mio nome in un altro thread.Questo è il massimo che riesco a trovare mantenendo la tabella delle proteine ​​sulla riga di comando:

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

(Citazione di Shell, per Windows citazione di swap ' E " caratteri).Questa versione contrassegna i codoni non validi con %, probabilmente puoi risolverlo aggiungendo =~y/%//d in un punto appropriato.

Suggerimento:Questo seleziona 6 bit dalla codifica ASCII grezza di una tripla RNA, fornendo 64 codici compresi tra 0 e 101058048;per ottenere un indice di stringa riduco il risultato modulo 63, ma questo crea una doppia mappatura che purtroppo ha dovuto codificare due proteine ​​diverse.IL s/GGG/GGC/i ne associa uno a un altro che codifica la proteina giusta.

Notare anche le parentesi prima di % operatore quale Entrambi isolare il , operatore dall'elenco degli argomenti di substr E fissare la precedenza di & contro %.Se mai lo usi nel codice di produzione, sei una persona cattiva, cattiva.

Altri suggerimenti

Le uniche modifiche che consiglierei di fare sono la semplificazione del ciclo while:

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

Poiché y e tr sono sinonimi, dovresti utilizzare solo uno di essi.Penso che tr legga meglio di y, quindi ho scelto tr.Inoltre, le stavi chiamando in modo molto diverso, ma questo dovrebbe essere lo stesso effetto e menziona solo le lettere che effettivamente cambi.(Tutti gli altri personaggi venivano trasposti su se stessi. Ciò rende molto più difficile vedere cosa viene effettivamente cambiato.)

Potresti voler rimuovere il open(INPUT,"<dna.txt"); e le corrispondenti righe close(INPUT);, poiché rendono molto più difficile usare il tuo programma nelle pipeline della shell o con diversi file di input.Ma dipende da te, se il file di input sarà sempre dna.txt e mai niente di diverso, va bene.

#!/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

Phew.Il meglio che riesco a trovare, almeno così velocemente.Se sei sicuro che l'input sia sempre in maiuscolo, puoi anche rilasciare il uc salvando altri due caratteri.Oppure, se l'input è sempre lo stesso, puoi assegnarlo subito a $_ invece di leggerlo da qualsiasi luogo.

Immagino di non aver bisogno di dire che questo codice non deve essere utilizzato in ambienti di produzione o altrove se non per puro divertimento.Quando si esegue la programmazione effettiva, la leggibilità vince quasi sempre sulla compattezza.

Alcune altre versioni che ho menzionato nei commenti:

Lettura di% p e del DNA dai file:

#!/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

Dalla shell 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 maggior parte delle cose è già stata evidenziata, soprattutto che la leggibilità è importante.Non proverei a ridurre il programma più di quanto segue.

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";

L'unica cosa "one-liner" che ho aggiunto è il push map grep m//g nel ciclo while.Nota che Perl 5.10 aggiunge l'operatore "definito o" - // - che ti permette di scrivere:

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

Ah okay, l'idioma slurp del file open do local $/ è utile per caricare piccoli file in memoria.Spero che lo trovi un po 'stimolante.:-)

Se scrive i dati delle proteine in un altro file, delimitato da spazi e senza interruzione di riga.Quindi, puoi importare i dati leggendo il file una volta.

#!/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);

Puoi rimuovere la riga di codice " tr / a, c, g, t / A, C, G, T / " perché l'operatore di corrispondenza ha l'opzione per il casoinsensibile (opzione i ).E il ciclo foreach originale può essere ottimizzato come il codice sopra.La variabile $1 qui corrisponde al risultato del modello tra parentesi dell'operazione di corrispondenza /(\w{3})/gi

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top