Página 1 de 1

Generar todas las combinaciones de nucleótidos

NotaPublicado: 2011-12-25 01:44 @114
por informatic777
Estoy haciendo un programa en Perl para contar secuencias de longitud n en un archivo de ADN.

Me gustaría saber cómo puedo hacer una subrutina que devuelva todas las posibles combinaciones de palabras de longitud n, es decir, las 4^n permutaciones. Llevo varios días intentándolo y solo lo consigo para secuencias de n=2.

¿Podrías indicarme una forma sencilla de cómo hacerlo, puesto que llevo poco programando? Quizá alguna subrutina que mute continuamente o algo así...

Re: Generar todas las combinaciones de nucleótidos

NotaPublicado: 2011-12-25 12:04 @544
por explorer
Bienvenido a los foros de Perl en español, informatic777.

Ese tema ya lo hemos tratado aquí, en otros hilos. Con la ayuda de Algorithm::Combinatorics se puede solucionar fácilmente. O mediante generación de código, como en este ejemplo.

Si nos pones el código que tienes, quizás te podemos decir qué le falta.

Re: Generar todas las combinaciones de nucleótidos

NotaPublicado: 2011-12-26 04:43 @238
por informatic777
No me aclaro mucho con los ejemplos.

Con este código he conseguido todas las combinaciones para palabras de longitud 2, pero no me funciona para el resto de forma general (de 2 a 8) ya que me da menos combinaciones. A lo mejor debería poner algún bucle anidado más, pero no me funciona.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. use strict;
  2. use warnings;
  3. my $w = <STDIN>;
  4. chomp $w;                              #$w es el valor de la longitud de la palabra(2 a 8)
  5. my $a = 'A' x $w;
  6. my $c = 'C' x $w;
  7. my $g = 'G' x $w;
  8. my $t = 'T' x $w;
  9. print "t=$a\n";
  10. my @posiblespalabras = rad( $a, $c, $g, $t, $w );
  11. my @pal = cog(@posiblespalabras);
  12. print "las posibles combinaciones son:@pal\n";
  13.  
  14. sub rad {
  15.     my ( $a, $c, $g, $t, $w ) = @_;
  16.     my @posibles = ();
  17.     my @bases    = qw( A C G T);
  18.     print "t=$t\n";
  19.     for ( my $i = 1; $i < $w; $i++ ) {
  20.         foreach my $b (@bases) {
  21.             substr( $a, $i, 1, $b );
  22.             substr( $c, $i, 1, $b );
  23.             substr( $g, $i, 1, $b );
  24.             substr( $t, $i, 1, $b );
  25.             push( @posibles, $a, $c, $g, $t );
  26.         }
  27.     }
  28.     return @posibles;
  29. }
  30.  
  31. sub cog {
  32.     my (@array) = @_;
  33.     my %hash = ();
  34.     foreach (@array) {
  35.         $hash{$_}++;
  36.     }
  37.     return sort keys %hash;
  38. }
  39.  
Coloreado en 0.004 segundos, usando GeSHi 1.0.8.4

Re: Generar todas las combinaciones de nucleótidos

NotaPublicado: 2011-12-26 10:21 @473
por explorer
Sí, el código no funciona bien...

Para n=4, esta es la salida:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
Introduzca longitud: 4
t=AAAA
t=TTTT
AAAA    CACC    GAGG    TATT
ACAA    CCCC    GCGG    TCTT
AGAA    CGCC    GGGG    TGTT
ATAA    CTCC    GTGG    TTTT
ATAA    CTAC    GTAG    TTAT
ATCA    CTCC    GTCG    TTCT
ATGA    CTGC    GTGG    TTGT
ATTA    CTTC    GTTG    TTTT
ATTA    CTTA    GTTA    TTTA
ATTC    CTTC    GTTC    TTTC
ATTG    CTTG    GTTG    TTTG
ATTT    CTTT    GTTT    TTTT
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4
Observa la primera columna: a partir del momento en que se coloca una 'T' en la segunda posición, permanece así para el resto de combinaciones. Y hay combinaciones que se repiten (como 'ATAA') y otras muchas que faltan (como 'ACCC'). El número de combinaciones debería ser 4^4 = 256.

No es tan simple como hacer un bucle que meta cuatro letras a las combinaciones que ya tenemos. Hay que hacer una nueva lista de combinaciones por cada combinación de la letra precedente.

Una forma obvia es la que se comenta en uno de los enlaces: hacer tantos bucles anidados como sea 'n'. O de forma recursiva (una función que se llame a sí misma).

Esta es la forma cómoda de hacerlo (para n=4):
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use 5.010;
  3. use Algorithm::Combinatorics 'variations_with_repetition';
  4.  
  5. my @x = variations_with_repetition([qw(A T C G)], 4);
  6.  
  7. for my $x (@x) {    # cada elemento del array es una ref. a otro array, que contiene los elementos por separado
  8.     say @$x;        # desreferenciamos y sacamos el array. El say(), por defecto, sacará los elementos unidos
  9. }
  10.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4