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


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:



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



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.

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

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.


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.


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!


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

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.




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


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)$.)$)

@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 .



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.


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

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.


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.



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


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


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.


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!


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)

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))
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.