Exécution d'un algorithme de croisement de gènes

16

Votre tâche consiste à accepter en entrée deux séquences de gènes et une séquence de «points de croisement» et à renvoyer la séquence de gènes résultant des croisements indiqués.

Ce que je veux dire par là, c'est que vous avez les séquences [A, A, A, A, A, A, A]et [Z, Z, Z, Z, Z, Z, Z], et traversez les points de 2et 5. La séquence résultante serait[A, A, Z, Z, Z, A, A] , car:

Traverser ici: VV
Indices: 0 1 2 3 4 5 6

Gènes 1: AAAAAAA
Gènes 2: ZZZZZZZ

Résultat: AAZZZAA
              ^ ^

Notez que pendant que j'utilise des lettres ici pour plus de clarté, le défi réel utilise des nombres pour les gènes.

Le résultat est la première séquence jusqu'à ce qu'un point de croisement soit rencontré, puis le résultat prend de la deuxième séquence jusqu'à ce qu'un autre point de croisement soit rencontré, puis le résultat prend de la première séquence jusqu'à ce qu'un point de croisement soit rencontré ...

Contribution:

  • L'entrée peut prendre toute forme raisonnable. Les deux séquences peuvent être une paire, avec les points comme deuxième argument, les trois peuvent être des arguments séparés, un seul triplet de (genes 1, genes 2, cross-points), une carte avec des clés nommées ...

  • Les points de croisement seront toujours en ordre et seront toujours dans les limites. Il n'y aura pas de points en double, mais la liste des points de croisement peut être vide.

  • Les séquences de gènes auront toujours la même longueur et ne seront pas vides.

  • Les indices peuvent être basés sur 0 ou 1.

  • Les gènes seront toujours des nombres compris entre 0 et 255.

  • Peu importe quel argument est "gènes 1" ou "gènes 2". En cas d'absence de points de croisement, le résultat peut être soit entièrement "gènes 1" soit "gènes 2".


Production

  • La sortie peut être toute forme raisonnable qui n'est pas ambiguë. Il peut s'agir d'un tableau / liste de nombres, d'un tableau de nombres de chaînes, d'une chaîne de nombres délimitée (certains caractères non numériques doivent séparer les nombres) ...

  • Il peut être retourné ou imprimé à la sortie standard.


Les entrées peuvent être effectuées par des programmes ou des fonctions complets.


Cas de test (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]

C'est Code Golf.

Carcigenicate
la source
Votre exemple travaillé serait un peu plus clair si les indices de croisement n'étaient pas également des éléments dans les séquences.
Shaggy
1
Fixé. Changé en A et Z. J'espère que c'est plus clair.
Carcigenicate

Réponses:

1

Gelée , 12 10 octets

ṁ⁹L‘¤ḣ"ḷ"/

Essayez-le en ligne!

Argument 1: seq1, seq2
Argument 2: points de croisement (indexés 0)

Erik le Outgolfer
la source
Il y avait une raison ... cela ne fonctionne pas pour l' un des cas de test !
Jonathan Allan
Échoue également dans d'autres scénarios, par exemple
Jonathan Allan
On dirait que quelque chose comme ;⁹ZL‘¤Ṭ+\ịŒDḢserait nécessaire :(
Jonathan Allan
@JonathanAllan En fait, j'ai réussi à trouver une version 12 octets assez différente de ce que vous avez suggéré. :)
Erik the Outgolfer
@JonathanAllan ... et puis j'ai découvert une version complètement différente de 10 octets, vérifiée à la fois avec vos liens et un autre cas de test (détendez-vous, je me suis souvenu de passer à l'indexation basée sur 0). : D
Erik the Outgolfer
4

Haskell, 58 53 51 45 octets

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

Les deux séquences de gènes sont considérées comme une paire de listes et les points de croisement comme un deuxième argument.

Essayez-le en ligne!

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
la source
4

JavaScript (ES6), 47 45 octets

Enregistré 2 octets grâce à @ETHproductions

Prend l'entrée sous la forme d'un triplet [a, b, c]a et b sont les séquences de gènes et c est la liste des points de croisement indexés sur 0.

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

Essayez-le en ligne!

Commenté

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
la source
Je pense que vous pouvez faire quelque chose comme x[(j+=x[2][j]==i)%2][i++]pour économiser quelques octets.
ETHproductions
@ETHproductions Merci! J'ai follement essayé d'ajouter une troisième variable pour garder une trace du pointeur dans x [2] mais j'ai ignoré cette optimisation.
Arnauld
3

APL (Dyalog 16.0) , 26 octets

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

Essayez-le en ligne!

L'entrée est a , c , puis b . c est1 indexé.

Comment?

a←⎕- obtenez un .

0⍴⍨≢ - créer un tableau de 0 s à sa longueur.

1@⎕⊢- prendre c et changer le 0s en1 s sur les indices.

d←- attribuer à d .

⊂≠\d- développez d avec xor pour créer la séquence de sélection ( 0pour a , 1pour b ), et fermez.

(~,⊢)- prendre d et son inverse.

a⎕×- et multiplier respectivement entré est b et a .

+/- additionner chaque paire d'éléments, donnant les a s sur 0s et b s sur 1s.

Uriel
la source
⊢0⍴⍨≢-> ≠⍨( astuce )
ngn
@ngn Je n'arrive pas à le faire fonctionner [tio ]
Uriel
vous avez besoin d'un ,vecteur avant à 1 élément dans l'entrée
ngn
2

Perl 5 -a , 45 40 octets

Donnez une entrée dans l'ordre "contrôle", "deuxième séquence", "première séquence" comme lignes distinctes sur STDIN

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

Essayez-le en ligne!

Ton Hospel
la source
2

J , 24 octets

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

Essayez-le en ligne!

Je ne compte pas le f=: caractères, car cela fonctionne aussi bien qu'une fonction anonyme (comme démontré dans un exemple TIO)

Remarque: Cela ne fonctionne pas pour une liste vide de points de croisement!

Un oneliner explicite, xest l'argument de gauche - la liste des points de croisement,y est l'argument de droite, un tableau à deux lignes des séquences.

Explication:

4 :' ... ' - un verbe dyadique

(...)}y - Chaque atome d'opérande (...) sélectionne un atome parmi les positions correspondantes des éléments de y

#{.y - prend la première séquence et trouve sa longueur

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

I. crée une liste de zéros avec la longueur de l'argument

   I.6
0 0 0 0 0 0

1 x}change les éléments de l'argument rigth (une liste de zéros) à 1 aux indices indiqués par x(la liste des cors sur les points)

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

+/\ exécution de sommes d'une liste

   +/\ 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

Assemblé:

    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
la source
2

R , 84 79 octets

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}

Essayez-le en ligne!

Prend l'entrée comme une matrice de 2 colonnes et a vector.

Giuseppe
la source
2

Python 3, 61 60 octets

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

Essayez-le en ligne!

-1 octet de Jonathan Frech

Explication:

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
la source
1
Possible 60 octets ; en supposant que a[d:c[0]]+f(b,a,c[1:],c[0])ce ne sera jamais faux.
Jonathan Frech
1

Gelée , 13 octets

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

Un lien dyadique acceptant les points de croisement (indexés 1) à gauche et une liste des deux séquences à droite qui renvoie la liste résultante.

Essayez-le en ligne!

Comment?

ṬœṗЀż/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
la source
@Carcigenicate - merci, je viens de remarquer après avoir demandé: D
Jonathan Allan
: Quelle chose inutile pour l'indexation dans une liste à 2 éléments. ż/: Quelle complication inutile, c'est quand même cruellement aplati par un gros camion!
Erik l'Outgolfer
1

Fusain , 19 octets

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

Essayez-le en ligne! Le lien est vers la version détaillée du code. Prend les entrées sous la forme d'une paire de séquences de gènes de chaîne et d'une liste indexée de 0 de points de croisement. Explication:

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

Alternativement, pourrait être substitué pour imprimer le résultat sous forme de chaîne. Essayez-le en ligne!

Neil
la source
1

SWI-Prolog, 78 octets

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.

Utilisation: Appelez "Genes1 / Genes2 / CrossoverPoints / X" où "Genes1", "Genes2", "CrossoverPoints" sont des listes entre crochets et séparées par des virgules.

ashtraypettingzoo
la source
1

C (clang) , 79 octets

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

Essayez-le en ligne!

Entrées:
g[0]est la séquence de gènes 1,
g[1]est la séquence de gènes 2,
cest des points de croisement.
lest la longueur de g[0]et g[1]
mest la longueur de c
Toutes les entrées du tableau sont des tableaux d'entiers avec un index basé sur 0.

Les sorties:
sortie est stockée dansg[0]

la macro a () dans le pied de page fait une jolie impression des cas de test et du résultat

GPS
la source