Всі k-mers / n-грам


21

Вступ

У нас були гістограми та підраховувались , але не перелічуючи їх усіх.

Щорічно ТОВ «Діялог» проводить конкурс студентів. Завдання полягає в тому, щоб написати хороший APL-код. Це мовний агностичний видання шостої цьогорічної проблеми.

Я маю чіткий дозвіл на публікацію цього виклику тут від оригінального автора конкурсу. Не соромтеся перевіряти, перейшовши за посиланням та зв’язавшись з автором.

Проблема

Термін k-mer зазвичай відноситься до всіх можливих підрядків довжиною k , які містяться в рядку. У обчислювальній геноміці k-mers посилаються на всі можливі послідовності (довжини k ) з читання, отриманого за допомогою секвенування ДНК. Напишіть функцію / програму, яка приймає рядок і k (довжина підрядки) і повертає / виводить вектор k-mers початкового рядка.

Приклади

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

k > довжина рядка? Повернути нічого / будь-який порожній результат:
[4,"AC"][]або ""або[""]


4
Чи має значення порядок виводу? Коли підрядка виникає кілька разів, чи слід це повторювати у висновку?
feersum

1
Чи можу я повернути рядок необхідних підрядів, розділених новими рядками замість масиву рядків, як це ?
Leaky Nun

Чи можемо ми також вводити та виводити рядок у вигляді масиву символів (наприклад, ['A', 'T', 'C', 'G']замість "ATCG"?
Аднан

Чи дозволені відповіді Dyalog APL у цьому виклику PPCG (оскільки виклик також приймає Dyalog)?
Kritixi Lithos

1
@feersum Порядок має значення, і повтори слід повторити. Це просто як розсувне вікно.
Адам

Відповіді:


15

Желе , 1 байт

Для цієї операції желе має єдиний байтовий діадний атом

Спробуйте в Інтернеті! (Нижній колонтитул розбиває отриманий список новими рядками, щоб уникнути друку мушкетного зображення.)


1
Якось ОП, мабуть, знало ...
Лина монашка

1
@LeakyNun я насправді цього не зробив.
Адам

8

Октава, 28 байт

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

Спробуйте в Інтернеті!

Для k> довжина рядків працює в Windows Octave 4.2.1, але в tio (Octave 4.0.3) не працює.

Створює числові індекси послідовних елементів та індексує рядок ним.

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


7

C (GCC на POSIX), 67 66 63 байт

-3 байти завдяки @LeakyNun!

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

Спробуйте в Інтернеті!


Я не думаю, що вам це потрібно j=0.
Лина монашка

@LeakyNun функція повинна бути багаторазовою. Спробуйте в Інтернеті! vs Спробуйте в Інтернеті!
betseg

Хоча якщо я це зроблю ...
betseg

1
Ви можете замінити j+i<=strlen(s)простоs[j+i]
Kritixi Lithos


5

Пітон 3 ,  47 45 42 байт

-3 байти завдяки ovs (використовуйте розпакування Python 3 для повторного використання a[n-1:] в хвості.)

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

Рекурсивна функція, що приймає рядок, a і довжину фрагмента n, і повертає список фрагментів або порожній рядок.

a[n-1:]бере зріз поточної струни від n-1- го (0-індексованого) елемента вперед, щоб перевірити, чи залишилось достатньо елементів (порожній рядок - фальси в Python) - це коротше, ніж еквівалент len(a)>=n.

  • Якщо елементів достатньо, складається список [...]із першими nелементами рядка a[:n]та розпакованим результатом повторного виклику функції,*f(...) з версією з черги на вхід струму (без першого елемента), a[1:].

  • Якщо елементів недостатньо, хід рекурсії досягається при a[n-1:]поверненні (у цьому випадку порожній рядок).

Спробуйте в Інтернеті!


45 для Python 2 або 3 з:

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)]за 42 байти (Python 3) TIO
ов

@ovs, дуже приємно, я запитав, чи це прийнятно (оскільки вони порожній результат - це рядок, тоді як не порожній результат - список).
Джонатан Аллан

4

J , 2 байти

,\

Це не повна програма, а функція з оператором.

Назвіть це як таке:

echo 4 ,\ 'ATCGAAGGTCGT'

Спробуйте в Інтернеті!

Як це працює

Оператор (званий "з'єднання") \(з назвою " інфікс ") використовується як такий:

(x u\ y)застосовує дієслово uдо послідовних частин списку y(званих infixes).

Функція (називається "дієсловом") uу цьому випадку є функцією, ,яка є простою функцією " додавання ":

Створює масив, що містить елементи, за якими xслідують елементи y.


3

Математика, 21 байт

##~StringPartition~1&

Анонімна функція. Бере рядок та число (у такому порядку) як вхідні та повертає список рядків як вихідний.


3

R, 65 61 байт

-2 байти завдяки MickyT

-2 байти, змінивши індексацію

повертає анонімну функцію.

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

substringцикли через індекси (на відміну від substrяких немає), і якщо стартовий індекс менше 1, він за замовчуванням до1 замість , тому він перевіряє та повертає порожній рядок.

x:n-n+1еквівалентний з 1:(x-n+1)тих пір: має перевагу над сумами / різницями

Спробуйте в Інтернеті!


ви можете зберегти пару байтів, function(s,n,x=nchar(s))якщо(n>x,'',substring(s,1:(x-n+1),n:x))
MickyT

@MickyT, дякую! Я також помітив, що міг скинути кілька байт, змінивши обчислення індексу
Джузеппе


2

Медузи , 7 байт

p
_I
\i

Спробуйте в Інтернеті!

Як це працює

У лінійному:, p(\(I,i))де pє print і \отримує необхідні підрядки.

I- це перший необроблений вхід, тоді iяк оцінюється другий вхід.

У медуз кожна функція та оператор отримує два аргументи, один справа, а другий знизу. Тут функція pотримує аргумент з виводу _, який необхідний, якщо ми хочемо використовувати оператор \для отримання підрядків.




2

Clojure, 19 байт

Ну це зручно:

#(partition % 1 %2)

Приклади:

(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

Сітківка , 41 38 байт

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

Спробуйте в Інтернеті!

Бере рядок і рахує окремими рядками. Перші два рядки використовуються для перетворення підрахунку від десяткових до одинарних, тож якщо прийнято одинарне введення, кількість байтів буде зменшено до 34 31. Редагувати: Збережено 3 байти завдяки @FryAmTheEggman. Або, якщо ви віддаєте перевагу, 48-байтну версію, яка обробляє нові рядки в рядку, хоча це і дає заплутаний вихід:

.*$
$*
!&`(\S|\s)+(?=[\S\s]*¶(?<-1>.)+(?(1)$.)$)

@KritixiLithos Я не бачу, як ваше рішення враховує ...
Ніл

О, вибачте, що у мене просто прийшов мозковий приступ> _ <
Kritixi Lithos

Це не обов'язково буде працювати , якщо рядок може містити символ нового рядка, так що я думаю , що ви можете змінити (?!)в .
FryAmTheEggman

2

Октава з пакетом зображень, 29 байт

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

Спробуйте в Інтернеті!

Пояснення

Функція im2col(m,b)приймає матрицю m, витягує bз неї блоки розмірів і впорядковує їх як стовпці. За замовчуванням блоки ковзають (на відміну від окремих). Тут матриця mє вектором рядків ASCII-кодів вхідного рядка s(це робиться як +s, який коротший, ніж у стандартного double(s)), а розмір b- [1 n]для отримання горизонтально розсувних блоківn елементів.

Результат транспонується (використовуючи складний кон'югат транспозиції ', який коротше транспозиції .') для перетворення стовпців у рядки, а потім перетворюється назад у char ( [... '']що коротше стандартного char(...)).



1

Python 3 , 49 байт

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

Спробуйте в Інтернеті!

Нерекурсивний розчин, хоча і не коротший.

Сумісний з Python 2.


Можна скинути f=, заощадивши два байти, тому що ви більше fніде не використовуєте . За замовчуванням функції, які щойно оголошені та не використовуються, можна залишити без назви.
Містер Xcoder


1

Хаскелл, 39 байт

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

Приклад використання: 4 # "ABCDEF"-> ["ABCD","BCDE","CDEF"]. Спробуйте в Інтернеті!

Проста рекурсія, яка зберігає перші nсимволи вхідного рядка a, продовжується хвостом рядка до тих пір, поки його довжина не буде меншою n.


1

Сервер Microsoft Sql, 199 байт

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

Перевір це.






1

Рубі, 48 46 байт

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

Ніяких особливих хитрощів, лише стабільна лямбда, що визначає функцію, яка витягує необхідну підрядку з кожної дійсної вихідної точки.

Збережено два байти, оскільки, схоже, не потрібно зберігати лямбда.


1

V , 16 байт

òÀ|ly0Ïp
"_xòkVp

Боюсь, не дуже добре гольф, боюся з "видалити рядок, якщо k> len (str)". Вхід у файл, k - аргумент. Гольф перед поясненням

Спробуйте в Інтернеті!


Що станеться, якщо ви не спробуєте впоратися із випадком k> len (str)?
Адам

Залежно від методу, який я використовую (зокрема в цьому), він просто залишає рядок як є
nmjcman101

1

Стандартний ML (mosml), 109 65 61 байт

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

Бере число та список символів (досить поширена альтернатива рядків у світі SML). (Дійсно працює у всіх списках, звичайно.)

Використання:

- 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

Журнал змін:

  • Правильно, є стандартна бібліотека .. (-44 байта)
  • Змініть порівняння та нуль на [], як було запропоновано (-4 байти)

1
Ви можете зберегти байт, перейшовши if length(x)<n thenна if n>length(x)then. Однак, оскільки для SML цілком можливо обробити рядки, я не впевнений, що дозволено вимагати explodeзастосування вже до вхідного рядка.
Лайконі

Також then nil elseможна скоротити до then[]else.
Лайконі

@Laikoni теж не впевнений, але ¯ \ _ (ツ) _ / ¯
L3viathan

Використовуючи деякі інші функції бібліотеки, я отримав 68-байтну версію, яка стосується рядків замість списків char. Крім того, ваш підхід може бути скорочений до 54 байт: fun f$n=if n>length$then[]else List.take($,n)::f(tl$)n.
Лайконі

1

JavaScript (Firefox 30-57), 51 байт

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

64 байти в ES6:

(s,n,t=s.slice(0,--n))=>[...s.slice(n)].map(c=>(t+=c).slice(~n))
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.