Tous les k-mers / n-grammes


21

Intro

Nous avons eu des histogrammes et des comptages , mais pas tous.

Chaque année, Dyalog Ltd. organise un concours étudiant. Le défi consiste à écrire un bon code APL. Il s'agit d'une édition de indépendante du langage du sixième problème de cette année.

J'ai l'autorisation explicite de publier ce défi ici de l'auteur original du concours. N'hésitez pas à vérifier en suivant le lien fourni et en contactant l'auteur.

Problème

Le terme k-mer fait généralement référence à toutes les sous-chaînes possibles de longueur k contenues dans une chaîne. En génomique computationnelle, les k-mers font référence à toutes les sous-séquences possibles (de longueur k ) d'une lecture obtenue par séquençage d'ADN. Écrivez une fonction / programme qui prend une chaîne et k (la longueur de la sous-chaîne) et retourne / sort un vecteur des k-mers de la chaîne d'origine.

Exemples

[4,"ATCGAAGGTCGT"]["ATCG","TCGA","CGAA","GAAG","AAGG","AGGT","GGTC","GTCG","TCGT"]

k > longueur de chaîne? Ne rien retourner / aucun résultat vide:
[4,"AC"][]ou ""ou[""]


4
L'ordre de sortie est-il important? Lorsqu'une sous-chaîne se produit plusieurs fois, doit-elle être répétée dans la sortie?
feersum

1
Puis-je retourner une chaîne des sous-chaînes requises séparées par des retours à la ligne au lieu d'un tableau de chaînes, comme ceci ?
Leaky Nun

Pouvons-nous également entrer et sortir la chaîne sous la forme d'un tableau de caractères (comme ['A', 'T', 'C', 'G']au lieu de "ATCG"?
Adnan

Les réponses Dyalog APL sont-elles autorisées dans ce défi PPCG (car le défi est également hébergé par Dyalog)?
Kritixi Lithos

1
@feersum Order est important et les répétitions doivent être répétées. C'est comme une fenêtre coulissante.
Adám

Réponses:


15

Gelée , 1 octet

La gelée a un atome dyadique à un seul octet pour cette opération

Essayez-le en ligne!(le pied de page divise la liste résultante par des sauts de ligne, pour éviter l'impression d'une représentation musclée.)


1
D'une manière ou d'une autre, l'OP devait savoir ...
Leaky Nun

1
@LeakyNun Je ne l'ai pas fait.
Adám

8

Octave, 28 octets

@(N,s)s((1:N)+(0:nnz(s)-N)')

Essayez-le en ligne!

Pour k> la longueur de chaîne fonctionne dans les fenêtres Octave 4.2.1 mais dans tio (Octave 4.0.3) ne fonctionne pas.

Crée des index numériques d'éléments consécutifs et indexe la chaîne par elle.

s= "ATCGAAGGTCGT"
N = 4
idx = (1:N)+(0:nnz(s)-N)'
 =
    1    2    3    4
    2    3    4    5
    3    4    5    6
    4    5    6    7
    5    6    7    8
    6    7    8    9
    7    8    9   10
    8    9   10   11
    9   10   11   12

s(idx) =

ATCG
TCGA
CGAA
GAAG
AAGG
AGGT
GGTC
GTCG
TCGT



5

Brachylog , 3 octets

s₎ᶠ

Essayez-le en ligne!

Spécifications:

  • Contribution: ["ATCGAAGGTCGT",4]
  • Argument: Z
  • Sortie: Z = ["ATCG","TCGA","CGAA","GAAG","AAGG","AGGT","GGTC","GTCG","TCGT"]

Comment ça marche

s₎ᶠ
s    Output is a substring of first element of input,
 ₎   with length specified by second element of input.
  ᶠ  Find all solutions.

5

Python 3 ,  47 45 42 octets

-3 octets grâce aux ovs (utilisez le déballage de Python 3 pour réutiliser a[n-1:]à la fin.)

f=lambda a,n:a[n-1:]and[a[:n],*f(a[1:],n)]

Une fonction récursive prenant la chaîne, aet la longueur de tranche n, et renvoyant une liste des tranches ou une chaîne vide.

a[n-1:]prend une tranche de la chaîne actuelle à partir du n-1 ème élément (indexé 0) pour tester s'il reste suffisamment d'éléments (une chaîne vide est falsey en Python) - c'est plus court que l'équivalent len(a)>=n.

  • S'il y a suffisamment d' éléments d' une liste est construite, [...]avec les premiers néléments de la chaîne, a[:n]et le résultat décompressé d'appeler à nouveau la fonction, *f(...)avec une version dequeued de l'entrée actuelle (sans le premier élément), a[1:].

  • S'il n'y a pas assez d'éléments, la queue de la récursivité est atteinte quand a[n-1:]est retournée (dans ce cas une chaîne vide).

Essayez-le en ligne!


45 pour Python 2 ou 3 avec:

f=lambda a,n:a[n-1:]and[a[:n]]+f(a[1:],n)or[]

f=lambda a,n:a[n-1:]and[a[:n],*f(a[1:],n)]pour 42 octets (Python 3) TIO
ovs

@ovs, très bien, j'ai demandé si cela était acceptable (car le résultat vide est une chaîne, tandis que le résultat non vide est une liste).
Jonathan Allan

4

J , 2 octets

,\

Ce n'est pas un programme complet, mais une fonction avec un opérateur.

Appelez-le comme tel:

echo 4 ,\ 'ATCGAAGGTCGT'

Essayez-le en ligne!

Comment ça marche

L'opérateur (appelé "conjonction") \(nommé " infix ") est utilisé comme tel:

(x u\ y)applique le verbe uaux parties successives de la liste y(appelées infixes).

La fonction (appelée "verbe") udans ce cas est la fonction ,qui est une simple fonction " ajouter ":

Crée un tableau contenant les éléments de xsuivis des éléments de y.


3

Mathematica, 21 octets

##~StringPartition~1&

Fonction anonyme. Prend une chaîne et un nombre (dans cet ordre) en entrée et renvoie une liste de chaînes en sortie.


3

R, 65 61 octets

-2 octets grâce à MickyT

-2 octets en modifiant l'indexation

renvoie une fonction anonyme.

function(s,n,x=nchar(s))`if`(n>x,'',substring(s,x:n-n+1,n:x))

substringfait défiler les indices (contrairement à substrce qui n'est pas le cas), et si l'indice de départ est inférieur à 1, il est par défaut1 place, il vérifie et renvoie la chaîne vide.

x:n-n+1est équivalent à 1:(x-n+1)puisque: a priorité sur les sommes / différences

Essayez-le en ligne!


vous pouvez enregistrer quelques octets avec function(s,n,x=nchar(s))if(n>x,'',substring(s,1:(x-n+1),n:x))
MickyT

@MickyT, merci! J'ai également remarqué que je pouvais supprimer quelques octets en modifiant le calcul de l'index
Giuseppe


2

Méduse , 7 octets

p
_I
\i

Essayez-le en ligne!

Comment ça marche

En linéaire:, p(\(I,i))pest imprimé et\ obtient les sous-chaînes requises.

I est la première entrée brute i la deuxième entrée évaluée.

Dans Jellyfish, chaque fonction et opérateur reçoit deux arguments, l'un à droite et l'autre à partir du bas. Ici, la fonction pobtient l'argument de la sortie de _, qui est nécessaire si nous voulons utiliser l'opérateur \pour obtenir des sous-chaînes.




2

Clojure, 19 octets

Eh bien c'est pratique:

#(partition % 1 %2)

Exemples:

(def f #(partition % 1 %2))
(println [(f 4 "ATCGAAGGTCGT")
          (f 4 "abc")])

[((A T C G) (T C G A) (C G A A) (G A A G) (A A G G) (A G G T) (G G T C) (G T C G) (T C G T))
 ()]

2

CJam , 4 octets

{ew}

Bloc anonyme qui attend les arguments sur la pile et laisse le résultat sur la pile après.

Essayez-le en ligne!

ew est un intégré qui fait exactement ce qui est nécessaire.


5
Je n'ai qu'une chose à dire: ew
Adám

2

Rétine , 41 38 octets

.*$
$*
!&`(.)+(?=.*¶(?<-1>.)+(?(1)¶)$)

Essayez-le en ligne!

Prend la chaîne et compte sur des lignes séparées. Les deux premières lignes sont utilisées pour convertir le nombre de décimales en unaire, donc si une entrée unaire est acceptable, le nombre d'octets sera réduit à 34 31. Edit: 3 octets enregistrés grâce à @FryAmTheEggman. Ou, si vous préférez, une version de 48 octets qui gère les sauts de ligne dans la chaîne, bien que cela produise une sortie déroutante:

.*$
$*
!&`(\S|\s)+(?=[\S\s]*¶(?<-1>.)+(?(1)$.)$)

@KritixiLithos Je ne vois pas comment votre solution prend en compte le décompte ...
Neil

Oh, désolé je viens d'avoir un pet de cerveau> _ <
Kritixi Lithos

Cela ne fonctionne pas nécessairement si la chaîne peut contenir une nouvelle ligne, donc je pense que vous pouvez passer (?!)à .
FryAmTheEggman

2

Octave avec paquet d'images, 29 octets

@(s,n)[im2col(+s, [1 n])' '']

Essayez-le en ligne!

Explication

La fonction im2col(m,b)prend une matrice m, en extrait des blocs de taille bet les arrange en colonnes. Par défaut, les blocs glissent (par opposition à distincts). Ici, la matrice mest un vecteur ligne des codes ASCII de la chaîne d'entrée s(cela se fait comme +s, ce qui est plus court que la norme double(s)), et la taille best [1 n]d'obtenir des blocs coulissants horizontalement den éléments .

Le résultat est transposé (en utilisant une transposition conjuguée complexe ', qui est plus courte que transposer .') pour transformer les colonnes en lignes, puis il est reconverti en char ( [... ''], qui est plus court que la norme char(...)).



1

Python 3 , 49 octets

f=lambda a,n:[a[i:i+n]for i in range(len(a)-n+1)]

Essayez-le en ligne!

Une solution non récursive, quoique pas plus courte.

Compatible avec Python 2.


Vous pouvez supprimer f=, en économisant deux octets, car vous ne l'utilisez fnulle part ailleurs. Par défaut, les fonctions qui viennent d'être déclarées et non utilisées peuvent être laissées sans nom.
M. Xcoder

1

PHP, 75 octets

Version en ligne

for([,$n,$s]=$argv;$i+$n-1<strlen($s);)$r[]=substr($s,$i++,$n);print_r($r);

80 octets sans valeurs doubles

for([,$n,$s]=$argv;$i+$n-1<strlen($s);)$r[$p=substr($s,$i++,$n)]=$p;print_r($r);

1

Haskell, 39 octets

n#s|length s<n=[]|1<2=take n s:n#tail s

Exemple d'utilisation: 4 # "ABCDEF"-> ["ABCD","BCDE","CDEF"]. Essayez-le en ligne!

Une récursivité simple qui conserve les premiers ncaractères de la chaîne d'entrée et continue avec la queue de la chaîne tant que sa longueur n'est pas inférieure à n.


1

Microsoft Sql Server, 199 octets

create function dbo.f(@s nvarchar(max),@ int)returns table as return
with v as(select 2 p,left(@s,@)g where len(@s)>=@ union all
select p+1,substring(@s,p,@)from v where len(@s)>p-2+@)select g from v

Vérifie ça.



1

Empilé , 7 octets

infixes

Essayez-le en ligne!

Assez standard. Sans cette fonction intégrée, elle devient 20 octets:

{%x#'y-#+:>y#-#>x\#}

Lequel est:

{%x#'y-#+:>y#-#>x\#}
{%                 }   dyad; first arg: x, second arg: y
  x#'                  length of x (the array)
     y-                minus y (the skew)
       #+              plus 1
         :>            range [x, y]
           y#-         y minus 1
              #>       range from [[x, y], [x, y] + y]
                x\#    get indices from x


1

C # 89 octets

void a(string s,int n){for(int i=n;i<=s.Length;)Console.WriteLine(s.Substring(i++-n,n));}

Essayez-le en ligne!

La meilleure méthode que j'ai pu trouver en C # est fondamentalement la même que Java


1

Rubis, 48 46 octets

->(s,k){0.upto(s.size-k).map{|i|s[i..i+k-1]}}

Aucune astuce particulière, juste un stabby-lambda définissant une fonction qui tire la sous-chaîne requise de chaque point de départ valide.

Enregistrement de deux octets, car il ne semble pas nécessaire de stocker le lambda.


1

V , 16 octets

òÀ|ly0Ïp
"_xòkVp

Pas terriblement bien joué, je le crains, j'ai du mal à "supprimer la chaîne si k> len (str)". L'entrée est dans le fichier, k est un argument. Jouer au golf avant l'explication

Essayez-le en ligne!


Que se passe-t-il si vous n'essayez pas de gérer le cas k> len (str)?
Adám

Selon la méthode que j'utilise (dans celle-ci en particulier), elle laisse simplement la chaîne telle
quelle

1

ML standard (mosml), 109 65 61 octets

fun f(n,x)=if n>length(x)then[]else List.take(x,n)::f(n,tl x)

Prend un nombre et une liste de caractères (une alternative assez courante aux chaînes dans le monde SML). (Fonctionne vraiment sur toutes les listes bien sûr.)

Usage:

- f(3,explode("ABCDEFGH"));
> val it =
    [[#"A", #"B", #"C"], [#"B", #"C", #"D"], [#"C", #"D", #"E"],
     [#"D", #"E", #"F"], [#"E", #"F", #"G"], [#"F", #"G", #"H"]] :
  char list list
- f(7, explode("ABCD"));
> val it = [] : char list list

Journal des modifications:

  • À droite, il y a une bibliothèque standard .. (-44 octets)
  • Changez la comparaison et zéro en [] comme suggéré (-4 octets)

1
Vous pouvez enregistrer un octet en changeant if length(x)<n thenpour if n>length(x)then. Cependant, comme il est parfaitement possible pour SML de gérer des chaînes, je ne suis pas sûr qu'il soit autorisé d'exiger d' explodeêtre déjà appliqué à la chaîne d'entrée.
Laikoni

then nil elsePeut également être raccourci then[]else.
Laikoni

@Laikoni pas sûr non plus, mais ¯ \ _ (ツ) _ / ¯
L3viathan

En utilisant d'autres fonctions de bibliothèque, j'ai obtenu une version de 68 octets qui traite des chaînes au lieu des listes de caractères. De plus , votre approche peut être raccourci à 54 octets: fun f$n=if n>length$then[]else List.take($,n)::f(tl$)n.
Laikoni

1

JavaScript (Firefox 30-57), 51 octets

(s,n,t='')=>[for(c of s)if((t+=c)[n-1])t.slice(-n)]

64 octets dans ES6:

(s,n,t=s.slice(0,--n))=>[...s.slice(n)].map(c=>(t+=c).slice(~n))
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.