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


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


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



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.

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

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.


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.


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!


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

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




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


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

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



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.


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

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.


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.



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


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


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.


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!


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)

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))
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.