Página 1 de 1

Posiciones de un array

NotaPublicado: 2016-11-16 08:55 @413
por angelluigi
Buenas.

Me están pidiendo que diga las posiciones en un array que presenten el valor mínimo. Ando un poco liado con esto. Si alguien me puede ayudar...

Muchas gracias.

Re: Posiciones de un array

NotaPublicado: 2016-11-16 18:09 @798
por explorer
Bienvenido a los foros de Perl en Español, angelluigi.

Es un problema algo complejo, ya que hay que recordar las posiciones que vamos encontrando, con el valor mínimo.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/env perl
  2. use v5.20;
  3.  
  4. my @array = map { 10 + int rand 90 } 1 .. 100;
  5.  
  6. #say "@array";
  7.  
  8. my @posiciones_minimo;
  9. my $valor_minimo = 10E10;
  10.  
  11. while(my($i, $valor) = each @array) {
  12.     if ($valor_minimo > $valor) {
  13.         $valor_minimo = $valor;
  14.         @posiciones_minimo = ();
  15.     }
  16.  
  17.     if ($valor_minimo == $valor) {
  18.         push @posiciones_minimo, $i;
  19.     }
  20. }
  21.  
  22. say "Mínimo encontrado: $valor_minimo";
  23. say "Posiciones en las que se encuentra: @posiciones_minimo";
  24.  
  25. __END__
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
Una posible ejecución:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
$./kk.pl
Mínimo encontrado: 10
Posiciones en las que se encuentra: 43 59 90
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Bueno, al final, no es tan complejo... con apenas 5 líneas principales lo resolvemos.

La explicación del funcionamiento te lo dejo como deberes para casa.

Naturalmente, se puede hacer de otras formas.

Re: Posiciones de un array

NotaPublicado: 2016-11-16 19:22 @849
por angelluigi
Muchas gracias, acabo de empezar el master en bioinformática y todavía ando un poco verde.

Lo he probado y la solución concuerda perfectamente. Más o menos creo que lo he entendido. Lo que pasa es que no he visto el bucle while() ... each(), que has usado. Yo he sacado el valor mínimo con un foreach y pensaba sacar la posición, o sea, el índice, con un bucle for.

Te dejo el código para ver si puedes sacarlo con un bucle for, gracias y perdón por las molestias.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my @skew = ();
  2.  
  3. $contador_G = 0;
  4. $contador_C = 0;
  5. $min_skew   = 0;
  6.  
  7. $secuencia = "CCTATCGGTGGATTAGCATGTCCCTGTACGTTTCGCCGCGAACTAGTTCACACGGCTTGATGGCAAATGGTTTTTCCGGCGACCGTAATCGTCCACCGAG";
  8.  
  9. for ( my $i = 0; $i < ( length $secuencia ); $i++ ) {
  10.     $base = substr( $secuencia, $i, 1 );
  11.     if    ( $base =~ /C/ ) { $contador_C = $contador_C + 1; }
  12.     elsif ( $base =~ /G/ ) { $contador_G = $contador_G + 1; }
  13.     my $diferencia_GC = $contador_G - $contador_C;
  14.  
  15.     push @skew, $diferencia_GC;
  16.     foreach (@skew) {
  17.         if ( $_ < $min_skew ) { $min_skew = $_; }
  18.  
  19.     }
  20.  
  21. }
  22.  
  23. $skew = join( '', (@skew) );
  24. print $skew, "\n\n\n";
  25.  
  26. $valor_minimo = $min_skew;
  27.  
  28. my @posiciones_minimo;
  29.  
  30. while ( my ( $i, $valor ) = each @skew ) {
  31.     if ( $valor_minimo > $valor ) {
  32.         $valor_minimo      = $valor;
  33.         @posiciones_minimo = ();
  34.     }
  35.  
  36.     if ( $valor_minimo == $valor ) {
  37.         push @posiciones_minimo, $i;
  38.     }
  39. }
  40.  
  41. print @posiciones_minimo;
  42.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Re: Posiciones de un array

NotaPublicado: 2016-11-17 18:28 @811
por explorer
No necesitas hacer dos bucles, ya que con uno te vale, ya que estás recorriendo toda la secuencia:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/env perl
  2.  
  3. my @skew;
  4.  
  5. my $contador_G;
  6. my $contador_C;
  7. my $min_skew   = length $secuencia;     # hay que inicializarlo a un valor alto o máximo
  8. my @posiciones_minimo;
  9.  
  10. my $secuencia = "CCTATCGGTGGATTAGCATGTCCCTGTACGTTTCGCCGCGAACTAGTTCACACGGCTTGATGGCAAATGGTTTTTCCGGCGACCGTAATCGTCCACCGAG";
  11.  
  12. for ( my $i = 0; $i < length $secuencia; $i++ ) {
  13.  
  14.     $base = substr $secuencia, $i, 1;
  15.  
  16.     if    ( $base eq 'C' ) { $contador_C++; }
  17.     elsif ( $base eq 'G' ) { $contador_G++; }
  18.  
  19.     my $diferencia_GC = $contador_G - $contador_C;
  20.  
  21.     push @skew, $diferencia_GC;
  22.  
  23.     if ($min_skew > $diferencia_GC) {
  24.         $min_skew = $diferencia_GC;     # tenemos un nuevo mínimo
  25.         @posiciones_minimo = ();        # reiniciamos el almacén de posiciones
  26.     }
  27.  
  28.     if ( $diferencia_GC == $min_skew ) {        # si es un mínimo,
  29.         push @posiciones_minimo, $i;            # recordamos su posición
  30.     }
  31. }
  32.  
  33. print join('|', @skew), "\n\n";         # -1|-2|-2|-2|-2|-3|-2|-1|-1|0|1|1|1|1|1|2|1|1|1|2|2|1|0|-1|-1|0|0|0|-1|0|0|0|0|-1|0|-1|-2|-1|-2|-1|-1|-1|-2|-2|-2|-1|-1|-1|-2|-2|-3|-3|-4|-3|-2|-3|-3|-3|-2|-2|-2|-1|0|-1|-1|-1|-1|-1|0|1|1|1|1|1|1|0|-1|0|1|0|1|1|0|-1|0|0|0|0|0|-1|0|0|-1|-2|-2|-3|-4|-3|-3|-2
  34.  
  35. print "Valor mínimo: $min_skew\n";     # Valor mínimo: -4
  36.  
  37. print "@posiciones_minimo\n";           # 52 96
  38.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Re: Posiciones de un array

NotaPublicado: 2016-11-17 18:39 @818
por angelluigi
Muchas gracias, lo acabo de probar y va perfecto.

Re: Posiciones de un array

NotaPublicado: 2016-11-19 20:45 @906
por explorer
Esta es otra versión, más corta, usando otra técnica.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/env perl
  2. use v5.14;
  3.  
  4. my $secuencia = 'CCTATCGGTGGATTAGCATGTCCCTGTACGTTTCGCCGCGAACTAGTTCACACGGCTTGATGGCAAATGGTTTTTCCGGCGACCGTAATCGTCCACCGAG';
  5.  
  6. my %visto;
  7. my $contador = 0;
  8.  
  9. while ($secuencia =~ m/(?<letras_repetidas>(?|(?<letra>C)+|G+))/g) {
  10.     my $largo = length $+{letras_repetidas};
  11.  
  12.     $contador += $+{letra} eq 'C' ? -$largo : $largo;
  13.  
  14.     push @{$visto{ $contador }}, pos($secuencia);       # posiciones basadas en 0, pero terminan más allá,
  15.                                                         # así que es como si estuvieran basadas en 1
  16. }
  17.  
  18. #use Data::Dumper;
  19. #say Dumper \%visto;
  20.  
  21. my $minimo = (sort {$a <=> $b} keys %visto)[0];
  22.  
  23. say "Mínimo [$minimo] en las posiciones [@{$visto{$minimo}}]";         # Mínimo [-4] en las posiciones [53 97]
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

La idea se basa en localizar los grupos de letras 'C' y 'G', contando las veces que se repiten, y la posición en la que se encuentran.

Re: Posiciones de un array

NotaPublicado: 2017-01-08 14:10 @632
por angelluigi
Buenas, otra vez.

Repasando otra vez el ejercicio me ha venido una duda, en el penúltimo script que me mandaste.

if ($min_skew > $diferencia_GC) {
$min_skew = $diferencia_GC; # tenemos un nuevo mínimo
@posiciones_minimo = (); # reiniciamos el almacén de posiciones
}

No logro entender lo que haces con @posiciones_minimo

Muchas gracias.

Re: Posiciones de un array

NotaPublicado: 2017-01-08 16:57 @748
por explorer
El objetivo es saber en qué posiciones encontramos el mínimo (valor más pequeño) de la diferencia entre 'C' y 'G'.

Entonces, en el if() nos preguntamos si hemos encontrado un valor más pequeño que el que tenemos hasta ahora ($min_skew). Si la $diferencia_GC es menor que $min_skew, resulta que hemos encontrado un mínimo más pequeño, así que todas las @posiciones_minimo que teníamos antes, ya no nos valen (no nos interesan), y por eso reiniciamos el array.

En la línea siguiente hay otro if(), que se cumplirá en el caso de que hayamos encontrado un mínimo más pequeño: en la línea 24 igualamos el valor de las variables, así que la condición de la línea 28 se cumple, por lo que la 29 se ejecuta siempre que encontremos un nuevo mínimo más pequeño. Y la labor de la línea 29 es almacenar la posición de ese nuevo mínimo (de ese, y de todos los demás que sigan iguales a $min_skew).