<div dir="ltr">Madre mía, qué hack. Aplausos. <br></div><div class="gmail_extra"><br><div class="gmail_quote">El 2 de febrero de 2015, 22:42, Salvador Fandiño <span dir="ltr"><<a href="mailto:sfandino@gmail.com" target="_blank">sfandino@gmail.com</a>></span> escribió:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div bgcolor="#FFFFFF" text="#000000"><div><div class="h5">
<div>On 02/02/2015 08:58 PM, Verónica Olmos
González wrote:<br>
</div>
<blockquote type="cite">
<div dir="ltr">
<div>
<div>
<div>
<div>¡Hola a todos!<br>
<br>
Bueno, ante todo, como decía en mi presentación, soy
bastante (muy) novata en Perl, así que es bastante
probable que la esté liando con algo muy básico... pero
me gustaría compartir mi problema con vosotros, por si
alguno supiera darme alguna orientación (aunque sea
simplemente remitirme a alguna página concreta de
documentación).<br>
<br>
</div>
El contexto de mi problema es el siguiente: parto de un
array que contiene secuencias de nucleótidos (o sea,
strings que deben estar formados por "A", "C", "G" o "T").
La cosa es que estos strings pueden contener, cualquiera
de ellos, en determinada posición, el carácter "N", que no
es "válido". Lo que hace el resto de mi programa es hacer
comparaciones dos a dos entre cada elemento del array. Lo
que quiero hacer, y el quid de mi duda: si en "x" posición
de cualquier elemento encuentro una "N", debo borrar esa
"x-ésima" posición en TODOS los elementos del array. Un
ejemplo: si tengo @arr = ("AATN", "AATG", "TATG") debo
quedarme con @arr2 = ("AAT", "AAT", "TAT").<br>
<br>
</div>
Sin enrollarme con más explicaciones, os enseño el código
con mi planteamiento:<br>
<br>
</div>
<blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" class="gmail_quote"><font><span style="font-family:monospace,monospace">@sequences =
("AATGTCAACGAN", "AATGTCAACGNA", "ATTGTCAACGTN",
"ATTGTGATCGTT");</span></font><br>
<font><span style="font-family:monospace,monospace">for ($i
= 0; $i <= scalar(@sequences); $i++) {</span></font><br>
<font><span style="font-family:monospace,monospace"> if
($sequences[$i] =~ "N") {</span></font><br>
<font><span style="font-family:monospace,monospace"></span></font></blockquote>
</div>
<blockquote><font><span style="font-family:monospace,monospace">
# Localizo las "N" y guardo su posición en un array</span></font><br>
<font><span style="font-family:monospace,monospace"></span></font></blockquote>
<div>
<blockquote>
<div><font><span style="font-family:monospace,monospace">
push(@pos,index($sequences[$i], "N"));<br>
}<br>
}<br>
<br>
</span></font></div>
<div><font><span style="font-family:monospace,monospace">#
Elimino posiciones repetidas y ordeno los valores<br>
</span></font></div>
<div><font><span style="font-family:monospace,monospace">my
@pos = do { my %seen; grep { !$seen{$_}++ } @pos };<br>
@pos = sort @pos;<br>
<br>
</span></font></div>
<div><font><span style="font-family:monospace,monospace">#
Mi idea era, mediante expresiones regulares, poner "N"
en todos los elementos de los arrays, en las
posiciones guardadas, para luego eliminarlo todo
evitando "corrimientos" en las posiciones<br>
</span></font></div>
</blockquote>
<div>
<blockquote><font><span style="font-family:monospace,monospace">for ($i = 0;
$i <= scalar(@sequences); $i++) {</span></font><br>
<font><span style="font-family:monospace,monospace">
for ($j = 0; $j <= scalar(@pos); $j++) {</span></font><br>
<font><span style="font-family:monospace,monospace">
substr($sequences[$i],$pos[$j],1) =~ s/\D/N/;</span></font><br>
<font><span style="font-family:monospace,monospace"> }</span></font><br>
<font><span style="font-family:monospace,monospace">}</span></font><br>
<br>
</blockquote>
Ahora bien, en el último bucle se me va todo de madre,
permanece iterando continuamente.<br>
<br>
</div>
<div>La verdad es que seguro que estoy haciendo fatal algo
tontísimo, pero no soy capaz de ver el origen del error, por
lo que agradecería enormemente cualquier tipo de
orientación.<br>
<br>
<br>
</div>
<div>Un saludo,<br>
</div>
<div>Verónica<br>
</div>
<div>
<div>
<div>
<div>
<div><br>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</blockquote>
<br></div></div>
Para esto de la N hay un truco.<br>
<br>
Si te fijas, de todos los caracteres AGCTN solo la N tiene un 1 en
el bit 3 (0x08) asi que puedes detectar donde hay Ns haciendo un OR
de todas las sequencias y luego buscando los caracteres que tienen
ese bit a uno en el resultado.<br>
<br>
A partir de ahi es fácil generar una mascara que al hacer AND con
las secuencias originales ponga a cero las posiciones con N, y luego
solo hay que borrar los ceros:<span class=""><br>
<br>
@sequences = ("AATGTCAACGAN",<br>
"AATGTCAACGNA",<br>
"ATTGTCAACGTN",<br>
"ATTGTGATCGTT");<br>
<br></span>
my $mask = '';<br>
$mask |= $_ for @sequences;<br>
$mask =~ s/(.)/(ord($1) & 8) ? "\0" : "\xFF"/ge;<br>
<br>
for (@sequences) {<br>
$_ &= $mask;<br>
tr/\0//;<br>
}<br>
<br>
use Data::Dumper;<br>
print Dumper \@sequences;<br>
<br>
<br>
</div>
<br>_______________________________________________<br>
llista dels Barcelona-pm<br>
<a href="mailto:Barcelona-pm@pm.org">Barcelona-pm@pm.org</a><br>
<a href="http://mail.pm.org/mailman/listinfo/barcelona-pm" target="_blank">http://mail.pm.org/mailman/listinfo/barcelona-pm</a><br>
BCN Perl Mongers: <a href="http://barcelona.pm.org" target="_blank">http://barcelona.pm.org</a><br></blockquote></div><br><br clear="all"><br>-- <br><div class="gmail_signature">JJ</div>
</div>