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[""]

Adam
la source
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.)

Jonathan Allan
la source
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
rahnema1
la source
7

C (GCC sur POSIX), 67 66 63 octets

-3 octets grâce à @LeakyNun!

f(i,s,j)char*s;{for(;j+i<=strlen(s);puts(""))write(1,s+j++,i);}

Essayez-le en ligne!

betseg
la source
Je ne pense pas que vous en ayez besoin j=0.
Leaky Nun
@LeakyNun, la fonction doit être réutilisable. Essayez-le en ligne! vs Essayez-le en ligne!
betseg
Mais si je fais ça ...
betseg
1
Vous pouvez remplacer j+i<=strlen(s)par justes[j+i]
Kritixi Lithos
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.
Leaky Nun
la source
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[]
Jonathan Allan
la source
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.

Leaky Nun
la source
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.

LegionMammal978
la source
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!

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

Pyth , 2 octets

.:

Ce n'est pas un programme complet, mais une fonction intégrée.

Appelez-le comme tel:

.:"ATCGAAGGTCGT"4

Essayez-le en ligne!

Programme complet:

.:.*

Essayez-le en ligne!

(Le .*est splat.)

Leaky Nun
la source
Même si cela n'a pas vraiment d'importance, .:Fc'est un octet plus court pour le programme complet.
FryAmTheEggman
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.

Leaky Nun
la source
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))
 ()]
NikoNyrh
la source
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.

Chat d'affaires
la source
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)$.)$)
Neil
la source
@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(...)).

Luis Mendo
la source
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.

Leaky Nun
la source
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);
Jörg Hülsermann
la source
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.

nimi
la source
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.

Andrei Odegov
la source
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
Conor O'Brien
la source
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

Skidsdev
la source
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.

Chowlett
la source
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!

nmjcman101
la source
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)
L3viathan
la source
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))
Neil
la source