Palíndromos de Watson-Crick

31

Problema

Crie uma função que possa determinar se uma sequência de DNA arbitrária é ou não um palíndromo Watson-Crick. A função pegará uma sequência de DNA e produzirá um valor verdadeiro se a sequência for um palíndromo Watson-Crick e um valor falso, se não for. (Verdadeiro e Falso também podem ser representados como 1 e 0, respectivamente.)

A cadeia de DNA pode estar em maiúsculas ou minúsculas, dependendo da sua preferência.

Além disso, a cadeia de DNA não estará vazia.

Explicação

Uma cadeia de DNA é um palíndromo de Watson-Crick quando o complemento de seu reverso é igual a si próprio.

Dada uma sequência de DNA, primeiro inverta-a e depois complemente cada caractere de acordo com as bases de DNA (A ↔ T e C ↔ G). Se a cadeia original for igual à cadeia de reversão complementada, será um palíndromo de Watson-Crick.

Para mais, veja esta pergunta . É um desafio diferente, onde você deve encontrar a substring mais longa de uma cadeia de DNA em que essa substring é um palíndromo de Watson-Crick.

Objetivo

Este é o código-golfe e o código mais curto vence.

Casos de teste

O formato é <input> = <output>.

ATCGCGAT = true
AGT = false
GTGACGTCAC = true
GCAGTGA = false
GCGC = true
AACTGCGTTTAC = false
ACTG = false
milhas
fonte
Relacionado.
Martin Ender
3
Alguém deve escrever um programa no DNA # que também seja um palíndromo de Watson-Crick. : D (pode não ser possível)
mbomb007
Ou, se preferir, "uma palavra é um palíndromo Watson-Crick se tiver a ordem 2 no grupo livre em 2 geradores" (ou em n geradores!).
precisa saber é
(Eu acho que tecnicamente dessa "ordem no máximo 2.")
wchargin
1
@AndrasDeak De acordo com o livro de Watsons, Franklin era aparentemente um espinho do lado deles. Ela se recusou repetidamente a entregar raios-x mostrando a hélice (pelo que me lembro), porque se recusou a acreditar. Vale a pena ler se você estiver interessado na descoberta de qualquer forma.
Obsidian Phoenix

Respostas:

27

05AB1E , 10 7 bytes

Código:

Â'š×‡Q

Explicação:

Para verificar se uma string é um palíndromo, precisamos apenas verificar a entrada com a entrada, com atswapped e cgswapped e depois revertê-la. Então é isso que vamos fazer. Nós pressionamos a entrada e a entrada foi revertida usando Â(bifurcado). Agora vem uma parte complicada. 'š×é a versão compactada para creating. Se a revertermos, você poderá ver por que está no código:

CreATinG
|  ||  |
GniTAerC

Isso será usado para transliterar a entrada reversa. A transliteração é feita com . Depois disso, apenas verificamos se a entrada e a entrada transliterada são Qiguais e imprimimos esse valor. Então é assim que a pilha se parece com a entrada actg:

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

O que também pode ser visto com o sinalizador de depuração ( tente aqui ).

Usa a codificação CP-1252 . Experimente online! .

Adnan
fonte
4
Muito, er, criativo ...
Toby Speight
2
Esse idioma tem alguns recursos muito legais
milhas
18

Geléia , 9 bytes

O%8µ+U5ḍP

Experimente online! ou verifique todos os casos de teste .

Como 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.
Dennis
fonte
4
Eu acho que o Python está bem perto de competir com esta resposta! Compare os primeiros nove bytes de minha resposta: lambda s:. Essa é quase a solução completa!
orlp
Espere, a parte "Como funciona" não explica realmente como funciona ... Por que resíduos de 8 e somas de 5 ?? Onde as cartas são complementadas?
precisa saber é o seguinte
@ZeroOne eu esclareço essa parte.
Dennis
Uau! Isso é muito inteligente. :) Obrigado!
precisa saber é o seguinte
12

Python 2, 56 45 44 bytes

lambda s:s==s[::-1].translate("_T_GA__C"*32)
orlp
fonte
lambda s:s==s[::-1].translate("TCG_A"*99)trabalha em Python 3
Alex Varga
8

Perl, 27 bytes

Inclui +2 para -lp

Dê entrada no STDIN, imprima 1 ou nada:

dnapalin.pl <<< ATCGCGAT

dnapalin.pl:

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

Substitua $_=por $_+=para obter em 0vez de vazio para o caso falso

Ton Hospel
fonte
7

Retina , 34 33 bytes

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

Experimente online!(Ligeiramente modificado para executar todos os casos de teste de uma vez.)

Explicação

$
;$_

Duplique a entrada correspondendo ao final da sequência e inserindo a ;seguida por toda a entrada.

T`ACGT`Ro`;.+

Combine apenas a segunda metade da entrada ;.+e execute a substituição de pares por uma transliteração. Quanto ao conjunto de destino Ro: oreferencia o outro conjunto, que oé substituído por ACGT. Mas Rinverte esse conjunto, então os dois conjuntos são realmente:

ACGT
TGCA

Se a entrada for um palíndromo de DNA, agora teremos a entrada seguida pelo seu reverso (separado por ;).

+`(.);\1
;

Repetidamente ( +) remova um par de caracteres idênticos ao redor do ;. Isso continuará até que apenas o ;seja deixado ou até que os dois caracteres ao redor ;não sejam mais idênticos, o que significaria que as seqüências não são o inverso uma da outra.

^;

Verifique se o primeiro caractere é ;e imprima 0ou de 1acordo.

Martin Ender
fonte
6

JavaScript (ES6), 59 bytes

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

O melhor que pude fazer sem usar o Regexp foi de 62 bytes:

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

Ruby, 35

Tentei de outras maneiras, mas a maneira óbvia foi a mais curta:

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

no programa de teste

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'] 
Level River St
fonte
2
->s{s.==s.reverse.tr'ACGT','TGCA'}é um byte menor
Mitch Schwartz
@MitchSchwartz uau, isso funciona, mas eu não tenho ideia do que é isso primeiro .. O código parece mais correto para mim sem ele, mas é necessário para fazê-lo funcionar. Está documentado em algum lugar?
Level River St
Tem certeza de que não quer descobrir por conta própria?
Mitch Schwartz
@MitchSchwartz hahaha eu já tentei. Acho os requisitos do ruby ​​para espaços em branco muito idiossincráticos. Requisitos estranhos para períodos são outra questão. Eu tenho várias teorias, mas todas elas podem estar erradas. Suspeito que possa ter algo a ver com o tratamento ==como um método do que como um operador, mas a busca por símbolos é impossível.
Level River St
Você suspeitou corretamente. :) É apenas uma simples chamada de método antiga.
Mitch Schwartz
5

Haskell, 48 45 bytes

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

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

Uma versão não-pointfree é

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..."

Edit: @Mathias Dolidon salvou 3 bytes. Obrigado!

nimi
fonte
Funciona com cycle "TCG_A" também. :)
Mathias Dolidon
4

Retina, 52 bytes

^G(.*)C$
$1
^A(.*)T$
$1
^T(.*)A$
$1
}`^C(.*)G$
$1
^$
CalculatorFeline
fonte
4

Julia, 47 38 bytes

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

Esta é uma função anônima que aceita uma Charmatriz e retorna um booleano. Para chamá-lo, atribua-o a uma variável.

Isso usa o algoritmo de Dennis, que é mais curto que a solução ingênua. Obtemos o restante de cada ponto de código dividido por 8, adicionamos isso a ele próprio, invertemos, obtemos os restantes da divisão por 5 e verificamos se todos são 0. O último passo é realizado usando a versão infix de issubset, que lança os dois argumentos para Setantes de verificar. Isso significa que [0,0,0]é declarado um subconjunto de 0, desde Set([0,0,0]) == Set(0). Isso é mais curto que uma verificação explícita contra 0.

Experimente online!

Economizou 9 bytes graças a Dennis!

Alex A.
fonte
4

Jolf, 15 bytes

Tente!

=~A_iγ"AGCT"_γi

Explicação:

   _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
incha
fonte
3

Jolf, 16 bytes

Try it here!

pe+i~Aiγ"GATC"_γ

Explanation

pe+i~Aiγ"GATC"_γ
    ~Aiγ"GATC"_γ  perform DNA transformation
  +i              i + (^)
pe                is a palindrome
Conor O'Brien
fonte
3

Actually, 19 bytes

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

This uses Dennis's algorithm.

Try it online!

Explanation:

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
Mego
fonte
3

Oracle SQL 11.2, 68 bytes

SELECT DECODE(TRANSLATE(REVERSE(:1),'ATCG','TAGC'),:1,1,0)FROM DUAL; 
Jeto
fonte
2
With SQL like that, I'm confident you must have written reports for some of my projects before...
corsiKa
3

Julia 0.4, 22 bytes

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

The string contains the control characters EOT (4) and NAK (21). Input must be in form of a character array.

This approach XORs the characters of the input with the corresponding characters in the reversed input. For valid pairings, this results in the characters EOT or NAK. Testing for inclusion in the string of those characters produces the desired Boolean.

Try it online!

Dennis
fonte
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 saved by Dennis. Additional 2 bytes saved by adapting for lowercase input: constants 37 and 21 are revised to 5 and 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;}

Saved one byte: Eliminated parenthesis by taking the product of the two ASCII codes mod 37. The valid pairs evaluate to 21. Assumes uppercase input.

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;}

Uses the fact that ASCII codes of the valid pairs sum to 138 or 149. When taken mod 11, these are the only pairs that sum to 6. Assumes uppercase input.

ungolfed in test program

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"));
} 
Level River St
fonte
1
r,e;f(char*s){for(r=0,e=strlen(s)+1;*s;s++)r|=*s*s[e-=2]%37^21;return!r;} saves a couple of bytes.
Dennis
@Dennis thanks, I really wasn't in the mood for modifying pointers, but it squeezed a byte out! I should have seen != > ^ myself. I reduced another 2 by changing to lowercase input: both magic numbers are now single digit.
Level River St
3

Factor, 72 bytes

Unfortunately regex can't help me here.

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

Reverse, lookup table, compare equal.

cat
fonte
Uau, isso é muito espaço em branco !!! Tudo isso é necessário? Além disso, um link para a página inicial do idioma seria útil.
Level River St
@LevelRiverSt Infelizmente, tudo é necessário. Vou adicionar um link ao cabeçalho.
gato
3

Bash + coreutils, 43 32 bytes

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

Testes:

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
Toby Speight
fonte
3

J - 21 bytes

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

Baseado no 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

Explicação

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
milhas
fonte
3

Labirinto , 42 bytes

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

Termina com um erro de divisão por zero (mensagem de erro em STDERR).

Experimente online!

O layout parece realmente ineficiente, mas agora não estou vendo uma maneira de jogar golfe.

Explicação

Esta solução é baseada no truque aritmético de Dennis: pegue todos os módulos de códigos de caracteres 8, adicione um par de ambas as extremidades e verifique se é divisível por 5.

Primário labirinto:

  • O labirinto possui duas pilhas de números inteiros de precisão arbitrária, principal e auxiliar (iliária), que são inicialmente preenchidos com uma quantidade infinita (implícita) de zeros.
  • O código fonte se assemelha a um labirinto, onde o ponteiro de instrução (IP) segue os corredores quando pode (mesmo nos cantos). O código começa no primeiro caractere válido em ordem de leitura, ou seja, no canto superior esquerdo neste caso. Quando o IP chega a qualquer forma de junção (ou seja, várias células adjacentes além daquela de onde veio), ele selecionará uma direção com base no topo da pilha principal. As regras básicas são: vire à esquerda quando negativo, continue em frente quando zero, vire à direita quando positivo. E quando uma dessas opções não for possível porque existe uma parede, o IP seguirá na direção oposta. O IP também muda ao atingir becos sem saída.
  • Os dígitos são processados ​​multiplicando a parte superior da pilha principal por 10 e adicionando o dígito.

O código começa com um pequeno loop 2x2 no sentido horário, que lê todos os módulos de entrada 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.

Agora ;descarta o -1. Entramos em outro loop no sentido horário que move o topo da pilha principal (ou seja, o último caractere) para baixo:

"   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.

Agora há um pequeno bit linear:

{{  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.

O IP está agora em uma junção que atua como uma ramificação para testar a divisibilidade em 5. Se o resultado do módulo for diferente de zero, sabemos que a entrada não é um palíndromo de Watson-Crick e viramos para o leste:

_   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.

Caso contrário, precisamos continuar verificando o restante da entrada, para que o IP continue indo para o sul. Ele {puxa a parte inferior da entrada restante. Se esgotarmos a entrada, será um 0(na parte inferior do aux ) e o IP continuará se movendo para o sul:

)   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.

Caso contrário, há mais caracteres na sequência a serem verificados. O IP vira para oeste e passa para o próximo loop 2x2 (no sentido horário), que consiste basicamente de 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.

Após esse loop, temos a entrada na pilha principal novamente, exceto seu primeiro e último caractere e com um zero no topo. Ele ;descarta 0e =troca as partes superiores das pilhas, mas isso é apenas para cancelar o primeiro =no loop, porque agora estamos inserindo o loop em um local diferente. Enxague e repita.

Martin Ender
fonte
3

sed, 67 61 bytes

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

(67 bytes)

Teste

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

Saída

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

Usando expressões regulares estendidas, a contagem de bytes pode ser reduzida para 61.

sed -r 'G;H;:1;s/(.)(.*\n)/\2\1/;t1;y/ACGT/TGCA/;G;s/^(.*)\1$/1/;t;c0'
PM 2Ring
fonte
Se você pode fazê-lo em 61 bytes, essa é sua pontuação - não há nada contra a NFA ou a regexp completa neste desafio em particular. Alguns desafios desaprovam o regex por completo, mas geralmente apenas o regex-golf não permite expressões não regulares .
gato
3

C #, 65 bytes

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

O .NET possui alguns nomes de método de estrutura bastante longos às vezes, o que não é necessariamente o melhor framework de golfe de código. Nesse caso, os nomes dos métodos da estrutura compõem 33 caracteres em 90. :)

Com base no truque de módulo de outro lugar no segmento:

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

Agora pesa 67 caracteres, dos quais 13 são nomes de métodos.

Outra otimização menor para cortar dois caracteres impressionantes:

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

Portanto, 65 dos quais 13 são nomes de estrutura.

Edit: Omitir parte do "clichê" limitado da solução e adicionar algumas condições nos deixa com a expressão

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

O que fornece 0 se e somente se a sequência s for uma resposta válida. Como o gato aponta, "bool F (string s) =>" é realmente substituível por "s =>" se estiver claro no código que a expressão é a Func<string,bool>, ie. mapeia uma string para um booleano.

Robhol
fonte
1
Bem-vindo ao PPCG, boa primeira resposta! : D
cat
@cat Obrigado por isso! :)
robhol
1
Eu realmente não conheço C #, mas se este é um lambda, você pode deixar de fora seu tipo e atribuí-lo, pois as funções anônimas são boas, desde que sejam capazes de atribuir .
gato
1
Além disso, você não pode fazer em !s.Zip...vez de s.Zip...==0? (Ou você não pode !inverter em C #?) Mesmo se não puder negá-lo, você pode deixar de fora qualquer tipo de inversão e declarar em sua resposta que isso retorna <essa coisa> por falsidade e <outro determinista, coisa claramente discernível> para a verdade.
gato
1
@cat: Você está certo sobre abandonar o tipo. Eu pensei que o código tinha que ser diretamente executável, mas fazer suposições simples sobre entrada e saída facilita um pouco. A outra coisa não funcionará, no entanto - com razão, na minha opinião, uma vez que uma operação booleana não tem uma maneira lógica (de matiz) para aplicar a um número. Atribuir 0 e 1 os valores de falso e verdadeiro é, afinal, apenas convenção.
robhol
2

REXX 37

s='ATCGCGAT';say s=translate(reverse(s),'ATCG','TAGC')
aja
fonte
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 teste

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
syntonicC
fonte
strsplit(x,"")[[1]] is 3 bytes shorter than unlist(strsplit(x,"")) and, here, is equivalent since x is always a single string of character.
plannapus
2

Octave, 52 bytes

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

Following Denis's trick ... take the ASCII values mod 8, flip and add together; if every sum is a multiple of five, you're golden.

dcsohl
fonte
That one whitespace is significant? That's... odd.
cat
Also, you can leave out the f= assignment; unnamed functions are okay.
cat
1

Clojure/ClojureScript, 49 chars

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

Works on strings. If the requirements are loosened to allow lists, I can take off the (list* ) and save 7 chars.

MattPutnam
fonte
1

R, 70 bytes

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

Usage:

> 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
plannapus
fonte
1

C, 71 bytes

Requires ASCII codes for the relevant characters, but accepts uppercase, lowercase or mixed-case input.

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

This code maintains two pointers, s and p, traversing the string in opposite directions. At each step, we compare the corresponding characters, setting b true if they don't match. The matching is based on XOR of the character values:

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

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

We can see in the above table that we want to record success for xx10x and failure for anything else, so we XOR with 00100 (four) and mask with 00110 (six) to get zero for AT or CG and non-zero otherwise. Finally, we return true if all the pairs accumulated a zero result in b, false otherwise.

Test program:

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

𝔼𝕊𝕄𝕚𝕟, 13 chars / 17 bytes

⟮ïĪ`ACGT”⟯ᴙ≔Ⅰ

Try it here (Firefox only).

Explanation

Transliterate input from ACGT to TGCA and check if the resulting string is a palindrome.

Mama Fun Roll
fonte