Alle k-mers / n-Gramm

21

Intro

Wir hatten Histogramme und haben gezählt , aber nicht alle aufgelistet.

Jedes Jahr veranstaltet Dyalog Ltd. einen Studentenwettbewerb. Die Herausforderung besteht darin, guten APL-Code zu schreiben . Dies ist eine sprachunabhängige Ausgabe des diesjährigen sechsten Problems.

Ich habe die ausdrückliche Erlaubnis, diese Herausforderung hier vom ursprünglichen Autor des Wettbewerbs zu posten. Sie können dies jederzeit überprüfen, indem Sie dem angegebenen Link folgen und den Autor kontaktieren.

Problem

Der Begriff k-mer bezieht sich typischerweise auf alle möglichen Teilzeichenfolgen der Länge k , die in einer Zeichenfolge enthalten sind. In der Computational Genomics beziehen sich k-mere auf alle möglichen Teilsequenzen (mit der Länge k ) aus einem durch DNA-Sequenzierung erhaltenen Messwert. Schreiben Sie eine Funktion / ein Programm, das eine Zeichenfolge und k (die Länge der Teilzeichenfolge) verwendet und einen Vektor der k-mere der ursprünglichen Zeichenfolge zurückgibt / ausgibt.

Beispiele

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

k > Stringlänge? Nichts / kein leeres Ergebnis zurückgeben:
[4,"AC"][]oder ""oder[""]

Adam
quelle
4
Ist die Reihenfolge der Ausgabe wichtig? Wenn eine Teilzeichenfolge mehrmals vorkommt, sollte sie in der Ausgabe wiederholt werden?
Feersum
1
Kann ich durch Zeilenumbrüche getrennt , um eine Zeichenfolge der erforderlichen Teilrück anstelle eines Arrays von Strings, wie diese ?
Undichte Nonne
['A', 'T', 'C', 'G']"ATCG"
Adnan
Sind Dyalog APL-Antworten in dieser PPCG-Challenge zulässig (da die Challenge auch von Dyalog gehostet wird)?
Kritixi Lithos
1
@feersum Reihenfolge ist wichtig und Wiederholungen sollten wiederholt werden. Das ist wie ein Schiebefenster.
Adám

Antworten:

15

Gelee , 1 Byte

Jelly hat genau für diese Operation ein dyadisches Einzelbyte-Atom

Probieren Sie es online! (Die Fußzeile teilt die resultierende Liste mit Zeilenumbrüchen, um zu vermeiden, dass eine muskulöse Darstellung gedruckt wird.)

Jonathan Allan
quelle
1
Irgendwie muss das OP gewusst haben ...
Undichte Nonne
1
@LeakyNun habe ich eigentlich nicht.
Adám
8

Oktave, 28 Bytes

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

Probieren Sie es online!

Für k> funktioniert die Stringlänge in Octave 4.2.1-Fenstern, in tio (Octave 4.0.3) jedoch nicht.

Erstellt numerische Indizes aufeinanderfolgender Elemente und indiziert die Zeichenfolge danach.

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
quelle
7

C (GCC auf POSIX), 67 66 63 Bytes

-3 Bytes dank @LeakyNun!

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

Probieren Sie es online!

betseg
quelle
Ich glaube nicht, dass du brauchst j=0.
Undichte Nonne
@LeakyNun Die Funktion sollte wiederverwendbar sein. Probieren Sie es online! vs Online ausprobieren!
Betseg
Obwohl , wenn ich tun , um dieses ...
betseg
1
Sie können j+i<=strlen(s)mit nur ersetzens[j+i]
Kritixi Lithos
5

Brachylog , 3 Bytes

s₎ᶠ

Probieren Sie es online!

Technische Daten:

  • Eingang: ["ATCGAAGGTCGT",4]
  • Streit: Z
  • Ausgabe: Z = ["ATCG","TCGA","CGAA","GAAG","AAGG","AGGT","GGTC","GTCG","TCGT"]

Wie es funktioniert

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

Python 3 ,  47 45 42 Bytes

-3 Bytes dank ovs (benutze das Auspacken von Python 3, um es a[n-1:]am Ende wiederzuverwenden .)

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

Eine rekursive Funktion, die die Zeichenfolge aund die Slice-Länge verwendet nund eine Liste der Slices oder eine leere Zeichenfolge zurückgibt.

a[n-1:]Nimmt einen Teil der aktuellen Zeichenfolge ab dem n- 1ten (0-indizierten) Element, um zu testen, ob noch genügend Elemente vorhanden sind (eine leere Zeichenfolge ist in Python falsch). Dies ist kürzer als das Äquivalent len(a)>=n.

  • Wenn genügend Elemente vorhanden sind, wird eine Liste [...]mit den ersten nElementen der Zeichenfolge a[:n]und dem entpackten Ergebnis des erneuten Aufrufs der Funktion *f(...)mit einer in die Warteschlange gestellten Version der aktuellen Eingabe (ohne das erste Element) erstellt a[1:].

  • Wenn nicht genügend Elemente vorhanden sind, wird der Endpunkt der Rekursion erreicht, wenn a[n-1:]zurückgegeben wird (in diesem Fall eine leere Zeichenfolge).

Probieren Sie es online!


45 für Python 2 oder 3 mit:

f=lambda a,n:a[n-1:]and[a[:n]]+f(a[1:],n)or[]
Jonathan Allan
quelle
f=lambda a,n:a[n-1:]and[a[:n],*f(a[1:],n)]für 42 Bytes (Python 3) TIO
ovs
@ovs, sehr nett, ich habe gefragt, ob dies akzeptabel ist (da das leere Ergebnis eine Zeichenfolge ist, während das nicht leere Ergebnis eine Liste ist).
Jonathan Allan
4

J , 2 Bytes

,\

Es ist kein vollständiges Programm, sondern eine Funktion mit einem Operator.

Nennen Sie es als solches:

echo 4 ,\ 'ATCGAAGGTCGT'

Probieren Sie es online!

Wie es funktioniert

Der Operator (genannt "Konjunktion") \(genannt " Infix ") wird als solcher verwendet:

(x u\ y)Wendet das Verb uauf aufeinanderfolgende Teile der Liste an y(so genannte Infixe).

Die Funktion (genannt "Verb") ist uin diesem Fall die Funktion, ,die eine einfache " Anhängen " -Funktion ist:

Erstellt ein Array mit den Elementen von, xgefolgt von den Elementen von y.

Undichte Nonne
quelle
3

Mathematica, 21 Bytes

##~StringPartition~1&

Anonyme Funktion. Nimmt eine Zeichenfolge und eine Zahl (in dieser Reihenfolge) als Eingabe und gibt eine Liste von Zeichenfolgen als Ausgabe zurück.

LegionMammal978
quelle
3

R 65 61 Bytes

-2 Bytes dank MickyT

-2 Bytes durch Ändern der Indizierung

Gibt eine anonyme Funktion zurück.

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

substringDurchläuft die Indizes (im Gegensatz zu substrdenen , die dies nicht 1tun ). Wenn der Startindex kleiner als 1 ist, wird stattdessen standardmäßig der Wert 1 verwendet, sodass die leere Zeichenfolge überprüft und zurückgegeben wird.

x:n-n+1entspricht 1:(x-n+1)da :hat Vorrang vor Summen / Differenzen

Probieren Sie es online!

Giuseppe
quelle
Sie können ein paar Bytes mit function(s,n,x=nchar(s))if(n>x,'',substring(s,1:(x-n+1),n:x))
MickyT
@ MickyT, danke! Ich bemerkte auch, dass ich einige Bytes
Giuseppe
2

Pyth , 2 Bytes

.:

Es ist kein vollständiges Programm, sondern eine eingebaute Funktion.

Nennen Sie es als solches:

.:"ATCGAAGGTCGT"4

Probieren Sie es online!

Volles Programm:

.:.*

Probieren Sie es online!

(Das .*ist splat.)

Undichte Nonne
quelle
Während es eigentlich egal ist, .:Fist ein Byte kürzer für das gesamte Programm.
FryAmTheEggman
2

Qualle , 7 Bytes

p
_I
\i

Probieren Sie es online!

Wie es funktioniert

In linear :, p(\(I,i))wo pwird gedruckt und \erhält die erforderlichen Teilzeichenfolgen.

Iist die rohe erste Eingabe, während idie ausgewertete zweite Eingabe ist.

In Jellyfish erhält jede Funktion und jeder Operator zwei Argumente, eines von rechts und eines von unten. Hier perhält die Funktion das Argument aus der Ausgabe von _. Dies ist erforderlich, wenn der Operator \zum Abrufen von Teilzeichenfolgen verwendet werden soll.

Undichte Nonne
quelle
2

Clojure, 19 Bytes

Gut, das ist praktisch:

#(partition % 1 %2)

Beispiele:

(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
quelle
2

CJam , 4 Bytes

{ew}

Anonymer Block, der die Argumente auf dem Stapel erwartet und das Ergebnis danach auf dem Stapel belässt.

Probieren Sie es online!

ew ist ein eingebautes Gerät, das genau das tut, was benötigt wird.

Geschäfts-Katze
quelle
5
Ich muss nur eines sagen: ew
Adám
2

Retina , 41 38 Bytes

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

Probieren Sie es online!

Nimmt den String und zählt in separaten Zeilen. Die ersten beiden Zeilen werden verwendet, um den Zählwert von dezimal nach unär zu konvertieren. Wenn also eine unäre Eingabe zulässig ist, wird die Byteanzahl auf 34 reduziert . Oder, wenn Sie es vorziehen, eine 48-Byte-Version, die Zeilenumbrüche in der Zeichenfolge verarbeitet, obwohl dies zu einer verwirrenden Ausgabe führt:

.*$
$*
!&`(\S|\s)+(?=[\S\s]*¶(?<-1>.)+(?(1)$.)$)
Neil
quelle
@KritixiLithos Ich verstehe nicht, wie Ihre Lösung die Anzahl berücksichtigt ...
Neil
Oh, tut mir leid, ich hatte gerade einen
Hirnfurz
Dies bedeutet nicht unbedingt funktionieren , wenn die Zeichenfolge eine neue Zeile enthalten kann, so dass ich denke , Sie ändern können , (?!)zu .
FryAmTheEggman
2

Oktave mit Bildpaket, 29 Bytes

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

Probieren Sie es online!

Erläuterung

Die Funktion im2col(m,b)nimmt eine Matrix m, extrahiert daraus Größenblöcke bund ordnet sie als Spalten an. Standardmäßig werden Blöcke verschoben (im Gegensatz zu unterschiedlichen). Hier ist die Matrix mein Zeilenvektor der ASCII-Codes der Eingabezeichenfolge s(dies erfolgt als +s, was kürzer als der Standard ist double(s)), und die Größe bist [1 n], um horizontal gleitende Blöcke von nElementen zu erhalten.

Das Ergebnis wird transponiert (mithilfe der komplex-konjugierten Transponierung ', die kürzer als die Transponierung ist .'), um die Spalten in Zeilen umzuwandeln, und dann wieder in char ( [... '']die kürzer als der Standard ist char(...)) konvertiert .

Luis Mendo
quelle
1

Python 3 , 49 Bytes

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

Probieren Sie es online!

Eine nicht rekursive Lösung, wenn auch nicht kürzer.

Kompatibel mit Python 2.

Undichte Nonne
quelle
Sie können f=zwei Bytes sparen, da Sie sie fnirgendwo anders verwenden. Standardmäßig können Funktionen, die nur deklariert und nicht verwendet werden, unbenannt bleiben.
Mr. Xcoder
1

PHP, 75 Bytes

Online Version

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

80 Bytes ohne doppelte Werte

for([,$n,$s]=$argv;$i+$n-1<strlen($s);)$r[$p=substr($s,$i++,$n)]=$p;print_r($r);
Jörg Hülsermann
quelle
1

Haskell, 39 Bytes

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

Anwendungsbeispiel: 4 # "ABCDEF" -> ["ABCD","BCDE","CDEF"]. Probieren Sie es online!

Eine einfache Rekursion, die die ersten nZeichen der Eingabezeichenfolge beibehält und mit dem Ende der Zeichenfolge fortfährt, solange ihre Länge nicht kleiner als ist n.

nimi
quelle
1

Microsoft SQL Server, 199 Byte

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

Prüfen Sie.

Andrei Odegov
quelle
1

Gestapelt , 7 Bytes

infixes

Probieren Sie es online!

Ziemlich normal. Ohne dieses Builtin werden es 20 Bytes:

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

Welches ist:

{%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
quelle
1

C # 89 Bytes

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

Probieren Sie es online!

Die beste Methode, die ich in C # finden konnte, ist im Grunde die gleiche wie in Java

Skidsdev
quelle
1

Ruby, 48 46 Bytes

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

Keine besonderen Tricks, nur ein Stabby-Lambda, das eine Funktion definiert, die die erforderliche Teilzeichenfolge von jedem gültigen Startpunkt abzieht.

Zwei Bytes gespart, da das Lambda nicht gespeichert werden muss.

Chowlett
quelle
1

V , 16 Bytes

òÀ|ly0Ïp
"_xòkVp

Ich fürchte, nicht besonders gut golfen zu können, da ich mit "Lösche die Zeichenfolge, wenn k> len (str)" kämpfe. Die Eingabe erfolgt in der Datei, k ist ein Argument. Golfen vor der Erklärung

Probieren Sie es online!

nmjcman101
quelle
Was passiert, wenn Sie nicht versuchen, den Fall k> len (str) zu behandeln?
Adám
Abhängig von der Methode, die ich verwende (insbesondere in dieser), wird die Zeichenfolge so
belassen,
1

Standard ML (mosml), 109 65 61 Bytes

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

Nimmt eine Zahlen- und eine Zeichenliste auf (eine häufig verwendete Alternative zu Zeichenfolgen in der SML-Welt). (Funktioniert natürlich wirklich auf allen Listen.)

Verwendung:

- 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

Änderungsprotokoll:

  • Richtig, es gibt eine Standardbibliothek. (-44 Bytes)
  • Ändere Vergleich und Null in [] wie vorgeschlagen (-4 Bytes)
L3viathan
quelle
1
Sie können durch Ändern eines Byte speichern if length(x)<n thenzu if n>length(x)then. Da es für SML jedoch durchaus möglich ist, Zeichenfolgen zu verarbeiten, bin ich mir nicht sicher, ob es erforderlich explodesein darf, dass diese bereits auf die Eingabezeichenfolge angewendet werden.
Laikoni
Auch then nil elsekann verkürzt werden then[]else.
Laikoni
@ Laikoni nicht sicher, aber ¯ \ _ (ツ) _ / ¯
L3viathan
Unter Verwendung einiger anderer Bibliotheksfunktionen habe ich eine 68-Byte-Version erhalten, die sich mit Zeichenfolgen anstelle von Zeichenlisten befasst. Auch kann Ihr Ansatz auf 54 Bytes verkürzt werden: fun f$n=if n>length$then[]else List.take($,n)::f(tl$)n.
Laikoni
1

JavaScript (Firefox 30-57), 51 Byte

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

64 Bytes in ES6:

(s,n,t=s.slice(0,--n))=>[...s.slice(n)].map(c=>(t+=c).slice(~n))
Neil
quelle