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.