Однажды мне нужно было написать функцию, которая вычисляет энтропию блоков для данной серии символов для данного размера блока, и был удивлен, насколько коротким был результат. Таким образом, я призываю вас кодировать такую функцию. Я не скажу вам, что я сделал сейчас (и на каком языке), но я сделаю это через неделю или около того, если никто не придумал те же или лучшие идеи в первую очередь.
Определение блока энтропии:
Для данной последовательности символов A = A_1,…, A_n и размера блока m:
- Блок размером m является сегментом из m последовательных элементов последовательности символов, то есть A_i,…, A_ (i + m − 1) для любого подходящего i.
- Если x является символьной последовательностью размера m, N (x) обозначает количество блоков A, которые идентичны x.
- p (x) - вероятность того, что блок из A идентичен последовательности символов x размера m, т. е. p (x) = N (x) / (n − m + 1)
- Наконец, энтропия блока для размера блока m из A является средним значением -log (p (x)) по всем блокам x размера m в A или (что эквивалентно) сумме -p (x) · log (p) (x)) по каждому x размера m, встречающемуся в A. (Вы можете выбрать любой разумный логарифм, который хотите.)
Ограничения и уточнения:
- Ваша функция должна принимать последовательность символов A, а также размер блока m в качестве аргумента.
- Вы можете предположить, что символы представлены как целые числа, начинающиеся с нуля, или в другом удобном формате.
- Ваша программа должна быть способна принимать любые разумные аргументы в теории и в действительности должна быть способна рассчитать пример (см. Ниже) на стандартном компьютере.
- Разрешены встроенные функции и библиотеки, если они не выполняют большие части процедуры за один вызов, то есть извлекают все блоки размером m из A, подсчитывают количество вхождений данного блока x или вычисляют энтропии. из последовательности значений р - вы должны сделать эти вещи самостоятельно.
Тестовое задание:
[2, 3, 4, 1, 2, 3, 0, 0, 3, 2, 3, 0, 2, 2, 4, 4, 4, 1, 1, 1, 0, 4, 1,
2, 2, 4, 0, 1, 2, 3, 0, 2, 3, 2, 3, 2, 0, 1, 3, 4, 4, 0, 2, 1, 4, 3,
0, 2, 4, 1, 0, 4, 0, 0, 2, 2, 0, 2, 3, 0, 0, 4, 4, 2, 3, 1, 3, 1, 1,
3, 1, 3, 1, 0, 0, 2, 2, 4, 0, 3, 2, 2, 3, 0, 3, 3, 0, 0, 4, 4, 1, 0,
2, 3, 0, 0, 1, 4, 4, 3]
Первые блок-энтропии этой последовательности (для натурального логарифма):
- м = 1: 1,599
- м = 2: 3,065
- м = 3: 4,067
- м = 4: 4,412
- m = 5: 4,535
- м = 6: 4,554
entropy(probabilities(blocks(A,m)))
.Ответы:
Mathematica -
8178757267656256 байтЯ ничего не играл в Mathematica раньше, поэтому я полагаю, что есть возможности для улучшения. Это один не вполне соответствуют правилам из - за
Partition
иTally
функции, но это довольно опрятно , поэтому я думал , что я отправлю его в любом случае.Это работает с любым набором символов и может использоваться как
Вот несколько нелепая версия:
Это, вероятно, будет работать быстрее, если я применю
N
непосредственно к результатуTally
.Кстати, у Mathematica действительно есть
Entropy
функция, которая уменьшает ее до 28 байт , но это определенно противоречит правилам.С другой стороны, вот 128-байтовая версия, которая переопределяет
Partition
иTally
:Ungolfed:
источник
Partition
иTally
не являются пограничными случаями, они прямо нарушают правила, поскольку они «извлекают все блоки размера m из A» и «подсчитывают количество вхождений данного блока x», соответственно, в одном вызове. Тем не менее, после всего, что я знаю о Mathematica, я не удивлюсь, если бы без них было достойное решение.Partition
иTally
.Perl, 140 байт
Следующий скрипт Perl определяет функцию,
E
которая принимает последовательность символов, за которой следует размер сегмента в качестве аргументов.Неуправляемая версия с тестом
Результат:
Условные обозначения:
Символы не ограничиваются целыми числами, потому что используется сопоставление с образцом на основе строк. Строковое представление символа не должно содержать запятую, поскольку оно используется в качестве разделителя. Разные символы должны иметь разные строковые представления.
В версии для гольфа строковое представление символов не должно содержать специальных символов шаблонов. Дополнительные четыре байта
\Q
...\E
не нужны для чисел.источник
sub f{($s,$m,$r,%h)=@_;$h{x,@$s[$_..$_+$m-1]}++for 0..@$s-$m;$r-=($_/=@$s-$m+1)*log for values %h;return$r}
; где$s
- ссылка$r
и%h
сбрасываются на undef с 1-м присваиванием, списки - это хэш-ключи (с небольшой помощью$;
, а некоторыеx
- к сожалению), и, как мне кажется, они немного менее сложны.values %h
не требуется, поэтому вашему решению нужно всего лишь 106 байтов.Python
127152B 138BС поправкой на то, чтобы больше не нарушать правила и иметь немного более симпатичный алгоритм. Скорректировано, чтобы быть меньше
Старая версия:
Мой первый скрипт Python! Посмотрите это в действии: http://pythonfiddle.com/entropy
источник
count
функции прямо противоречит правилам, поскольку она «считает количество вхождений данного блока x».;
при необходимости). Также квадратные скобки в последней строке не нужны.and 1 or 0
. Кроме того, вы можете сохранить некоторые символы, предварительно определивrange(N)
.Питон с Numpy,
146143 байтаКак и было обещано, вот мое собственное решение. Требуется ввод неотрицательных целых чисел:
Недостатком является то, что это разрывает вашу память на большой
m
илиmax(A)
.Вот в основном версия без комментариев и комментариев:
источник
MATLAB
источник