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||
(==)=<<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
в цикле, потому что теперь мы входим в цикл в другом месте. Промойте и повторите.