Запуск алгоритма генного кроссовера

16

Ваша задача - принять в качестве входных данных две последовательности гена и последовательность «точек пересечения» и вернуть последовательность гена, полученную в результате указанных пересечений.

Я имею в виду, что у вас есть последовательности [A, A, A, A, A, A, A]и [Z, Z, Z, Z, Z, Z, Z], и пересекайте точки 2и 5. Результирующая последовательность будет [A, A, Z, Z, Z, A, A], потому что:

Крест здесь: ВВ
Индексы: 0 1 2 3 4 5 6

Гены 1: ААААААА
Гены 2: ZZZZZZZ

Результат: AAZZZAA
              ^ ^

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

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

Входные данные:

  • Ввод может быть в любой разумной форме. Две последовательности могут быть парой, с точками в качестве второго аргумента, все три могут быть отдельными аргументами, одним триплетом (genes 1, genes 2, cross-points), картой с именованными ключами ...

  • Точки пересечения всегда будут в порядке и всегда будут в границах. Повторных точек не будет, но список точек пересечения может быть пустым.

  • Генные последовательности всегда будут одинаковой длины и будут непустыми.

  • Индексы могут быть 0 или 1 на основе.

  • Гены всегда будут числами в диапазоне 0-255.

  • Неважно, какой аргумент "гены 1" или "гены 2". В случае отсутствия точек пересечения, результатом может быть либо полностью «гены 1», либо «гены 2».


Выход

  • Вывод может быть любой разумной формой, которая не является неоднозначной. Это может быть массив / список чисел, массив строковых чисел, строка чисел с разделителями (некоторые нечисловые символы должны разделять числа) ...

  • Его можно вернуть или распечатать на стандартный вывод.


Записи могут быть полными программами или функциями.


Тестовые случаи (genes 1, genes 2, cross points) => result:

[0], [1], [0] => [1]
[0, 1], [9, 8], [1] => [0, 8]
[0, 2, 4, 6, 8, 0], [1, 3, 5, 7, 9, 1], [1, 3, 5] => [0, 3, 5, 6, 8, 1]
[1, 2, 3, 4], [5, 6, 7, 8], [] => [1, 2, 3, 4]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 2, 3, 6, 8] => [1, 1, 0, 1, 1, 1, 0, 0, 1, 1]

Это Код Гольф.

Carcigenicate
источник
Ваш работающий пример был бы немного понятнее, если бы индексы кроссовера не были элементами в последовательностях.
Мохнатый
1
Исправлена. Поменял его на А и З. Надеюсь, это понятнее.
Carcigenicate

Ответы:

1

Желе , 12 10 байт

ṁ⁹L‘¤ḣ"ḷ"/

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

Аргумент 1: seq1, seq2
Аргумент 2: точки пересечения (с 0 индексами)

Эрик Outgolfer
источник
Была причина ... это не работает для одного из тестовых случаев !
Джонатан Аллан
Также терпит неудачу в других сценариях, например
Джонатан Аллан
Похоже, что-то вроде ;⁹ZL‘¤Ṭ+\ịŒDḢбы потребуется :(
Джонатан Аллан
@JonathanAllan Мне действительно удалось найти 12-байтовую версию, совершенно отличную от предложенной вами. :)
Эрик Outgolfer
@JonathanAllan ... и затем я обнаружил совершенно другую 10-байтовую версию, проверил ваши ссылки и другой контрольный пример (расслабьтесь, я действительно помнил, чтобы перейти на индексирование на основе 0). : D
Эрик Outgolfer
4

Haskell, 58 53 51 45 байт

(fst.).foldl(\(a,b)p->(take p a++drop p b,a))

Две генные последовательности взяты в виде пары списков, а точки пересечения - в качестве второго аргумента.

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

foldl           -- fold the pair of genes into the list of
                -- cross points and on each step
    \(a,b) p -> -- let the pair of genes be (a,b) and the next cross point 'p'
      (take p a++drop p b,a)  
                -- let 'b' the new first element of the pair, but
                --   drop the first 'p' elements and 
                --   prepend the first 'p' elements of 'a'
                -- let 'a' the new second element 
fst             -- when finished, return the first gene   
Ними
источник
4

JavaScript (ES6), 47 45 байт

Сохранено 2 байта благодаря @ETHproductions

Принимает входные данные в виде триплета [a, b, c], где a и b - последовательности генов, а c - список 0-индексированных точек пересечения.

x=>x[i=j=0].map(_=>x[(j+=x[2][j]==i)&1][i++])

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

комментарии

x =>                    // given x = [ geneSeqA, geneSeqB, crossPoints ]
  x[i = j = 0]          // initialize i = gene sequence pointer and j = cross point pointer
  .map(_ =>             // for each value in the first gene sequence:
    x[(                 //   access x[]
      j += x[2][j] == i //     increment j if i is equal to the next cross point
    ) & 1]              //   access either x[0] or x[1] according to the parity of j
    [i++]               //   read gene at x[0][i] or x[1][i]; increment i
  )                     // end of map()
Arnauld
источник
Я считаю, что вы можете сделать что-то вроде, x[(j+=x[2][j]==i)%2][i++]чтобы сохранить пару байтов.
ETHproductions
@ETHproductions Спасибо! Я по глупости попытался добавить третью переменную, чтобы отслеживать указатель в x [2], но упустил эту оптимизацию.
Арнаулд
3

APL (Dyalog 16.0) , 26 байтов

+/a⎕×(~,⊢)⊂≠\d1@⎕⊢0⍴⍨≢a←⎕

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

Ввод a , c , затем b . с будет 1индексироваться.

Как?

a←⎕- получить .

0⍴⍨≢создать массив 0s в его длине.

1@⎕⊢- возьмите c и измените 0s на 1s по индексам.

d←- назначить на d .

⊂≠\d- разверните d с помощью xor, чтобы создать последовательность выбора ( 0для a , 1для b ), и заключите.

(~,⊢)- взять d и его обратное.

a⎕×- и умножить соответственно с введенными b и a .

+/- суммировать каждую пару элементов, получая a s на 0s и b s на 1s.

Уриэль
источник
⊢0⍴⍨≢-> ≠⍨( совет )
нгн
@ngn Я не могу заставить его работать [tio ]
Уриэль
вам нужно ,до 1-элементных векторов на входе
ngn
2

Perl 5 -a , 45 40 байт

Введите входные данные в порядке «контроль», «вторая последовательность», «первая последовательность» в виде отдельных строк на STDIN

#!/usr/bin/perl -alp
@{$.}=@F}for(map${$.^=$%~~@1}[$%++],@2){

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

Тон Хоспел
источник
2

J , 24 байта

4 :'(2|+/\1 x}I.#{.y)}y'

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

Я не считаю f=: символы, потому что он работает так же хорошо, как анонимная функция (как показано в примере TIO)

Примечание: это не работает для пустого списка точек пересечения!

Явный xаргумент, левый аргумент - список точек пересечения,y - это правый аргумент, таблица из двух рядов последовательностей.

Объяснение:

4 :' ... ' - диадический глагол

(...)}y - Каждый атом операнда (...) выбирает атом из соответствующих позиций элементов у

#{.y - берет первую последовательность и находит ее длину

    #{. 0 2 4 6 8 0,: 1 3 5 7 9 1
6

I. создает список нулей с длиной аргумента

   I.6
0 0 0 0 0 0

1 x}изменяет элементы аргумента rigth (список нулей) на 1 по индексам, обозначенным как x(список cors по точкам)

   1(1 3 5)}I.6
0 1 0 1 0 1

+/\ промежуточные суммы списка

   +/\ 0 1 0 1 0 1
0 1 1 2 2 3

2| по модулю 2

   2|+/\ 0 1 0 1 0 1
0 1 1 0 0 1

Собранный:

    0 1 1 0 0 1 } 0 2 4 6 8 0 ,: 1 3 5 7 9 1
0 3 5 6 8 1
Гален Иванов
источник
2

R , 84 79 байт

function(G,K){o=G[,1]
m=1:nrow(G)
for(i in K)o[m>=i]=G[m>=i,match(i,K)%%2+1]
o}

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

Принимает входные данные в виде матрицы из 2 столбцов и a vector.

Giuseppe
источник
2

Python 3, 61 60 байт

f=lambda a,b,c,d=0:c and a[d:c[0]]+f(b,a,c[1:],c[0])or a[d:]

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

-1 байт от Джонатана Фреха

Объяснение:

f=lambda a,b,c,d=0:c and a[d:c[0]]+f(b,a,c[1:],c[0])or a[d:]
f=lambda a,b,c,d=0:
 # recursive lambda: a and b are the two lists,
 # c is the crossovers, and d is where to start
                   c and
 # if there is at least one crossover left
 #  then
                         a[d:c[0]]
 #  return the items of the first list from the
 #  starting point up to the first crossover
                                  +f(b,a,c[1:],c[0])
 #  plus the result of the inverted lists with
 #  the remaining crossovers, starting where
 #  the first part left off
                                                    or
 # else
                                                       a[d:]
 #  the first list from the starting point to the end
pizzapants184
источник
1
Возможные 60 байтов ; при условии, что a[d:c[0]]+f(b,a,c[1:],c[0])это никогда не будет ложным.
Джонатан Фрех
1

Желе , 13 байт

ṬœṗЀż/JḂị"ƊF

Двоичная ссылка, принимающая точки пересечения (с 1 индексом) слева и список двух последовательностей справа, который возвращает результирующий список.

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

Как?

ṬœṗЀż/JḂị"ƊF - Link: list, C; list, S     e.g. [2,4,6]; [[0,2,4,6,8,0],[1,3,5,7,9,1]]
Ṭ             - untruth C                       [0,1,0,1,0,1]
   Ѐ         - map across S with:
 œṗ           -   partition at truthy indices   [[0],[2,4],[6,8],[0]]  /  [[1],[3,5],[7,9],[1]]
      /       - reduce with:
     ż        -   zip                           [[[0],[1]],[[2,4],[3,5]],[[6,8],[7,9]],[[0],[1]]]
           Ɗ  - last three links as a monad:
       J      -   range of length               [1,2,3,4]
        Ḃ     -   bit (modulo by 2)             [1,0,1,0]
          "   -   zip with:
         ị    -     index into                  [[0],[3,5],[6,8],[1]]
            F - flatten                         [0,3,5,6,8,1]
Джонатан Аллан
источник
@Carcigenicate - спасибо, что я только что заметил, спросив: D
Джонатан Аллан
: Бесполезная вещь для индексации в двухэлементном списке. ż/: Как бесполезно из-за осложнений, он все равно жестоко расправляется с большим грузовиком!
Эрик Аутгольфер,
1

Древесный уголь , 19 байт

AθAηE§θ⁰§§θLΦ⊕κ№ηλκ

Попробуйте онлайн! Ссылка на подробную версию кода. Принимает входные данные в виде пары последовательностей генных строк и 0-индексированного списка точек пересечения. Объяснение:

Aθ                  Input the pair of gene sequences into `q`
  Aη                Input the list of crossing points into `h`
    E§θ⁰            Loop over one of the gene sequences
              κ     Current index
             ⊕      Incremented
            Φ  №ηλ  Intersect implicit range with crossing points
           L        Take the length
         §θ         Cyclically index into the pair of gene sequences
        §         κ Take the appropriate element of that sequence
                    Implicitly output on separate lines

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

Нил
источник
1

SWI-Пролог, 78 байт

A/B/[0|C]/D:-B/A/C/D. [H|A]/[_|B]/C/[H|D]:-maplist(succ,E,C),A/B/E/D. A/_/_/A.

Использование: вызовите «Genes1 / Genes2 / CrossoverPoints / X», где «Genes1», «Genes2», «CrossoverPoints» являются заключенными в скобки списками, разделенными запятыми.

ashtraypettingzoo
источник
1

C (лязг) , 79 байтов

*g[2],*c,l,m;f(i,j,k){for(i=j=k=0;i<l;g[0][i++]=g[k][i])m&&c[j]==i?k=!k,j++:0;}

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

Входные данные:
g[0]последовательность гена 1, последовательность
g[1]гена 2, точки
cпересечения.
lэто длина g[0]и g[1]
mдлина c
всех входных массивов являются массивами целых чисел с индексом на основе 0.

Выходы:
выход хранится вg[0]

macro a () в нижнем колонтитуле выполняет симпатичную печать тестовых случаев и результата

GPS
источник