Esecuzione dell'algoritmo crossover genico


16

Il tuo compito è accettare come input due sequenze geniche e una sequenza di "punti di crossover" e restituire la sequenza genica che risulta dai crossover indicati.

Quello che voglio dire con questo è, supponiamo di avere le sequenze [A, A, A, A, A, A, A]e [Z, Z, Z, Z, Z, Z, Z], e attraversare i punti di 2e 5. La sequenza risultante sarebbe [A, A, Z, Z, Z, A, A], perché:

Croce qui: VV
Indici: 0 1 2 3 4 5 6

Geni 1: AAAAAAA
Geni 2: ZZZZZZZ

Risultato: AAZZZAA
              ^ ^

Nota che mentre sto usando le lettere qui per chiarezza, la vera sfida usa i numeri per i geni.

Il risultato è la prima sequenza fino a quando non viene rilevato un punto di incrocio, quindi il risultato prende dalla seconda sequenza fino a quando non viene rilevato un altro punto di incrocio, quindi il risultato prende dalla prima sequenza fino a quando non viene rilevato un punto di incrocio ...

Ingresso:

  • L'input può essere qualsiasi forma ragionevole. Le due sequenze possono essere una coppia, con i punti come secondo argomento, tutti e tre possono essere argomenti separati, una sola tripletta di (genes 1, genes 2, cross-points), una mappa con chiavi denominate ...

  • I punti di incrocio saranno sempre in ordine e saranno sempre in bilico. Non ci saranno punti duplicati, ma l'elenco dei punti di incrocio potrebbe essere vuoto.

  • Le sequenze geniche avranno sempre la stessa lunghezza e non saranno vuote.

  • Gli indici possono essere basati su 0 o 1.

  • I geni saranno sempre numeri nell'intervallo 0-255.

  • Non importa quale argomento sia "geni 1" o "geni 2". In caso di nessun punto di incrocio, il risultato può essere interamente "geni 1" o "geni 2".


Produzione

  • L'output può essere qualsiasi forma ragionevole che non sia ambigua. Può essere una matrice / un elenco di numeri, una matrice di numeri di stringa, una stringa di numeri delimitata (alcuni caratteri non numerici devono separare i numeri) ...

  • Può essere restituito o stampato sullo std-out.


Le voci possono tramite programmi o funzioni completi.


Casi di prova (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]

Questo è Code Golf.


Il tuo esempio elaborato sarebbe un po 'più chiaro se gli indici crossover non fossero anche elementi nelle sequenze.
Shaggy,

1
Fisso. Modificato in A e Z. Spero sia più chiaro.
Carcigenicate

Risposte:


1

Gelatina , 12 10 byte

ṁ⁹L‘¤ḣ"ḷ"/

Provalo online!

Argomento 1: seq1, seq2
Argomento 2: punti incrociati (indicizzati 0)


C'era una ragione ... questo non funziona per uno dei casi di test !
Jonathan Allan,

Fallisce anche in altri scenari, ad es
Jonathan Allan,

Sembra che ;⁹ZL‘¤Ṭ+\ịŒDḢsarebbe richiesto qualcosa del genere :(
Jonathan Allan,

@JonathanAllan In realtà sono riuscito a trovare una versione a 12 byte abbastanza diversa da quella che hai suggerito. :)
Erik the Outgolfer

@JonathanAllan ... e poi ho scoperto una versione di 10 byte completamente diversa, verificata con entrambi i tuoi collegamenti e un altro caso di test (rilassati, mi sono ricordato di passare all'indicizzazione basata su 0). : D
Erik the Outgolfer,

4

Haskell, 58 53 51 45 byte

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

Le due sequenze geniche sono prese come una coppia di liste e i punti croce come secondo argomento.

Provalo 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 byte

Salvato 2 byte grazie a @ETHproductions

Prende input come una tripletta [a, b, c] dove un e b sono le sequenze geniche e c è la lista di 0-indicizzati trasversali punti.

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

Provalo online!

Commentate

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

Credo che tu possa fare qualcosa di simile x[(j+=x[2][j]==i)%2][i++]per salvare un paio di byte.
ETHproductions

@ETHproductions Grazie! Ho stupidamente provato ad aggiungere una terza variabile per tenere traccia del puntatore in x [2] ma ho trascurato questa ottimizzazione.
Arnauld,

3

APL (Dyalog 16.0) , 26 byte

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

Provalo online!

L'input è a , c , quindi b . c è 1indicizzato.

Come?

a←⎕- prendi a .

0⍴⍨≢- crea una serie di 0s alla sua lunghezza.

1@⎕⊢- prendi c e cambia la 0s in 1s sugli indici.

d←- assegnare a d .

⊂≠\d- espandere d con xor per creare la sequenza di selezione ( 0per a , 1per b ) e racchiudere.

(~,⊢)- prendere d e il suo inverso.

a⎕×- e si moltiplicano rispettivamente immesso B e un .

+/- somma ogni coppia di elementi, producendo a s su 0s e b s su 1s.


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

@ngn Non riesco a farlo funzionare [tio ]
Uriel

hai bisogno di un ,vettore prima di 1 elemento nell'input
ngn


2

Perl 5 -a , 45 40 byte

Fornire input nell'ordine "controllo", "seconda sequenza", "prima sequenza" come righe separate su STDIN

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

Provalo online!


2

J , 24 byte

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

Provalo online!

Non conto i f=:caratteri, perché funziona ugualmente bene come funzione anonima (come dimostrato in un esempio TIO)

Nota: non funziona per un elenco vuoto di punti di crossover!

Un esplicito oneliner, xè l'argomento di sinistra: l'elenco dei punti incrociati,y è l'argomento giusto, una tabella a due righe delle sequenze.

Spiegazione:

4 :' ... ' - un verbo diadico

(...)}y - Ogni atomo dell'operando (...) seleziona un atomo dalle posizioni corrispondenti degli elementi di y

#{.y - prende la prima sequenza e trova la sua lunghezza

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

I. crea un elenco di zeri con lunghezza l'argomento

   I.6
0 0 0 0 0 0

1 x}cambia gli elementi dell'argomento rigth (un elenco di zero) in 1 in corrispondenza degli indici indicati da x(l'elenco dei punti cors over)

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

+/\ eseguendo somme di un elenco

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

2| modulo 2

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

assemblato:

    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 byte

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}

Provalo online!

Accetta input come una matrice di 2 colonne e a vector.


2

Python 3, 61 60 byte

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

Provalo online!

-1 byte da Jonathan Frech

Spiegazione:

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
Possibili 60 byte ; supponendo che a[d:c[0]]+f(b,a,c[1:],c[0])non sarà mai falso.
Jonathan Frech,

1

Gelatina , 13 byte

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

Un collegamento diadico che accetta i punti di crossover (1 indicizzati) a sinistra e un elenco delle due sequenze a destra che restituisce l'elenco risultante.

Provalo online!

Come?

ṬœṗЀż/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]

@Carcigenicato - grazie appena notato dopo aver chiesto: D
Jonathan Allan

: Che cosa inutile per indicizzare in un elenco di 2 elementi. ż/: Com'è inutile una complicazione, è comunque crudelmente schiacciata da un grosso camion!
Erik the Outgolfer,

1

Carbone , 19 byte

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

Provalo online! Il collegamento è alla versione dettagliata del codice. Prende input come una coppia di sequenze di geni stringa e un elenco di punti di attraversamento con indice 0. Spiegazione:

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

In alternativa, potrebbe essere sostituito per stampare il risultato come stringa. Provalo online!


1

SWI-Prolog, 78 byte

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.

Utilizzo: chiama "Genes1 / Genes2 / CrossoverPoints / X" dove "Genes1", "Genes2", "CrossoverPoints" sono elenchi racchiusi tra parentesi, separati da virgole.


1

C (clang) , 79 byte

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

Provalo online!

Input:
g[0]è la sequenza genica 1,
g[1]è la sequenza genica 2,
cè punti incrociati.
lè lunghezza g[0]ed g[1]
mè lunghezza di c
Tutti gli input di array sono array di numeri interi con indice basato su 0.

Uscite: l'
uscita è memorizzata ing[0]

la macro a () nel piè di pagina consente di stampare in modo grazioso casi di test e risultati

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.