Codegolf - Палиндромы Уотсона-Крика

  • Автор темы 771313019
  • Обновлено
  • 22, Oct 2024
  • #1

Проблема

Создайте функцию, которая может определить, является ли произвольная строка ДНК палиндромом Уотсона-Крика. Функция возьмет строку ДНК и выведет истинное значение, если строка является палиндромом Уотсона-Крика, и ложное значение, если это не так. (Истина и Ложь также могут быть представлены как 1 и 0 соответственно.)

Строка ДНК может быть написана как прописными, так и строчными буквами, в зависимости от ваших предпочтений.

Кроме того, строка ДНК не будет пустой.

Объяснение

Строка ДНК является палиндромом Уотсона-Крика, если дополнение ее обратной строки равно самой себе.

Дана строка ДНК, сначала переверните ее, а затем дополните каждый символ согласно основаниям ДНК (A ↔ T и C ↔ G). Если исходная строка равна дополняемой обратной строке, это палиндром Уотсона-Крика.

Подробнее см. здесь вопрос. Это другая задача: вам нужно найти самую длинную подстроку строки ДНК, где эта подстрока является палиндромом Уотсона-Крика.

Цель

Это код-гольф, и побеждает самый короткий код.

Тестовые случаи

Формат:

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

<input> = <output>

#код-гольф #строка #палиндром #биоинформатика

771313019


Рег
18 Feb, 2014

Тем
64

Постов
175

Баллов
515
  • 26, Oct 2024
  • #2

05AB1E, 10 7 байт

Код:

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 TGCA 

Объяснение:

Чтобы проверить, является ли строка палиндромом, нам просто нужно сверить входные данные с входными, с помощью ACGT swapped and ⟮ïĪ`ACGT”⟯ᴙ≔Ⅰ поменял местами, а потом перевернул. Вот что мы собираемся сделать. Мы нажимаем на ввод, и ввод меняется на противоположный, используя #include <stdio.h> int main(int argc, char **argv) { while (*++argv) printf("%s = %s\n", *argv, f(*argv)?"true":"false"); } (bifurcate). Now comes a tricky part. b это сжатая версия для CG . If we reverse it, you can see why it's in the code:

AT

Это будет использоваться для транслитерации обратного ввода. Транслитерация осуществляется с помощью 00110 . After that, we just check if the input and the transliterated input are e 00100 ual и распечатайте это значение. Вот как выглядит стек для ввода xx10x :

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

Это также можно увидеть с помощью флага отладки (попробуйте здесь).

Использование CP-1252 кодировка. Попробуйте онлайн!.

 

Pash


Рег
03 Nov, 2004

Тем
82

Постов
210

Баллов
640
  • 26, Oct 2024
  • #3

Желе, 9 байты

b

Попробуйте онлайн! или проверить все тестовые случаи.

Как это работает

p ||answer||

Python 2, 56 45 44 байта

s ||answer||

Перл, 27 байт

Включает +2 за f(char*s){char*p=s+strlen(s),b=0;for(;*s;b&=6)b|=*--p^*s++^4;return!b;}

Введите данные в STDIN, выведет 1 или ничего:

> 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

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

(list* )

Заменять #(=(list* %)(map(zipmap"ATCG""TAGC")(reverse %))) by f=@(s) prod(mod((i=mod(toascii(s),8))+flip(i),5)==0) получить 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 instead of empty for the false case

 

Zloikak


Рег
10 Sep, 2007

Тем
56

Постов
178

Баллов
488
  • 26, Oct 2024
  • #5

сетчатка, 34 33 байта

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

Попробуйте онлайн! (Немного изменено для одновременного запуска всех тестовых случаев.)

Объяснение

Func<string,bool>

Дублируйте ввод, сопоставив конец строки и вставив s.Zip(s.Reverse(),(a,b)=>(a%8+b%8)%5).Sum() followed by the entire input.

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

Сопоставьте только вторую половину ввода с bool F(string s)=>s.Zip(s.Reverse(),(a,b)=>a%8+b%8).All(x=>x%5==0); and perform the substitution of pairs with a transliteration. As for the target set bool F(string s)=>s.SequenceEqual(s.Reverse().Select(x=>"GACT"[("GACT".IndexOf(x)+2)%4])); : sed -r 'G;H;:1;s/(.)(.*\n)/\2\1/;t1;y/ACGT/TGCA/;G;s/^(.*)\1$/1/;t;c0' references the другой набор, то есть ATCGCGAT 1 AGT 0 GTGACGTCAC 1 GCAGTGA 0 GCGC 1 AACTGCGTTTAC 0 ACTG 0 is replaced with 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 . Но G;H;:1;s/\(.\)\(.*\n\)/\2\1/;t1;y/ACGT/TGCA/;G;s/^\(.*\)\1$/1/;t;c0 reverses this set, so the two sets are actually:

=

Если входные данные представляют собой палиндром ДНК, теперь у нас будет ввод, за которым следует его обратный вариант (разделенный знаком = ).

0

Неоднократно ( ; ) remove a pair of identical characters around the " 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. . Это будет продолжаться либо до тех пор, пока не останется только ) 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. is left or until the two characters around the 0 больше не идентичны, а это означает, что строки не являются обратными друг другу.

{

Проверьте, является ли первый символ _ 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. and print {{ 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. или " 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. accordingly.

 

Lubov_sher


Рег
02 Feb, 2012

Тем
82

Постов
175

Баллов
635
  • 26, Oct 2024
  • #6

JavaScript (ES6), 59 байт

-1

Лучшее, что я мог сделать без использования Regexp, — это 62 байта:

; ||answer||

Руби, 35 лет

Я пробовал другие способы, но очевидный путь был самым коротким:

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

в тестовой программе

5 ||answer||

Хаскелл, 48 45 байт

8

Пример использования: _8 ,% ; "}{{+_5 "= %_! = """{ ;"{" )! -> 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 .

Небесточечная версия

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

Редактировать: @Mathias Dolidon сохранил 3 байта. Спасибо!

 

Svkminsk


Рег
25 Oct, 2008

Тем
79

Постов
159

Баллов
584
  • 26, Oct 2024
  • #7

Ретина, 52 байта

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

Юля, 47 38 байт

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

Это анонимная функция, которая принимает [ `tr ATCG TAGC<<<$1|rev` = $1 ] array and returns a boolean. To call it, assign it to a variable.

При этом используется алгоритм Денниса, который короче наивного решения. Мы получаем остаток каждой кодовой точки, разделенный на 8, добавляем его в обратном порядке, получаем остатки от деления на 5 и проверяем, все ли они равны 0. Последний шаг выполняется с помощью [ dup reverse [ { { 67 71 } { 65 84 } { 71 67 } { 84 65 } } at ] map = ] , the infix version of 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])!=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")); } , который приводит оба аргумента к i,j;f(char*s){for(i=j=0;s[i];i++)j|=(s[i]+s[strlen(s)-i-1])!=6;return!j;} before checking. This means that i,j;f(char*s){for(i=j=0;s[i];i++)j|=s[i]*s[strlen(s)-i-1]%37!=21;return!j;} объявлен подмножеством 2 , since 5 . Это короче, чем явная проверка на 0.

Попробуйте онлайн!

Сэкономлено 9 байт благодаря Денису!

 

Egregor82


Рег
27 May, 2008

Тем
58

Постов
192

Баллов
512
  • 26, Oct 2024
  • #8

Йольф, 15 байт

Попробуйте!

21

Объяснение:

37 ||answer||

Йольф, 16 байт

Попробуйте здесь!

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

Объяснение

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

На самом деле 19 байт

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

Это использует Алгоритм Денниса.

Попробуйте онлайн!

Объяснение:

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 ||answer||

Oracle SQL 11.2, 68 байт

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

Джулия 0.4, 22 байта

pe+i~Aiγ"GATC"_γ ~Aiγ"GATC"_γ perform DNA transformation +i i + (^) pe is a palindrome

Строка содержит управляющие символы EOT (4) и NAK (21). Ввод должен быть в виде массива символов.

Этот подход выполняет XOR символов ввода с соответствующими символами в обратном вводе. Для действительных пар это приводит к появлению символов EOT или NAK. Проверка включения в строку этих символов дает желаемое логическое значение.

Попробуйте онлайн!

 

M_pumpkin


Рег
10 Oct, 2008

Тем
69

Постов
212

Баллов
567
  • 26, Oct 2024
  • #9

С, 71

pe+i~Aiγ"GATC"_γ

2 байта сохранены Деннисом. Дополнительные 2 байта сохранены за счет адаптации ввода в нижнем регистре: константы. _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 and =~A_iγ"AGCT"_γi пересмотрены на Set([0,0,0]) == Set(0) and 0 .

С, 75

[0,0,0]

Сэкономлен один байт: круглые скобки устранены путем произведения двух кодов ASCII по модулю 37. Допустимые пары оцениваются как 21. Предполагается ввод в верхнем регистре.

С, 76

Set

Использует тот факт, что ASCII-коды допустимых пар в сумме дают 138 или 149. Если взять по модулю 11, это единственные пары, сумма которых равна 6. Предполагается ввод в верхнем регистре.

без гольфа в тестовой программе

issubset ||answer||

Фактор, 72 байта

К сожалению, регулярное выражение не может мне здесь помочь.

Обратный, таблица поиска, сравнение равное.

 

Brorusro


Рег
29 Nov, 2019

Тем
70

Постов
203

Баллов
553
  • 26, Oct 2024
  • #10

Bash + coreutils, 43 32 байта

Char

Тесты:

s->((x=map(Int,s)%8)+reverse(x))%5⊆0 ||answer||

Дж – 21 байт

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

По методу Денниса

Использование

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

Объяснение

True ||answer||

Лабиринт, 42 байта

(==)=<<reverse.map((cycle"_T_GA__C"!!).fromEnum) $ "ATCGCGAT"

Завершается ошибкой деления на ноль (сообщение об ошибке в STDERR).

Попробуйте онлайн!

Планировка кажется действительно неэффективной, но я просто не вижу способа использовать ее прямо сейчас.

Объяснение

Это решение основано на арифметическом трюке Денниса: взять все коды символов по модулю. (==)=<<reverse.map((cycle"TCG_A"!!).fromEnum) , add a pair from both ends and make sure it's divisible by 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'] .

Лабиринтный праймер:

  • В Лабиринте есть два стека целых чисел произвольной точности: основной и вспомогательный(илиарий), которые изначально заполнены (неявным) бесконечным количеством нулей.
  • Исходный код напоминает лабиринт, где указатель инструкций (IP) следует по коридорам, когда это возможно (даже за углами). Код начинается с первого допустимого символа в порядке чтения, то есть в данном случае с верхнего левого угла. Когда IP-адрес достигает любой формы соединения (т. е. нескольких соседних ячеек в дополнение к той, из которой он пришел), он выберет направление, основанное на вершине основного стека. Основные правила таковы: поверните налево при отрицательном значении, продолжайте идти вперед при нулевом значении, поверните направо при положительном. А когда что-то из этого невозможно из-за стены, тогда IP пойдет в противоположном направлении. IP также разворачивается при попадании в тупик.
  • Цифры обрабатываются путем умножения вершины основного стека на 10 и последующего сложения цифр.

Код начинается с небольшого цикла 2x2 по часовой стрелке, который считывает все входные данные по модулю 8:

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

Сейчас f=s=>!s||parseInt(s[0]+s.slice(-1),33)%32%7<1&f(s.slice(1,-1)) discards the f=s=>!s||/^(A.*T|C.*G|G.*C|T.*A)$/.test(s)&f(s.slice(1,-1)) . Мы вводим еще один цикл по часовой стрелке, который перемещает верхнюю часть основного стека (т.е. последний символ) вниз:

1

Теперь есть короткий линейный бит:

0

IP теперь находится на стыке, который действует как ветвь для проверки делимости на 5. Если результат по модулю не равен нулю, мы знаем, что входные данные не являются палиндромом Уотсона-Крика, и поворачиваем на восток:

;

В противном случае нам нужно продолжать проверять остальную часть входных данных, чтобы IP продолжал идти на юг. ^; pulls over the bottom of the remaining input. If we've exhausted the input, then this will be a ; (из нижней части вспомогательный), а IP продолжает двигаться на юг:

;

В противном случае в строке, которую необходимо проверить, имеется больше символов. IP поворачивает на запад и переходит в следующий (по часовой стрелке) цикл 2x2, который в основном состоит из бездействующих операций:

;

После этого цикла мы снова получаем входные данные в основной стек, за исключением первого и последнего символа и нуля сверху. + discards the +`(.);\1 ; а потом ; swaps the tops of the stacks, but this is just to cancel the first ACGT TGCA в цикле, потому что теперь мы входим в цикл в другом месте. Промойте и повторите.

 

Copland


Рег
23 Feb, 2012

Тем
62

Постов
189

Баллов
519
  • 26, Oct 2024
  • #11

сед, 67 61 байт

R

(67 байт)

Тест

ACGT

Выход

o

Используя расширенные регулярные выражения, количество байтов можно уменьшить до 61.

o ||answer||

С#, 65 байт

Ro

.NET иногда имеет довольно длинные имена методов платформы, что не обязательно делает ее лучшей средой для игры в гольф. В данном случае имена методов фреймворка составляют 33 символа из 90. :)

На основе трюка с модулем из другого места ветки:

;.+

Теперь весит 67 символов, из которых 13 — имена методов.

Еще одна небольшая оптимизация, позволяющая убрать целых два символа:

T`ACGT`Ro`;.+

Итак, 65 из которых 13 — имена фреймворков.

Редактировать:

;

Если исключить из решения некоторые ограниченные «шаблоны» и добавить пару условий, мы получим выражение Что дает 0 тогда и только тогда, когда строка s является допустимым ответом. Как указывает кот, «bool F(string s)=>» на самом деле можно заменить на «s=>». $ ;$_ , ie. maps a string to a boolean.

если

в противном случае из кода ясно, что выражение является 37

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

 

Laman88


Рег
08 Apr, 2020

Тем
87

Постов
198

Баллов
673
  • 26, Oct 2024
  • #12
qQ_XQ"ACGT

РЕКСС

0 ||answer||

Р, 101 байт

$_+=

Тестовые случаи

Октава, 52 байта

Следуя трюку Дениса... возьмите значения ASCII по модулю 8, переверните и сложите; если каждая сумма кратна пяти, ты золотой.

$_=

 

Lastoctober


Рег
01 Dec, 2019

Тем
70

Постов
195

Баллов
565
  • 26, Oct 2024
  • #13
#!/usr/bin/perl -lp $_=y/ATCG/TAGC/r=~reverse and save 7 chars.

Clojure/ClojureScript, 49 символов

Работает на струнах. Если требования будут ослаблены и включены списки разрешенных, я могу снять

dnapalin.pl

 

Nubsaybot


Рег
09 Mar, 2007

Тем
58

Постов
200

Баллов
500
  • 26, Oct 2024
  • #14

dnapalin.pl <<< ATCGCGAT ||answer||

Р, 70 байт

Использование:

-lp

С, 71 байт lambda s:s==s[::-1].translate("_T_GA__C"*32) and 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. Требуются коды ASCII для соответствующих символов, но допускается ввод в верхнем, нижнем или смешанном регистре. O%8µ+U5ḍP true if they don't match. The matching is based on XOR of the character values:

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

Этот код поддерживает два указателя: actg and failure for anything else, so we XOR with Q , перемещая строку в противоположных направлениях. На каждом шаге мы сравниваем соответствующие символы, устанавливая (six) to get zero for CreATinG | || | GniTAerC В приведенной выше таблице видно, что мы хотим зафиксировать успех для creating and non-zero otherwise. Finally, we return true if all the pairs accumulated a zero result in 'š× (четыре) и маска с

или

 ||answer||

, в противном случае ложно.

cg

Тестовая программа:

???????????????, 13 символов/17 байт

Попробуйте здесь (только Firefox). at to Â'š×‡Q Объяснение

 

Finrigin


Рег
06 Feb, 2014

Тем
71

Постов
205

Баллов
610
Тем
403,760
Комментарии
400,028
Опыт
2,418,908

Интересно