Ejecución del algoritmo de cruce de genes

16

Su tarea es aceptar como entrada dos secuencias de genes y una secuencia de "puntos de cruce", y devolver la secuencia de genes que resulta de los cruces indicados.

Lo que quiero decir con esto es, digamos que tiene las secuencias [A, A, A, A, A, A, A]y [Z, Z, Z, Z, Z, Z, Z], y cruce los puntos de 2y 5. La secuencia resultante sería [A, A, Z, Z, Z, A, A], porque:

Cruce aquí: VV
Índices: 0 1 2 3 4 5 6

Genes 1: AAAAAAA
Genes 2: ZZZZZZZ

Resultado: AAZZZAA
              ^ ^

Tenga en cuenta que si bien estoy usando letras aquí para mayor claridad, el desafío real usa números para genes.

El resultado es la primera secuencia hasta que se encuentra un punto cruzado, luego el resultado toma de la segunda secuencia hasta que se encuentra otro punto cruzado, luego el resultado toma desde la primera secuencia hasta que se encuentra un punto cruzado ...

Entrada:

  • La entrada puede ser de cualquier forma razonable. Las dos secuencias pueden ser un par, con los puntos como el segundo argumento, los tres pueden ser argumentos separados, un solo triplete de (genes 1, genes 2, cross-points), un mapa con teclas con nombre ...

  • Los puntos cruzados siempre estarán en orden y siempre estarán dentro de los límites. No habrá puntos duplicados, pero la lista de puntos cruzados puede estar vacía.

  • Las secuencias de genes siempre tendrán la misma longitud y no estarán vacías.

  • Los índices pueden estar basados ​​en 0 o 1.

  • Los genes siempre serán números en el rango 0-255.

  • No importa qué argumento sea "genes 1" o "genes 2". En el caso de que no haya puntos cruzados, el resultado puede ser completamente "genes 1" o "genes 2".


Salida

  • La salida puede ser cualquier forma razonable que no sea ambigua. Puede ser una matriz / lista de números, una matriz de números de cadena, una cadena de números delimitada (algunos caracteres no numéricos deben separar los números) ...

  • Se puede devolver o imprimir en la salida estándar.


Las entradas pueden por programas completos o funciones.


Casos de prueba (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 es el código de golf.

Carcigenicate
fuente
Su ejemplo trabajado sería un poco más claro si los índices cruzados no fueran también elementos en las secuencias.
Shaggy
1
Fijo. Lo cambié a A y Z. Espero que sea más claro.
Carcigenicate

Respuestas:

1

Jalea , 12 10 bytes

ṁ⁹L‘¤ḣ"ḷ"/

Pruébalo en línea!

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

Erik el Outgolfer
fuente
Había una razón ... ¡esto no funciona para uno de los casos de prueba !
Jonathan Allan
También falla en otros escenarios, por ejemplo
Jonathan Allan
Parece ;⁹ZL‘¤Ṭ+\ịŒDḢque se requeriría algo así :(
Jonathan Allan
@JonathanAllan Realmente logré encontrar una versión de 12 bytes bastante diferente de lo que sugeriste. :)
Erik the Outgolfer
@JonathanAllan ... y luego descubrí una versión de 10 bytes completamente diferente, comprobada tanto con sus enlaces como con otro caso de prueba (relájese, recordé cambiar a indexación basada en 0). : D
Erik the Outgolfer
4

Haskell, 58 53 51 45 bytes

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

Las dos secuencias de genes se toman como un par de listas y los puntos de cruce como un segundo argumento.

Pruébalo en línea!

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   
nimi
fuente
4

JavaScript (ES6), 47 45 bytes

Guardado 2 bytes gracias a @ETHproductions

Toma la entrada como un triplete [a, b, c] donde a y b son las secuencias de genes y c es la lista de puntos cruzados indexados en 0.

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

Pruébalo en línea!

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()
Arnauld
fuente
Creo que puedes hacer algo como x[(j+=x[2][j]==i)%2][i++]guardar un par de bytes.
ETHproductions
@ETHproductions ¡Gracias! Intenté tontamente agregar una tercera variable para hacer un seguimiento del puntero en x [2] pero pasé por alto esta optimización.
Arnauld
3

APL (Dyalog 16.0) , 26 bytes

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

Pruébalo en línea!

La entrada es a , c , luego b . c es1 indexado.

¿Cómo?

a←⎕- obtener un .

0⍴⍨≢ - crear una matriz de 0 s en su longitud.

1@⎕⊢- tome c y cambie la 0s a1 s en los índices.

d←- asignar a d .

⊂≠\d- expanda d con xor para crear la secuencia de selección ( 0para a , 1para b ) y encierre.

(~,⊢)- tome d y su inverso.

a⎕×- y multiplicar respectivamente con las entradas b y a .

+/- suma cada par de elementos, produciendo a s en 0s y b s en 1s.

Uriel
fuente
⊢0⍴⍨≢-> ≠⍨( punta )
ngn
@ngn No puedo hacer que funcione [tio ]
Uriel
necesita un ,vector de 1 elemento antes en la entrada
ngn
2

Perl 5 -a , 45 40 bytes

Dé entrada en el orden "control", "segunda secuencia", "primera secuencia" como líneas separadas en STDIN

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

Pruébalo en línea!

Ton Hospel
fuente
2

J , 24 bytes

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

Pruébalo en línea!

No cuento el f=: caracteres, porque funciona igual de bien como una función anónima (como se demuestra en una muestra de TIO)

Nota: ¡No funciona para la lista vacía de puntos cruzados!

Un xargumento explícito es el argumento izquierdo: la lista de puntos cruzados,y es el argumento correcto, una tabla de dos filas de las secuencias.

Explicación:

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

(...)}y - Cada átomo de operando (...) selecciona un átomo de las posiciones correspondientes de los elementos de y

#{.y - toma la primera secuencia y encuentra su longitud

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

I. crea una lista de ceros con longitud del argumento

   I.6
0 0 0 0 0 0

1 x} cambia los elementos del argumento derecho (una lista de ceros) a 1 en los índices indicados por x (la lista de puntos sobre puntos)

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

+/\ corriendo sumas de una 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
Galen Ivanov
fuente
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}

Pruébalo en línea!

Toma datos como una matriz de 2 columnas y a vector.

Giuseppe
fuente
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:]

Pruébalo en línea!

-1 byte de Jonathan Frech

Explicación:

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
fuente
1
Posibles 60 bytes ; asumiendo que a[d:c[0]]+f(b,a,c[1:],c[0])eso nunca será falso.
Jonathan Frech
1

Jalea , 13 bytes

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

Un enlace diádico que acepta los puntos de cruce (indexados) a la izquierda y una lista de las dos secuencias a la derecha que devuelve la lista resultante.

Pruébalo en línea!

¿Cómo?

ṬœṗЀż/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]
Jonathan Allan
fuente
@Carcigenicate - gracias que acabo de notar después de preguntar: D
Jonathan Allan
: Qué cosa inútil para indexar en una lista de 2 elementos. ż/: ¡Qué inútil es una complicación, de todos modos es cruelmente aplastada por un gran camión!
Erik the Outgolfer
1

Carbón de leña , 19 bytes

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

Pruébalo en línea! El enlace es a la versión detallada del código. Toma datos como un par de secuencias de genes de cadena y una lista de puntos de cruce indexados en 0. Explicación:

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

Alternativamente, podría ser sustituido para imprimir el resultado como una cadena. Pruébalo en línea!

Neil
fuente
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: llame a "Genes1 / Genes2 / CrossoverPoints / X" donde "Genes1", "Genes2", "CrossoverPoints" son listas entre comillas y separadas por comas.

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

Pruébalo en línea!

Entradas:
g[0]es la secuencia génica 1,
g[1]es la secuencia génica 2,
ces un punto de cruce.
les longitud g[0]y g[1]
mes longitud dec
Todas las entradas de matriz son matrices de enteros con índice basado en 0.

Salidas:
salida se almacena eng[0]

la macro a () en el pie de página hace una impresión bonita de los casos de prueba y el resultado

GPS
fuente