Bienvenida a los foros de Perl en Español, entropia.
El problema está en las expresiones regulares, que no saben que deben buscar en múltiplos de tres posiciones.
Supongamos que estamos en la línea 19 donde el programa debe buscar por los codones que comienzan por timina.
Como la expresión regular solo sabe que debe buscar algo que comience por 'T' seguido de dos caracteres cualesquiera, empezará a buscar desde el principio de la cadena, y ya en la segunda posición encontrará la primera.
Nosotros sabemos que no es correcto: esa 'T' no está en múltiplo de tres.
Tienes varias soluciones:
1- Dividir la secuencia en codones (separarlos de tres en tres), y analizar cada codón por separado. Con la función substr() es fácil
2- Seguir con el mismo código que hasta ahora, pero antes de hacer el incremento del contador, comprobar que la posición es, efectivamente, múltiplo de tres. Algo así:
Using perl Syntax Highlighting
my $pos = pos($secuencia); # pos() nos devuelve la siguiente posición del patrón encontrado
$res3++ if not $pos % 3; # calculamos el resto de la división entera de la posición, entre 3
Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
Lo que hacemos, dentro de cada while(), es ver la posición donde terminó el patrón que buscamos. Si esa posición es múltiplo de 3, entonces estamos seguros que lo que buscamos también comienza en una posición múltiplo de 3, ya que los patrones todos tienen 3 caracteres de ancho. Y por lo tanto, son posiciones de inicio de codón y es correcta la búsqueda
3- Modificar la expresión regular para que tenga en cuenta la posición de inicio de búsqueda de los patrones:
Using perl Syntax Highlighting
while ($secuencia =~ /\G(?:...)*?A../g) {
$res1++;
}
Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
\G es la posición en la que quedó la última coincidencia -suponemos que fue un codón anterior o el inicio de la propia secuencia-. A partir de ahí buscamos por 0 o más conjuntos de tres letras (
(?:...)*), y seguidos por nuestro patrón de codón. Si la expresión regular encuentra el codón, incrementa el contador, y repite el proceso.
4- Hacer un bucle for() por la longitud de la secuencia, saltando de tres en tres, y leyendo solo una letra. Según sea esa letra, incrementamos su contador correspondiente (más cómodo si usamos un
hash)
5- ...
Por estos foros hay ejemplos de todos ellos. Busca por la palabra "codones".
A propósito, no necesitas un quinto patrón para saber cuántos codones hay... te basta con dividir la longitud de la secuencia entre 3:
print length($secuencia) / 3;