Palíndromos de Watson-Crick


31

Problema

Cree una función que pueda determinar si una cadena de ADN arbitraria es un palíndromo de Watson-Crick. La función tomará una cadena de ADN y generará un valor verdadero si la cadena es un palíndromo de Watson-Crick y un valor falso si no lo es. (Verdadero y falso también se puede representar como 1 y 0, respectivamente).

La cadena de ADN puede estar en mayúsculas o en minúsculas, según su preferencia.

Además, la cadena de ADN no estará vacía.

Explicación

Una cadena de ADN es un palíndromo de Watson-Crick cuando el complemento de su reverso es igual a sí mismo.

Dada una cadena de ADN, primero inviértala y luego complemente cada carácter de acuerdo con las bases de ADN (A ↔ T y C ↔ G). Si la cadena original es igual a la cadena inversa complementada, es un palíndromo de Watson-Crick.

Para más información, vea esta pregunta . Es un desafío diferente donde debes encontrar la subcadena más larga de una cadena de ADN donde esa subcadena es un palíndromo de Watson-Crick.

Gol

Este es el código de golf y gana el código más corto.

Casos de prueba

El formato es <input> = <output>.

ATCGCGAT = true
AGT = false
GTGACGTCAC = true
GCAGTGA = false
GCGC = true
AACTGCGTTTAC = false
ACTG = false


3
Alguien debería escribir un programa en DNA # que también sea un palíndromo de Watson-Crick. : D (podría no ser posible)
mbomb007

O, si lo desea, "una palabra es un palíndromo de Watson-Crick si tiene orden 2 en el grupo libre en 2 generadores" (¡o en n generadores!).
wchargin

(Supongo que técnicamente eso es "ordenar como máximo 2")
wchargin

1
@AndrasDeak Según el libro de Watsons, Franklin aparentemente era principalmente una espina en su costado. En repetidas ocasiones se negó a entregar rayos X que mostraban la hélice (según recuerdo), porque se negó a creerlo. Vale la pena leer si está interesado en el descubrimiento de todos modos.
Obsidian Phoenix

Respuestas:


27

05AB1E , 10 7 bytes

Código:

Â'š×‡Q

Explicación:

Para verificar si una cadena es un palíndromo, solo necesitamos verificar la entrada con la entrada, atintercambiada e cgintercambiada y luego invertirla. Entonces eso es lo que vamos a hacer. Empujamos la entrada y la entrada se invierte usando Â(bifurcar). Ahora viene una parte difícil. 'š×es la versión comprimida para creating. Si lo revertimos, puede ver por qué está en el código:

CreATinG
|  ||  |
GniTAerC

Esto se usará para transliterar la entrada invertida. La transliteración se hace con . Después de eso, simplemente verificamos si la entrada y la entrada transliterada son e Qe imprimimos ese valor. Así es como se ve la pila para la entrada actg:

          # ["actg", "gtca"]
 'š×       # ["actg", "gtca", "creating"]
    Â      # ["actg", "gtca", "creating", "gnitaerc"]
     ‡     # ["actg", "cagt"]
      Q    # [0]

Que también se puede ver con el indicador de depuración ( Pruébelo aquí ).

Utiliza la codificación CP-1252 . Pruébalo en línea! .


44
Muy, er, creativo ...
Toby Speight

2
Este lenguaje tiene algunas características muy interesantes
millas del

18

Jalea , 9 bytes

O%8µ+U5ḍP

Pruébalo en línea! o verificar todos los casos de prueba .

Cómo funciona

O%8µ+U5ḍP  Main link. Argument: S (string)

O          Compute the code points of all characters.
 %8        Compute the residues of division by 8.
           This maps 'ACGT' to [1, 3, 7, 4].
   µ       Begin a new, monadic link. Argument: A (array of residues)
    +U     Add A and A reversed.
      5ḍ   Test the sums for divisibility by 5.
           Of the sums of all pairs of integers in [1, 3, 7, 4], only 1 + 4 = 5
           and 3 + 7 = 10 are divisible by 5, thus identifying the proper pairings.
        P  Take the product of the resulting Booleans.

44
¡Creo que Python está muy cerca de competir con esta respuesta! Comparar los nueve primeros bytes de mi respuesta: lambda s:. ¡Esa es casi la solución completa!
orlp

Espera, la parte "Cómo funciona" realmente no explica cómo funciona ... ¿Por qué residuos de 8 y sumas de 5? ¿Dónde se complementan las letras?
ZeroOne

@ZeroOne He aclarado esa parte.
Dennis

¡Oh wow! Eso es muy inteligente. :) ¡Gracias!
ZeroOne

12

Python 2, 56 45 44 bytes

lambda s:s==s[::-1].translate("_T_GA__C"*32)

lambda s:s==s[::-1].translate("TCG_A"*99)funciona en Python 3
Alex Varga

8

Perl, 27 bytes

Incluye +2 para -lp

Dé entrada en STDIN, imprime 1 o nada:

dnapalin.pl <<< ATCGCGAT

dnapalin.pl:

#!/usr/bin/perl -lp
$_=y/ATCG/TAGC/r=~reverse

Reemplace $_=por $_+=para obtener en 0lugar de vacío para el caso falso



7

Retina , 34 33 bytes

$
;$_
T`ACGT`Ro`;.+
+`(.);\1
;
^;

Pruébalo en línea! (Ligeramente modificado para ejecutar todos los casos de prueba a la vez).

Explicación

$
;$_

Duplique la entrada haciendo coincidir el final de la cadena e insertando un ;seguido por la entrada completa.

T`ACGT`Ro`;.+

Haga coincidir solo la segunda mitad de la entrada ;.+y realice la sustitución de pares con una transliteración. En cuanto al conjunto de destino Ro: hace oreferencia al otro conjunto, que ose reemplaza con ACGT. Pero Rinvierte este conjunto, por lo que los dos conjuntos son en realidad:

ACGT
TGCA

Si la entrada es un palíndromo de ADN, ahora tendremos la entrada seguida de su reverso (separados por ;).

+`(.);\1
;

Repetidamente ( +) elimina un par de caracteres idénticos alrededor del ;. Esto continuará hasta que solo ;quede o hasta que los dos caracteres que lo rodean ;ya no sean idénticos, lo que significaría que las cadenas no son opuestas entre sí.

^;

Compruebe si el primer carácter es ;e imprima 0o en 1consecuencia.


6

JavaScript (ES6), 59 bytes

f=s=>!s||/^(A.*T|C.*G|G.*C|T.*A)$/.test(s)&f(s.slice(1,-1))

Lo mejor que pude hacer sin usar Regexp fue 62 bytes:

f=s=>!s||parseInt(s[0]+s.slice(-1),33)%32%7<1&f(s.slice(1,-1))

5

Ruby, 35

Intenté otras formas, pero la forma obvia fue la más corta:

->s{s.tr('ACGT','TGCA').reverse==s}

en programa de prueba

f=->s{s.tr('ACGT','TGCA').reverse==s}

puts f['ATCGCGAT']
puts f['AGT']
puts f['GTGACGTCAC']
puts f['GCAGTGA']
puts f['GCGC']
puts f['AACTGCGTTTAC'] 

2
->s{s.==s.reverse.tr'ACGT','TGCA'}es un byte más corto
Mitch Schwartz

@ MitchSchwartz wow, eso funciona, pero no tengo idea de para qué .sirve eso primero . El código me parece más correcto sin él, pero es necesario para que se ejecute. ¿Está documentado en alguna parte?
Level River St

¿Estás seguro de que no quieres resolverlo por tu cuenta?
Mitch Schwartz

@MitchSchwartz jajaja Ya lo intenté. Los requisitos de ruby ​​para espacios en blanco me parecen muy idiosincrásicos. Los requisitos extraños para los períodos son otra cuestión. Tengo varias teorías, pero todas pueden estar equivocadas. Sospecho que puede tener algo que ver con el tratamiento ==como un método en lugar de un operador, pero la búsqueda por símbolos es imposible.
Level River St

Sospechaste correctamente. :) Es una simple llamada al método antiguo.
Mitch Schwartz

5

Haskell, 48 45 bytes

(==)=<<reverse.map((cycle"TCG_A"!!).fromEnum)

Ejemplo de uso: (==)=<<reverse.map((cycle"_T_GA__C"!!).fromEnum) $ "ATCGCGAT"-> True.

Una versión sin puntos es

f x = reverse (map h x) == x           -- map h to x, reverse and compare to x
h c = cycle "TCG_A" !! fromEnum c      -- take the ascii-value of c and take the
                                       -- char at this position of string
                                       -- "TCG_ATCG_ATCG_ATCG_A..."

Editar: @Mathias Dolidon guardó 3 bytes. ¡Gracias!


Funciona con cycle "TCG_A" también. :)
Mathias Dolidon


4

Julia, 47 38 bytes

s->((x=map(Int,s)%8)+reverse(x))%50

Esta es una función anónima que acepta una Charmatriz y devuelve un valor booleano. Para llamarlo, asígnelo a una variable.

Esto utiliza el algoritmo de Dennis, que es más corto que la solución ingenua. Obtenemos el resto de cada punto de código dividido por 8, lo sumamos a sí mismo invertido, obtenemos los restos de la división por 5 y verificamos si todos son 0. El último paso se logra utilizando la versión infija de issubset, que arroja ambos argumentos a Setantes de verificar. Esto significa que [0,0,0]se declara un subconjunto de 0, desde Set([0,0,0]) == Set(0). Esto es más corto que una verificación explícita contra 0.

Pruébalo en línea!

¡Guardado 9 bytes gracias a Dennis!


4

Jolf, 15 bytes

¡Intentalo!

=~A_iγ"AGCT"_γi

Explicación:

   _i            Reverse the input
 ~A_iγ"AGCT"_γ   DNA swap the reversed input
=~A_iγ"AGCT"_γi  Check if the new string is the same as the original input


3

En realidad, 19 bytes

O`8@%`M;RZ`5@Σ%Y`Mπ

Esto usa el algoritmo de Dennis .

Pruébalo en línea!

Explicación:

O`8@%`M;RZ`5@Σ%Y`Mπ
O                    push an array containing the Unicode code points of the input
 `8@%`M              modulo each code point by 8
       ;RZ           zip with reverse
          `5@Σ%Y`M   test sum for divisibility by 5
                  π  product

3

Oracle SQL 11.2, 68 bytes

SELECT DECODE(TRANSLATE(REVERSE(:1),'ATCG','TAGC'),:1,1,0)FROM DUAL; 

2
Con SQL como ese, estoy seguro de que debe haber escrito informes para algunos de mis proyectos antes ...
corsiKa

3

Julia 0.4, 22 bytes

s->s$reverse(s)⊆""

La cadena contiene los caracteres de control EOT (4) y NAK (21). La entrada debe estar en forma de una matriz de caracteres.

Este enfoque XORs los caracteres de la entrada con los caracteres correspondientes en la entrada invertida. Para emparejamientos válidos, esto da como resultado los caracteres EOT o NAK. La prueba de inclusión en la cadena de esos caracteres produce el Booleano deseado.

Pruébalo en línea!


3

C, 71

r,e;f(char*s){for(r=0,e=strlen(s)+1;*s;s++)r|=*s*s[e-=2]%5^2;return!r;}

2 bytes guardados por Dennis. Se guardan 2 bytes adicionales al adaptarse para la entrada en minúscula: constantes 37y 21se revisan en 5y 2.

C, 75

i,j;f(char*s){for(i=j=0;s[i];i++)j|=s[i]*s[strlen(s)-i-1]%37!=21;return!j;}

Se guardó un byte: se eliminó el paréntesis tomando el producto de los dos códigos ASCII mod 37. Los pares válidos se evalúan en 21. Asume una entrada en mayúscula.

C, 76

i,j;f(char*s){for(i=j=0;s[i];i++)j|=(s[i]+s[strlen(s)-i-1])%11!=6;return!j;}

Utiliza el hecho de que los códigos ASCII de los pares válidos suman 138 o 149. Cuando se toman mod 11, estos son los únicos pares que suman 6. Asume una entrada en mayúsculas.

sin golf en el programa de prueba

i,j;

f(char *s){
   for(i=j=0;s[i];i++)                  //initialize i and j to 0; iterate i through the string
     j|=(s[i]+s[strlen(s)-i-1])%11!=6;  //add characters at i from each end of string, take result mod 11. If not 6, set j to 1
return!j;}                              //return not j (true if mismatch NOT detected.)

main(){
  printf("%d\n", f("ATCGCGAT"));
  printf("%d\n", f("AGT"));
  printf("%d\n", f("GTGACGTCAC"));
  printf("%d\n", f("GCAGTGA"));
  printf("%d\n", f("GCGC"));
  printf("%d\n", f("AACTGCGTTTAC"));
} 

1
r,e;f(char*s){for(r=0,e=strlen(s)+1;*s;s++)r|=*s*s[e-=2]%37^21;return!r;}Guarda un par de bytes.
Dennis

@Dennis gracias, realmente no estaba de humor para modificar punteros, ¡pero me sacó un byte! Debería haber visto !=> ^a mí mismo. Reduje otros 2 cambiando a minúsculas: ambos números mágicos ahora son de un solo dígito.
Level River St el

3

Factor , 72 bytes

Desafortunadamente, la expresión regular no puede ayudarme aquí.

[ dup reverse [ { { 67 71 } { 65 84 } { 71 67 } { 84 65 } } at ] map = ]

Invertir, tabla de búsqueda, comparar igual.


¡Guau, eso es mucho espacio en blanco! ¿Es todo necesario? Además, un enlace a la página de inicio del idioma sería útil.
Level River St el

@LevelRiverSt Desafortunadamente, todo es necesario. Agregaré un enlace al encabezado.
gato

3

Bash + coreutils, 43 32 bytes

[ `tr ATCG TAGC<<<$1|rev` = $1 ]

Pruebas:

for i in ATCGCGAT AGT GTGACGTCAC GCAGTGA GCGC AACTGCGTTTAC; do ./78410.sh $i && echo $i = true || echo $i = false; done
ATCGCGAT = true
AGT = false
GTGACGTCAC = true
GCAGTGA = false
GCGC = true
AACTGCGTTTAC = false

3

J - 21 bytes

0=[:+/5|[:(+|.)8|3&u:

Basado en el método de Dennis

Uso

   f =: 0=[:+/5|[:(+|.)8|3&u:
   f 'ATCGCGAT'
1
   f 'AGT'
0
   f 'GTGACGTCAC'
1
   f 'GCAGTGA'
0
   f 'GCGC'
1
   f 'AACTGCGTTTAC'
0
   f 'ACTG'
0

Explicación

0=[:+/5|[:(+|.)8|3&u:
                 3&u:    - Convert from char to int
               8|        - Residues from division by 8 for each
            |.           - Reverse the list
           +             - Add from the list and its reverse element-wise
        [:               - Cap, compose function
      5|                 - Residues from division by 5 for each
    +/                   - Fold right using addition to create a sum
  [:                     - Cap, compose function
0=                       - Test the sum for equality to zero

3

Laberinto , 42 bytes

_8
,%
;
"}{{+_5
"=    %_!
 = """{
 ;"{" )!

Termina con un error de división por cero (mensaje de error en STDERR).

Pruébalo en línea!

El diseño se siente realmente ineficiente, pero no estoy viendo una forma de jugar golf en este momento.

Explicación

Esta solución se basa en el truco aritmético de Dennis: tome todos los módulos de caracteres 8, agregue un par de ambos extremos y asegúrese de que sea divisible por 5.

Imprimación de laberinto:

  • Labyrinth tiene dos pilas de enteros de precisión arbitraria, main y aux (iliary), que inicialmente se rellenan con una cantidad infinita (implícita) de ceros.
  • El código fuente se asemeja a un laberinto, donde el puntero de instrucción (IP) sigue los corredores cuando puede (incluso alrededor de las esquinas). El código comienza en el primer carácter válido en el orden de lectura, es decir, en la esquina superior izquierda en este caso. Cuando la IP llega a cualquier forma de unión (es decir, varias celdas adyacentes además de la que proviene), elegirá una dirección basada en la parte superior de la pila principal. Las reglas básicas son: gire a la izquierda cuando sea negativo, siga adelante cuando sea cero, gire a la derecha cuando sea positivo. Y cuando uno de estos no es posible porque hay un muro, entonces la IP tomará la dirección opuesta. La IP también se da vuelta cuando llega a callejones sin salida.
  • Los dígitos se procesan multiplicando la parte superior de la pila principal por 10 y luego agregando el dígito.

El código comienza con un pequeño bucle de 2x2 en sentido horario, que lee todas las entradas del módulo 8:

_   Push a 0.
8   Turn into 8.
%   Modulo. The last three commands do nothing on the first iteration
    and will take the last character code modulo 8 on further iterations.
,   Read a character from STDIN or -1 at EOF. At EOF we will leave loop.

Ahora ;descarta el -1. Entramos en otro bucle en el sentido de las agujas del reloj que mueve la parte superior de la pila principal (es decir, el último carácter) hacia abajo:

"   No-op, does nothing.
}   Move top of the stack over to aux. If it was at the bottom of the stack
    this will expose a zero underneath and we leave the loop.
=   Swap top of main with top of aux. The effect of the last two commands
    together is to move the second-to-top stack element from main to aux.
"   No-op.

Ahora hay un bit lineal corto:

{{  Pull two characters from aux to main, i.e. the first and last (remaining)
    characters of the input (mod 8).
+   Add them.
_5  Push 5.
%   Modulo.

La IP está ahora en una unión que actúa como una rama para probar la divisibilidad entre 5. Si el resultado del módulo no es cero, sabemos que la entrada no es un palíndromo de Watson-Crick y giramos hacia el este:

_   Push 0.
!   Print it. The IP hits a dead end and turns around.
_   Push 0.
%   Try to take modulo, but division by zero fails and the program terminates.

De lo contrario, debemos seguir verificando el resto de la entrada, para que la IP siga yendo hacia el sur. El {tira sobre la parte inferior de la entrada restante. Si hemos agotado la entrada, esta será una 0(desde la parte inferior de aux ), y la IP continúa moviéndose hacia el sur:

)   Increment 0 to 1.
!   Print it. The IP hits a dead end and turns around.
)   Increment 0 to 1.
{   Pull a zero over from aux, IP keeps moving north.
%   Try to take modulo, but division by zero fails and the program terminates.

De lo contrario, hay más caracteres en la cadena para verificar. La IP gira hacia el oeste y pasa al siguiente ciclo 2x2 (en el sentido de las agujas del reloj) que consiste en gran medida en no-ops:

"   No-op.
"   No-op.
{   Pull one value over from aux. If it's the bottom of aux, this will be
    zero and the IP will leave the loop eastward.
"   No-op.

Después de este bucle, tenemos la entrada en la pila principal nuevamente, excepto por su primer y último carácter y con un cero en la parte superior. Los ;descartes de la 0y luego =intercambia la parte superior de las pilas, pero esto es sólo para cancelar la primera =en el circuito, porque estamos entrando ahora en el bucle en una ubicación diferente. Enjuague y repita.


3

sed, 67 61 bytes

G;H;:1;s/\(.\)\(.*\n\)/\2\1/;t1;y/ACGT/TGCA/;G;s/^\(.*\)\1$/1/;t;c0

(67 bytes)

Prueba

for line in ATCGCGAT AGT GTGACGTCAC GCAGTGA GCGC AACTGCGTTTAC ACTG
do echo -n "$line "
    sed 'G;H;:1;s/\(.\)\(.*\n\)/\2\1/;t1;y/ACGT/TGCA/;G;s/^\(.*\)\1$/1/;t;c0' <<<"$line"
done

Salida

ATCGCGAT 1
AGT 0
GTGACGTCAC 1
GCAGTGA 0
GCGC 1
AACTGCGTTTAC 0
ACTG 0

Mediante el uso de expresiones regulares extendidas, el recuento de bytes se puede reducir a 61.

sed -r 'G;H;:1;s/(.)(.*\n)/\2\1/;t1;y/ACGT/TGCA/;G;s/^(.*)\1$/1/;t;c0'

Si puede hacerlo en 61 bytes, entonces ese es su puntaje: no hay nada en contra de NFA o regexp completo en este desafío en particular. Algunos desafíos no permiten la expresión regular en su totalidad, pero por lo general solo la expresión regular de golf no permitirá expresiones no regulares .
gato

3

C #, 65 bytes

bool F(string s)=>s.SequenceEqual(s.Reverse().Select(x=>"GACT"[("GACT".IndexOf(x)+2)%4]));

.NET a veces tiene algunos nombres de métodos de framework bastante largos, lo que no necesariamente es el mejor framework de golf de código. En este caso, los nombres de los métodos del marco constituyen 33 caracteres de 90. :)

Según el truco del módulo de otra parte del hilo:

bool F(string s)=>s.Zip(s.Reverse(),(a,b)=>a%8+b%8).All(x=>x%5==0);

Ahora pesa 67 caracteres de los cuales 13 son nombres de métodos.

Otra optimización menor para eliminar 2 caracteres:

bool F(string s)=>s.Zip(s.Reverse(),(a,b)=>(a%8+b%8)%5).Sum()<1;

Entonces, 65 de los cuales 13 son nombres de marco.

Editar: Omitir algunas de las "repeticiones" limitadas de la solución y agregar un par de condiciones nos deja con la expresión

s.Zip(s.Reverse(),(a,b)=>(a%8+b%8)%5).Sum()

Lo que da 0 si y solo si la cadena s es una respuesta válida. Como señala cat, "bool F (string s) =>" en realidad es reemplazable por "s =>" si de lo contrario está claro en el código que la expresión es a Func<string,bool>, es decir. asigna una cadena a un booleano.


1
Bienvenido a PPCG, buena primera respuesta! : D
gato

@cat Gracias por eso! :)
robhol

1
Realmente no sé C #, pero si se trata de una lambda, puede omitir su tipo y asignarlo, ya que las funciones anónimas están bien siempre que se puedan asignar .
gato

1
Además, ¿no puedes hacer en !s.Zip...lugar de s.Zip...==0? (¿O no puede !inscribirse en C #?) Incluso si no puede negarlo booleanamente, puede omitir cualquier tipo de inversión y declarar en su respuesta que esto devuelve <esta cosa> por falsedad y <esta otra determinación, cosa claramente discernible> para la verdad.
gato

1
@cat: Tienes razón al soltar el tipo. Pensé que el código tenía que ser directamente ejecutable, pero hacer suposiciones simples sobre la entrada y la salida lo hace un poco más fácil. Sin embargo, lo otro no funcionará, con razón, en mi opinión, ya que una operación booleana no tiene una forma lógica (matiz) para aplicar a un número. Asignar 0 y 1 los valores de falso y verdadero es, después de todo, solo convención.
robhol

2

REXX 37

s='ATCGCGAT';say s=translate(reverse(s),'ATCG','TAGC')

2

R, 101 bytes

g=function(x){y=unlist(strsplit(x,""));all(sapply(rev(y),switch,"C"="G","G"="C","A"="T","T"="A")==y)}

Casos de prueba

g("ATCGCGAT")
[1] TRUE
g("AGT")
[1] FALSE
g("GTGACGTCAC")
[1] TRUE
g("GCAGTGA")
[1] FALSE
g("GCGC")
[1] TRUE
g("AACTGCGTTTAC")
[1] FALSE
g("ACTG")
[1] FALSE

strsplit(x,"")[[1]]es 3 bytes más corto que unlist(strsplit(x,""))y, aquí, es equivalente ya xque siempre es una sola cadena de caracteres.
plannapus

2

Octava, 52 bytes

f=@(s) prod(mod((i=mod(toascii(s),8))+flip(i),5)==0)

Siguiendo el truco de Denis ... tome los valores ASCII mod 8, voltee y sume; Si cada suma es un múltiplo de cinco, eres dorado.


Que uno espacio en blanco es significativo? Eso es extraño.
gato

Además, puede omitir la f=tarea; funciones sin nombre están bien.
gato

1

Clojure / ClojureScript, 49 caracteres

#(=(list* %)(map(zipmap"ATCG""TAGC")(reverse %)))

Funciona en cuerdas. Si los requisitos se aflojan para permitir listas, puedo quitar (list* )y guardar 7 caracteres.


1

R, 70 bytes

f=function(x)all(chartr("GCTA","CGAT",y<-strsplit(x,"")[[1]])==rev(y))

Uso:

> f=function(x)all(chartr("GCTA","CGAT",y<-strsplit(x,"")[[1]])==rev(y))
> f("GTGACGTCAC")
[1] TRUE
> f("AACTGCGTTTAC")
[1] FALSE
> f("AGT")
[1] FALSE
> f("ATCGCGAT")
[1] TRUE

1

C, 71 bytes

Requiere códigos ASCII para los caracteres relevantes, pero acepta entradas en mayúsculas, minúsculas o mayúsculas y minúsculas.

f(char*s){char*p=s+strlen(s),b=0;for(;*s;b&=6)b|=*--p^*s++^4;return!b;}

Este código mantiene dos punteros sy patraviesa la cadena en direcciones opuestas. En cada paso, comparamos los caracteres correspondientes, estableciendo bverdadero si no coinciden. La coincidencia se basa en XOR de los valores de los caracteres:

'A' ^ 'T' = 10101
'C' ^ 'G' = 00100

'C' ^ 'T' = 10111
'G' ^ 'A' = 00110
'A' ^ 'C' = 00010
'T' ^ 'G' = 10011
 x  ^  x  = 00000

Podemos ver en la tabla anterior que queremos registrar el éxito xx10xy el fracaso de cualquier otra cosa, por lo que XOR con 00100(cuatro) y enmascarar con 00110(seis) para obtener cero para ATo CGno cero de lo contrario. Finalmente, devolvemos verdadero si todos los pares acumularon un resultado cero b, falso de lo contrario.

Programa de prueba:

#include <stdio.h>
int main(int argc, char **argv)
{
    while (*++argv)
        printf("%s = %s\n", *argv, f(*argv)?"true":"false");
}

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.