Algoritmo de cruzamento de genes em execução


16

Sua tarefa é aceitar como entrada duas seqüências genéticas e uma sequência de "pontos de cruzamento" e retornar a sequência de genes resultante dos cruzamentos indicados.

O que quero dizer com isso é dizer que você tem as seqüências [A, A, A, A, A, A, A]e [Z, Z, Z, Z, Z, Z, Z], e cruza os pontos de 2e 5. A sequência resultante seria [A, A, Z, Z, Z, A, A], porque:

Cruze aqui: VV
Índices: 0 1 2 3 4 5 6

Genes 1: AAAAAAA
Genes 2: ZZZZZZZ

Resultado: AAZZZAA
              ^ ^

Observe que, enquanto uso letras aqui para maior clareza, o desafio real usa números para genes.

O resultado é a primeira sequência até que um ponto de cruzamento seja encontrado; o resultado leva da segunda sequência até que outro ponto de cruzamento seja encontrado; o resultado leva a partir da primeira sequência até que um ponto de cruzamento seja encontrado ...

Entrada:

  • A entrada pode ser de qualquer forma razoável. As duas sequências podem ser um par, com os pontos como segundo argumento, todos os três podem ser argumentos separados, um único trigêmeo de (genes 1, genes 2, cross-points), um mapa com chaves nomeadas ...

  • Os pontos cruzados estarão sempre em ordem e sempre estarão dentro dos limites. Não haverá pontos duplicados, mas a lista de pontos de cruzamento pode estar vazia.

  • As seqüências de genes sempre terão o mesmo comprimento e não serão vazias.

  • Os índices podem ser baseados em 0 ou 1.

  • Os genes sempre serão números no intervalo de 0 a 255.

  • Não importa qual argumento seja "genes 1" ou "genes 2". No caso de não haver pontos de cruzamento, o resultado pode ser inteiramente "genes 1" ou "genes 2".


Resultado

  • A saída pode ser de qualquer forma razoável que não seja ambígua. Pode ser uma matriz / lista de números, uma matriz de números de sequência, uma sequência de números delimitada (algum caractere não numérico deve separar os números) ...

  • Ele pode ser devolvido ou impresso na saída padrão.


As entradas podem por programas ou funções completos.


Casos de teste (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]

Este é o Code Golf.


Seu exemplo trabalhado seria um pouco mais claro se os índices de cruzamento também não fossem elementos nas seqüências.
Shaggy

1
Fixo. Alterou para A e Z. Espero que seja mais claro.
Carcigenicate

Respostas:


1

Gelatina , 12 10 bytes

ṁ⁹L‘¤ḣ"ḷ"/

Experimente online!

Argumento 1: seq1, seq2
Argumento 2: pontos cruzados (indexado 0)


Havia um motivo ... isso não funciona para um dos casos de teste !
Jonathan Allan

Também falhar em outros cenários, por exemplo
Jonathan Allan

Parece que algo como ;⁹ZL‘¤Ṭ+\ịŒDḢseria necessário :(
Jonathan Allan

@ JonathanAllan Na verdade, eu consegui encontrar uma versão de 12 bytes bastante diferente do que você sugeriu. :)
Erik the Outgolfer

@ JonathanAllan ... e então descobri uma versão completamente diferente de 10 bytes, verificada com seus links e outro caso de teste (relaxe, lembrei de mudar para a indexação baseada em 0). : D
Erik the Outgolfer 25/03

4

Haskell, 58 53 51 45 bytes

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

As duas seqüências gênicas são tomadas como um par de listas e os pontos cruzados como um segundo argumento.

Experimente online!

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 bytes

Economizou 2 bytes graças a @ETHproductions

Toma de entrada como um tripleto [a, b, c] , onde um e b são as sequências de genes e c é a lista de pontos de cruzamento 0-indexados.

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

Experimente online!

Comentado

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

Eu acredito que você pode fazer algo como x[(j+=x[2][j]==i)%2][i++]salvar alguns bytes.
ETHproductions

@ETHproductions Obrigado! Eu tolamente tentei adicionar uma 3ª variável para acompanhar o ponteiro em x [2], mas ignorei essa otimização.
Arnauld

3

APL (Dyalog 16.0) , 26 bytes

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

Experimente online!

A entrada é a , c e b . c é 1indexado.

Quão?

a←⎕- pegue um .

0⍴⍨≢- crie uma matriz de 0s em seu comprimento.

1@⎕⊢- pegue c e mude 0s para 1s nos índices.

d←- atribuir a d .

⊂≠\d- expanda d com xor para criar a sequência de seleção ( 0para a , 1para b ) e inclua.

(~,⊢)- tome d e seu inverso.

a⎕×- e multiplique respectivamente com b e a inseridos .

+/- somar cada par de elementos, obtendo-se o um s em 0s e b s no 1s.


⊢0⍴⍨≢-> ≠⍨( tip )
ngn

@ngn eu não posso obtê-lo para o trabalho [tio ]
Uriel

você precisa de um ,vetor de 1 elemento anterior na entrada
ngn


2

Perl 5 -a , 45 40 bytes

Dê entrada na ordem "controle", "segunda sequência", "primeira sequência" como linhas separadas em STDIN

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

Experimente online!


2

J , 24 bytes

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

Experimente online!

Eu não conto os f=:caracteres, porque funciona igualmente bem como uma função anônima (como demonstrado em uma amostra TIO)

Nota: Não funciona para uma lista vazia de pontos de passagem!

Um oneliner explícito xé o argumento da esquerda - a lista de pontos de cruzamento, yé o argumento da direita, uma tabela de duas linhas das seqüências.

Explicação:

4 :' ... ' - um verbo diádico

(...)}y - Cada átomo do operando (...) seleciona um átomo das posições correspondentes dos itens de y

#{.y - pega a primeira sequência e encontra seu comprimento

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

I. cria uma lista de zeros com o comprimento do argumento

   I.6
0 0 0 0 0 0

1 x}altera os itens do argumento rigth (uma lista de zeros) para 1 nos índices indicados por x(a lista de cors sobre pontos)

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

+/\ executando somas de uma lista

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

2| módulo 2

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

Montado:

    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 bytes

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}

Experimente online!

Recebe entrada como uma matriz de 2 colunas e a vector.


2

Python 3, 61 60 bytes

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

Experimente online!

-1 byte de Jonathan Frech

Explicação:

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

1
Possíveis 60 bytes ; assumindo que a[d:c[0]]+f(b,a,c[1:],c[0])nunca será falso.
Jonathan Frech 25/03

1

Gelatina , 13 bytes

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

Um link diádico que aceita os pontos de cruzamento (indexados em 1) à esquerda e uma lista das duas seqüências à direita que retorna a lista resultante.

Experimente online!

Quão?

ṬœṗЀż/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 - graças eu só notei depois de pedir: D
Jonathan Allan

: Que coisa inútil para indexar em uma lista de 2 elementos. ż/: Como é inútil uma complicação, ela é cruelmente achatada por um caminhão grande de qualquer maneira!
Erik the Outgolfer

1

Carvão , 19 bytes

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

Experimente online! Link é a versão detalhada do código. Recebe entrada como um par de seqüências de genes de cadeia e uma lista indexada de 0 de pontos de cruzamento. Explicação:

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

Como alternativa, pode ser substituído para imprimir o resultado como uma sequência. Experimente online!


1

SWI-Prolog, 78 bytes

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.

Uso: chame "Genes1 / Genes2 / CrossoverPoints / X" onde "Genes1", "Genes2", "CrossoverPoints" são listas entre colchetes e separadas por vírgula.


1

C (clang) , 79 bytes

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

Experimente online!

Entradas:
g[0]é a sequência gênica 1,
g[1]é a seqüência gênica 2,
cé um ponto de cruzamento.
lé comprimento de g[0]e g[1]
mé comprimento de c
Todas as entradas da matriz são matrizes de números inteiros com índice baseado em 0.

Saídas: A
saída é armazenada emg[0]

A macro a () no rodapé faz uma bonita impressão de casos de teste e resulta

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.