Todos os k-mers / n-gramas

21

Introdução

Tivemos histogramas e contando , mas não listamos todos eles.

Todos os anos, a Dyalog Ltd. realiza uma competição estudantil. O desafio é escrever um bom código APL. Esta é uma edição de independente de idioma do sexto problema deste ano.

Tenho permissão explícita para postar esse desafio aqui, do autor original da competição. Sinta-se livre para verificar, seguindo o link fornecido e entrando em contato com o autor.

Problema

O termo k-mer geralmente se refere a todas as substrings possíveis de comprimento k que estão contidas em uma sequência. Na genômica computacional, k-mers se referem a todas as subsequências possíveis (de comprimento k ) de uma leitura obtida por meio do seqüenciamento de DNA. Escreva uma função / programa que use uma string ek (o comprimento da substring) e retorne / produza um vetor dos k-mers da string original.

Exemplos

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

k > comprimento da corda? Retornar nada / nenhum resultado vazio:
[4,"AC"][]ou ""ou[""]

Adão
fonte
4
A ordem da saída é importante? Quando uma substring ocorre várias vezes, deve ser repetida na saída?
Feersum
11
Posso retornar uma string das substrings necessárias, separadas por novas linhas, em vez de uma matriz de strings, como esta ?
Leaky Nun
Podemos nós também entrada e saída da string como um array de caracteres (como ['A', 'T', 'C', 'G']em vez de "ATCG"?
Adnan
As respostas do Dyalog APL são permitidas neste desafio do PPCG (porque o desafio também é hospedado pelo Dyalog)?
Kritixi Lithos
11
@feersum A ordem é importante e as repetições devem ser repetidas. É como uma janela deslizante.
Adám

Respostas:

15

Geléia , 1 byte

A geléia possui um átomo diádico de byte único para esta operação

Experimente online! (o rodapé divide a lista resultante com novas linhas, para evitar que uma representação reduzida seja impressa.)

Jonathan Allan
fonte
11
De alguma forma, o OP deve ter sabido ...
Leaky Nun
11
@LeakyNun eu realmente não fiz.
Adám
8

Oitava, 28 bytes

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

Experimente online!

Para k> o comprimento da string funciona no Octave 4.2.1-windows, mas no tio (Octave 4.0.3) não funciona.

Cria índices numéricos de elementos consecutivos e indexa a string por ela.

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

C (GCC no POSIX), 67 66 63 bytes

-3 bytes graças a @LeakyNun!

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

Experimente online!

betseg
fonte
Eu acho que você não precisa j=0.
Leaky Nun
@LeakyNun a função deve ser reutilizável. Experimente online! vs Experimente online!
betseg
Embora se eu fizer isso ...
betseg
11
Você pode substituir j+i<=strlen(s)por apenass[j+i]
Kritixi Lithos 1/17/17
5

Braquilog , 3 bytes

s₎ᶠ

Experimente online!

Especificações:

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

Como funciona

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

Python 3 ,  47 45 42 bytes

-3 bytes graças ao ovs (use a descompactação do Python 3 para reutilizar a[n-1:]na cauda.)

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

Uma função recursiva que pega a sequência, ae o comprimento da fatia n, e retorna uma lista das fatias ou de uma sequência vazia.

a[n-1:]pega uma fatia da string atual do n- ésimo elemento (indexado a 0) para testar se ainda há elementos suficientes (uma string vazia é falsey no Python) - isso é mais curto que o equivalente len(a)>=n.

  • Se houver elementos suficientes, uma lista será construída, [...]com os primeiros nelementos da sequência, a[:n]e o resultado descompactado da chamada da função novamente *f(...), com uma versão em fila da entrada atual (sem o primeiro elemento),a[1:] ,.

  • Se não houver elementos suficientes, a cauda da recursão é alcançada quando a[n-1:]é retornada (neste caso, uma sequência vazia).

Experimente online!


45 para Python 2 ou 3 com:

f=lambda a,n:a[n-1:]and[a[:n]]+f(a[1:],n)or[]
Jonathan Allan
fonte
f=lambda a,n:a[n-1:]and[a[:n],*f(a[1:],n)]para 42 bytes (Python 3) TIO
ovs
@ovs, muito bom, perguntei se isso é aceitável (já que o resultado vazio é uma string, enquanto o resultado não vazio é uma lista).
Jonathan Allan
4

J , 2 bytes

,\

Não é um programa completo, mas uma função com um operador.

Chame assim:

echo 4 ,\ 'ATCGAAGGTCGT'

Experimente online!

Como funciona

O operador (chamado "conjunção") \(denominado " infix ") é usado como tal:

(x u\ y)aplica verbo ua partes sucessivas da lista y(chamadas infixes).

A função (chamada "verbo") unesse caso é a função ,que é uma função simples " anexar ":

Cria uma matriz que contém os itens xseguidos pelos itens de y.

Freira Furada
fonte
3

Mathematica, 21 bytes

##~StringPartition~1&

Função anônima. Pega uma string e um número (nessa ordem) como entrada e retorna uma lista de strings como saída.

LegionMammal978
fonte
3

R, 65 bytes 61

-2 bytes graças ao MickyT

-2 bytes alterando a indexação

retorna uma função anônima.

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

substringalterna entre os índices (ao contrário dos substrque não o fazem) e, se o índice inicial for menor que 1, o padrão será1 , portanto, verifica e retorna a sequência vazia.

x:n-n+1é equivalente a 1:(x-n+1)uma vez que :tem precedência sobre somas / diferenças

Experimente online!

Giuseppe
fonte
você pode salvar alguns bytes com function(s,n,x=nchar(s))if(n>x,'',substring(s,1:(x-n+1),n:x))
MickyT 1/17/17
@MickyT, obrigado! Notei também que eu poderia soltar alguns bytes, alterando o cálculo do índice
Giuseppe
2

Pitão , 2 bytes

.:

Não é um programa completo, mas uma função interna.

Chame assim:

.:"ATCGAAGGTCGT"4

Experimente online!

Programa completo:

.:.*

Experimente online!

(O .*é splat.)

Freira Furada
fonte
Embora isso realmente não importe, .:Fé um byte mais curto para o programa completo.
FryAmTheEggman #
2

Água-viva , 7 bytes

p
_I
\i

Experimente online!

Como funciona

Em linear:, p(\(I,i))onde pé impresso e \obtém as substrings necessárias.

Ié a primeira entrada bruta enquanto ié a segunda entrada avaliada.

No Jellyfish, cada função e operador recebe dois argumentos, um da direita e outro da parte inferior. Aqui, a função pobtém o argumento da saída de _, que é necessária se quisermos usar o operador \para obter substrings.

Freira Furada
fonte
2

Python 2 , 54 bytes

lambda x,n:map(''.join,zip(*[x[b:]for b in range(n)]))

Experimente online!

Adnan
fonte
2

Clojure, 19 bytes

Bem, isso é útil:

#(partition % 1 %2)

Exemplos:

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

CJam , 4 bytes

{ew}

Bloco anônimo que espera os argumentos na pilha e deixa o resultado na pilha depois.

Experimente online!

ew é um built-in que faz exatamente o que é necessário.

Gato de negócios
fonte
5
Só tenho uma coisa a dizer: ew
Adám
2

Retina , 41 38 bytes

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

Experimente online!

Pega a corda e conta em linhas separadas. As duas primeiras linhas são usadas para converter a contagem de decimal para unária; portanto, se a entrada unária for aceitável, a contagem de bytes será reduzida para 34 31. Edit: Salvo 3 bytes graças a @FryAmTheEggman. Ou, se preferir, uma versão de 48 bytes que lida com novas linhas na string, embora isso produza resultados confusos:

.*$
$*
!&`(\S|\s)+(?=[\S\s]*¶(?<-1>.)+(?(1)$.)$)
Neil
fonte
@KritixiLithos Não vejo como sua solução toma a contagem em conta ...
Neil
Oh, desculpe, eu só tinha um peido de cérebro> _ <
Kritixi Lithos
Isso não funciona necessariamente se a string pode conter uma nova linha, então acho que você pode mudar (?!)para .
FryAmTheEggman
2

Oitava com pacote de imagens, 29 bytes

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

Experimente online!

Explicação

A função im2col(m,b)pega uma matriz m, extrai blocos de tamanho bdela e os organiza como colunas. Por padrão, os blocos são deslizantes (em oposição a distintos). Aqui a matriz mé um vetor de linha dos códigos ASCII da sequência de entrada s(isso é feito como +s, que é mais curto que o padrão double(s)), e o tamanho bé [1 n]obter blocos deslizantes horizontalmente den elementos .

O resultado é transposto (usando a transposição conjugada complexa ', que é mais curta que a transposta .') para transformar as colunas em linhas e depois é convertida novamente em char ( [... '']que é mais curto que o padrão char(...)).

Luis Mendo
fonte
2

OK, 2 bytes

':

oK tem um operador de janela deslizante !

zgrep
fonte
1

Python 3 , 49 bytes

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

Experimente online!

Uma solução não recursiva, embora não menor.

Compatível com Python 2.

Freira Furada
fonte
Você pode soltar f=, salvando dois bytes, porque você não usa em fnenhum outro lugar. Por padrão, as funções que acabam de ser declaradas e não usadas podem ser deixadas sem nome.
Sr. Xcoder
1

PHP, 75 bytes

Versão Online

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

80 bytes sem valores duplos

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

Haskell, 39 bytes

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

Exemplo de uso: 4 # "ABCDEF"-> ["ABCD","BCDE","CDEF"]. Experimente online!

Uma recursão simples que mantém os primeiros ncaracteres da string de entrada e continua com a cauda da string desde que seu comprimento não seja menor que n.

nimi
fonte
1

Microsoft Sql Server, 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

Verifique-o.

Andrei Odegov
fonte
1

PowerShell, 70 bytes

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

Experimente online!

Andrei Odegov
fonte
1

Empilhados , 7 bytes

infixes

Experimente online!

Bastante padrão. Sem esse built-in, ele se torna 20 bytes:

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

Qual é:

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

MATL , 3 bytes

YC!

Experimente online!

Explicação

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

Bytes C # 89

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

Experimente online!

O melhor método que eu poderia encontrar em C # é basicamente o mesmo que Java

Skidsdev
fonte
1

Ruby, 48 46 bytes

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

Não há truques específicos, apenas um stabby-lambda que define uma função que extrai a substring necessária de cada ponto de partida válido.

Salva dois bytes, já que não parece haver necessidade de armazenar o lambda.

Chowlett
fonte
1

V , 16 bytes

òÀ|ly0Ïp
"_xòkVp

Receio que não seja muito bem jogado, lutando com "exclua a string se k> len (str)". A entrada está no arquivo, k é um argumento. Golfe antes da explicação

Experimente online!

nmjcman101
fonte
O que acontece se você não tentar lidar com o caso k> len (str)?
Adám 2/17/17
Dependendo do uso do método I (em um presente, em particular) que só deixa a cadeia como é
nmjcman101
1

ML padrão (mosml), 109 65 61 bytes

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

Leva um número e uma lista de caracteres (uma alternativa bastante comum para seqüências de caracteres no mundo SML). (Realmente funciona em todas as listas, é claro.)

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

Changelog:

  • Certo, existe uma biblioteca padrão .. (-44 bytes)
  • Altere a comparação e nulo para [] conforme sugerido (-4 bytes)
L3viathan
fonte
11
Você pode salvar um byte, alterando if length(x)<n thenpara if n>length(x)then. No entanto, como é perfeitamente possível para o SML manipular seqüências de caracteres, não tenho certeza se é permitido que explodeele já seja aplicado à sequência de entrada.
Laikoni
Também then nil elsepode ser reduzido para then[]else.
Laikoni
@Laikoni não tenho certeza qualquer um, mas ¯ \ _ (ツ) _ / ¯
L3viathan
Usando algumas outras funções da biblioteca, obtive uma versão de 68 bytes que lida com seqüências de caracteres em vez de listas de caracteres. Também a sua abordagem pode ser encurtado para 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 no ES6:

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