Todos los k-mers / n-gramos

21

Introducción

Hemos tenido histogramas y contando , pero no los hemos enumerado todos.

Cada año, Dyalog Ltd. celebra una competencia estudiantil. El desafío es escribir un buen código APL. Esta es una edición de independiente del sexto problema de este año.

Tengo permiso explícito para publicar este desafío aquí del autor original de la competencia. No dude en verificar siguiendo el enlace proporcionado y contactando al autor.

Problema

El término k-mer generalmente se refiere a todas las posibles subcadenas de longitud k que están contenidas en una cadena. En genómica computacional, los k-mers se refieren a todas las subsecuencias posibles (de longitud k ) de una lectura obtenida a través de la secuenciación de ADN. Escriba una función / programa que tome una cadena yk (la longitud de la subcadena) y devuelva / genere un vector de los k-mers de la cadena original.

Ejemplos

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

k > longitud de la cuerda? No devuelve nada / ningún resultado vacío:
[4,"AC"][]o ""o[""]

Adán
fuente
44
¿Importa el orden de salida? Cuando una subcadena ocurre varias veces, ¿debería repetirse en la salida?
Feersum
1
¿Puedo devolver una cadena de las subcadenas requeridas separadas por nuevas líneas en lugar de una matriz de cadenas, como esta ?
Leaky Nun
¿Podemos también ingresar y emitir la cadena como una matriz de caracteres (como en ['A', 'T', 'C', 'G']lugar de "ATCG"?
Adnan
¿Se permiten las respuestas Dyalog APL en este desafío PPCG (porque el desafío también está alojado por Dyalog)?
Kritixi Lithos
1
@feersum El orden es importante y las repeticiones deben repetirse. Esto es como una ventana deslizante.
Adám

Respuestas:

15

Gelatina , 1 byte

Jelly tiene un átomo diádico de un solo byte para esta misma operación

Pruébalo en línea! (el pie de página divide la lista resultante con nuevas líneas, para evitar que se imprima una representación borrosa).

Jonathan Allan
fuente
1
De alguna manera, el OP debe haber sabido ...
Leaky Nun
1
@LeakyNun en realidad no lo hice.
Adám
8

Octava, 28 bytes

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

Pruébalo en línea!

Para k> la longitud de la cadena funciona en Octave 4.2.1-windows pero en tio (Octave 4.0.3) no funciona.

Crea índices numéricos de elementos consecutivos e indexa la cadena por él.

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

C (GCC en POSIX), 67 66 63 bytes

-3 bytes gracias a @LeakyNun!

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

Pruébalo en línea!

Betseg
fuente
No creo que lo necesites j=0.
Leaky Nun
@LeakyNun la función debe ser reutilizable. Pruébalo en línea! vs Pruébalo en línea!
betseg
Aunque si hago esto ...
betseg
1
Puede reemplazar j+i<=strlen(s)con solos[j+i]
Kritixi Lithos
5

Brachylog , 3 bytes

s₎ᶠ

Pruébalo en línea!

Especificaciones:

  • Entrada: ["ATCGAAGGTCGT",4]
  • Argumento: Z
  • Salida: Z = ["ATCG","TCGA","CGAA","GAAG","AAGG","AGGT","GGTC","GTCG","TCGT"]

Cómo funciona

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

Python 3 ,  47 45 42 bytes

-3 bytes gracias a los ovs (use el desempaquetado de Python 3 para reutilizar a[n-1:]en la cola).

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

Una función recursiva que toma la cadena, ay la longitud de la porción n, y devuelve una lista de las rebanadas o una cadena vacía.

a[n-1:]toma una rebanada de la cadena actual de la n-1 ésimo (0 indexados) elemento hacia adelante a prueba si hay elementos suficientes restante (una cadena vacía es Falsey en Python) - esto es más corto que el equivalente len(a)>=n.

  • Si hay suficientes elementos, se construye una lista [...], con los primeros nelementos de la cadena,a[:n] y el resultado desempaquetado de llamada de la función, *f(...)con una versión quitado de la cola de la entrada actual (sin el primer elemento), a[1:].

  • Si no hay suficientes elementos, se alcanza la cola de la recursividad cuando a[n-1:] se devuelve (en este caso, una cadena vacía).

Pruébalo en línea!


45 para Python 2 o 3 con:

f=lambda a,n:a[n-1:]and[a[:n]]+f(a[1:],n)or[]
Jonathan Allan
fuente
f=lambda a,n:a[n-1:]and[a[:n],*f(a[1:],n)]para 42 bytes (Python 3) TIO
ovs
@ovs, muy bien, he preguntado si esto es aceptable (ya que el resultado vacío es una cadena, mientras que el resultado no vacío es una lista).
Jonathan Allan
4

J , 2 bytes

,\

No es un programa completo, sino una función con un operador.

Llámalo como tal:

echo 4 ,\ 'ATCGAAGGTCGT'

Pruébalo en línea!

Cómo funciona

El operador (llamado "conjunción") \(llamado " infijo ") se usa como tal:

(x u\ y)aplica el verbo ua partes sucesivas de la lista y(llamadas infijos).

La función (llamada "verbo") uen este caso es la función ,que es una simple función " agregar ":

Crea una matriz que contiene los elementos de xseguido de los elementos de y.

Monja permeable
fuente
3

Mathematica, 21 bytes

##~StringPartition~1&

Función anónima. Toma una cadena y un número (en ese orden) como entrada y devuelve una lista de cadenas como salida.

LegionMammal978
fuente
3

R, 65 61 bytes

-2 bytes gracias a MickyT

-2 bytes cambiando la indexación

devuelve una función anónima

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

substringrealiza un ciclo a través de los índices (a diferencia de los substrque no lo hacen), y si el índice inicial es menor que 1, su valor predeterminado es 1, por lo tanto, comprueba y devuelve la cadena vacía.

x:n-n+1es equivalente a 1:(x-n+1)ya que :tiene prioridad sobre sumas / diferencias

Pruébalo en línea!

Giuseppe
fuente
puedes guardar un par de bytes con function(s,n,x=nchar(s))if(n>x,'',substring(s,1:(x-n+1),n:x))
MickyT
@MickyT, gracias! También noté que podía soltar algunos bytes cambiando el cálculo del índice
Giuseppe,
2

Pyth , 2 bytes

.:

No es un programa completo, sino una función incorporada.

Llámalo como tal:

.:"ATCGAAGGTCGT"4

Pruébalo en línea!

Programa completo:

.:.*

Pruébalo en línea!

(El .*es splat.)

Monja permeable
fuente
Si bien realmente no importa, .:Fes un byte más corto para el programa completo.
FryAmTheEggman
2

Medusa , 7 bytes

p
_I
\i

Pruébalo en línea!

Cómo funciona

En lineal:, p(\(I,i))donde pse imprime y \obtiene las subcadenas requeridas.

Ies la primera entrada sin procesar mientras que ies la segunda entrada evaluada.

En Jellyfish, cada función y operador obtiene dos argumentos, uno desde la derecha y otro desde la parte inferior. Aquí, la función pobtiene el argumento de la salida de _, que es necesaria si vamos a usar el operador \para obtener subcadenas.

Monja permeable
fuente
2

Clojure, 19 bytes

Bueno, esto es útil:

#(partition % 1 %2)

Ejemplos:

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

CJam , 4 bytes

{ew}

Bloque anónimo que espera los argumentos en la pila y deja el resultado en la pila después.

Pruébalo en línea!

ew es una función integrada que hace exactamente lo que se requiere.

Gato de negocios
fuente
55
Solo tengo una cosa que decir: ew
Adám
2

Retina , 41 38 bytes

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

Pruébalo en línea!

Toma la cuerda y cuenta con líneas separadas. Las dos primeras líneas se utilizan para convertir el recuento de decimal a unario, por lo que si la entrada unaria es aceptable, el recuento de bytes se reducirá a 34 31. Editar: Guardado 3 bytes gracias a @FryAmTheEggman. O, si lo prefiere, una versión de 48 bytes que maneja nuevas líneas en la cadena, aunque eso produce resultados confusos:

.*$
$*
!&`(\S|\s)+(?=[\S\s]*¶(?<-1>.)+(?(1)$.)$)
Neil
fuente
@KritixiLithos No veo cómo su solución tiene en cuenta el recuento ...
Neil
Oh, lo siento, solo tuve un pedo cerebral> _ <
Kritixi Lithos
Esto no funciona necesariamente si la cadena puede contener una nueva línea, por lo que creo que puede cambiar (?!)a .
FryAmTheEggman
2

Octava con paquete de imágenes, 29 bytes

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

Pruébalo en línea!

Explicación

La función im2col(m,b)toma una matriz m, extrae bloques de tamaño bde ella y los organiza como columnas. Por defecto, los bloques son deslizantes (en oposición a distintos). Aquí la matriz mes un vector de fila de los códigos ASCII de la cadena de entrada s(esto se hace como +s, que es más corto que el estándar double(s)), y el tamaño bes [1 n]para obtener bloques de nelementos deslizantes horizontalmente .

El resultado se transpone (usando la transposición de conjugado complejo ', que es más corta que la transposición .') para convertir las columnas en filas, y luego se convierte de nuevo en char ( [... '']que es más corto que el estándar char(...)).

Luis Mendo
fuente
1

Python 3 , 49 bytes

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

Pruébalo en línea!

Una solución no recursiva, aunque no más corta.

Compatible con Python 2.

Monja permeable
fuente
Puede soltar f=, ahorrando dos bytes, porque no los usa en fningún otro lugar. Por defecto, las funciones que se declaran y no se pueden usar pueden dejarse sin nombre.
Sr. Xcoder
1

PHP, 75 bytes

Versión en línea

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

80 bytes sin valores dobles

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

Haskell, 39 bytes

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

Ejemplo de uso: 4 # "ABCDEF"-> ["ABCD","BCDE","CDEF"].Pruébalo en línea!

Una recursión simple que mantiene los primeros ncaracteres de la cadena de entrada y continúa con la cola de la cadena siempre que su longitud no sea menor que n.

nimi
fuente
1

Servidor SQL de Microsoft, 199 bytes

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

Revisalo.

Andrei Odegov
fuente
1

PowerShell, 70 bytes

$b={$c,$s=$args;[regex]::matches($s,"(?=(.{$c}))")|%{''+$_.groups[1]}}

Pruébalo en línea!

Andrei Odegov
fuente
1

Apilado , 7 bytes

infixes

Pruébalo en línea!

Bastante estándar Sin este incorporado, se convierte en 20 bytes:

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

Cual es:

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

MATL , 3 bytes

YC!

Pruébalo en línea!

Explicación

YC   % Sliding blocks of input string with input size, arranged as columns
!    % Transpose
Luis Mendo
fuente
1

C # 89 bytes

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

Pruébalo en línea!

El mejor método que pude encontrar en C # es básicamente el mismo que Java

Skidsdev
fuente
1

Ruby, 48 46 bytes

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

No hay trucos particulares, solo un stabby-lambda que define una función que extrae la subcadena requerida de cada punto de partida válido.

Se guardaron dos bytes, ya que no parece ser necesario almacenar el lambda.

Chowlett
fuente
1

V , 16 bytes

òÀ|ly0Ïp
"_xòkVp

Me temo que no está muy bien golfizado, luchando con "eliminar la cadena si k> len (str)". La entrada está en el archivo, k es un argumento. Golf antes de la explicación

Pruébalo en línea!

nmjcman101
fuente
¿Qué sucede si no intenta manejar el caso k> len (str)?
Adám
Dependiendo del método que use (en este caso en particular) simplemente deja la cadena como está
nmjcman101
1

ML estándar (mosml), 109 65 61 bytes

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

Toma un número y una lista de caracteres (una alternativa bastante común a las cadenas en el mundo SML). (Realmente funciona en todas las listas, por supuesto).

Uso:

- 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

Registro de cambios:

  • Correcto, hay una biblioteca estándar ... (-44 bytes)
  • Cambie la comparación y nula a [] como se sugiere (-4 bytes)
L3viatán
fuente
1
Puede guardar un byte cambiando if length(x)<n thena if n>length(x)then. Sin embargo, como es perfectamente posible que SML maneje cadenas, no estoy seguro de que se requiera explodeque ya se aplique a la cadena de entrada.
Laikoni
También then nil elsese puede acortar a then[]else.
Laikoni
@Laikoni tampoco está seguro, pero ¯ \ _ (ツ) _ / ¯
L3viathan
Usando algunas otras funciones de la biblioteca, obtuve una versión de 68 bytes que trata con cadenas en lugar de listas de caracteres. También su enfoque puede ser acortado a 54 bytes: fun f$n=if n>length$then[]else List.take($,n)::f(tl$)n.
Laikoni
1

JavaScript (Firefox 30-57), 51 bytes

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

64 bytes en ES6:

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