Uma vez eu precisei escrever uma função que calcula a entropia de bloco de uma determinada série de símbolos para um determinado tamanho de bloco e fiquei surpreso com o quão curto o resultado foi. Portanto, estou desafiando você a codificar essa função. Não estou lhe dizendo o que fiz por enquanto (e em que idioma), mas falarei daqui a uma semana, se ninguém tiver as mesmas ou melhores idéias primeiro.
Definição da entropia do bloco:
Dada uma sequência de símbolos A = A_1,…, A_n e um tamanho de bloco m:
- Um bloco de tamanho m é um segmento de m elementos consecutivos da sequência de símbolos, ou seja, A_i,…, A_ (i + m-1) para qualquer i apropriado.
- Se x é uma sequência de símbolos de tamanho m, N (x) indica o número de blocos de A que são idênticos a x.
- p (x) é a probabilidade de um bloco de A ser idêntico a uma sequência de símbolos x de tamanho m, ou seja, p (x) = N (x) / (n − m + 1)
- Finalmente, a entropia de bloco para o tamanho do bloco m de A é a média do log (p (x)) sobre todos os blocos x do tamanho m em A ou (o que é equivalente) a soma de -p (x) · log (p (x)) em cada x de tamanho m ocorrendo em A. (Você pode escolher qualquer logaritmo razoável que desejar.)
Restrições e esclarecimentos:
- Sua função deve usar a sequência de símbolos A e o tamanho do bloco m como argumento.
- Você pode assumir que os símbolos são representados como números inteiros baseados em zero ou em outro formato conveniente.
- Seu programa deve ser capaz de adotar qualquer argumento razoável em teoria e, na realidade, ser capaz de calcular o caso de exemplo (veja abaixo) em um computador padrão.
- Funções e bibliotecas integradas são permitidas, desde que não executem grandes partes do procedimento em uma chamada, ou seja, extraindo todos os blocos de tamanho m de A, contando o número de ocorrências de um determinado bloco x ou calculando as entropias a partir de uma sequência de valores p - você mesmo deve fazer essas coisas.
Teste:
[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]
As primeiras entropias de bloco desta sequência são (para o logaritmo natural):
- m = 1: 1.599
- m = 2: 3,065
- m = 3: 4,067
- m = 4: 4,412
- m = 5: 4.535
- m = 6: 4.554
entropy(probabilities(blocks(A,m)))
.Respostas:
Mathematica -
8178757267656256 bytesEu nunca joguei nada no Mathematica antes, então acho que há espaço para melhorias. Este não está de acordo com as regras devido às funções
Partition
eTally
, mas é bem legal, então pensei em publicá-lo de qualquer maneira.Isso funciona com qualquer conjunto de símbolos e pode ser usado como
Aqui está uma versão um pouco não-destruída:
Provavelmente funcionará mais rápido se eu aplicar
N
diretamente ao resultado deTally
.A propósito, o Mathematica realmente tem uma
Entropy
função, que reduz isso para 28 bytes , mas isso definitivamente é contra as regras.Por outro lado, aqui está uma versão de 128 bytes que reimplementa
Partition
eTally
:Ungolfed:
fonte
Partition
eTally
não são casos limítrofes, eles estão violando as regras, pois estão “extraindo todos os blocos de tamanho m de A” e “contando o número de ocorrências de um determinado bloco x”, respectivamente, em uma chamada. Ainda assim, depois de tudo o que sei sobre o Mathematica, não ficaria surpreso se houvesse uma solução decente sem eles.Partition
eTally
.Perl, 140 bytes
O script Perl a seguir define uma função
E
que aceita a sequência de símbolos, seguida pelo tamanho do segmento como argumentos.Versão ungolfed com teste
Resultado:
Símbolos:
Os símbolos não estão restritos a números inteiros, porque a correspondência de padrões com base em seqüências de caracteres é usada. A representação em cadeia de um símbolo não deve conter vírgula, pois é usada como delimitador. Obviamente, símbolos diferentes devem ter representações de cadeias diferentes.
Na versão golfed, a representação em cadeia dos símbolos não deve conter caracteres especiais de padrões. Os quatro bytes adicionais
\Q
...\E
não são necessários para números.fonte
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}
; Onde$s
é uma referência,$r
e%h
são redefinidos para undef com a 1ª atribuição, as listas são chaves de hash (com pouca ajuda$;
e algumasx
- infelizmente), e um pouco menos complicadas em geral, eu acho.values %h
não é necessário; portanto, sua solução precisa apenas de 106 bytes.Python
127 152B138BAjustado para não violar mais as regras e ter um algoritmo um pouco mais bonito. Ajustado para ser menor
Versão antiga:
Meu primeiro script Python! Veja em ação: http://pythonfiddle.com/entropy
fonte
count
função é totalmente contra as regras, pois está "contando o número de ocorrências de um determinado bloco x".;
se necessário). Também não são necessários colchetes na última linha.and 1 or 0
) é desnecessária. Além disso, você pode salvar alguns caracteres predefinindorange(N)
.Python com Numpy,
146143 bytesComo prometido, aqui está minha própria solução. Requer uma entrada de números inteiros não negativos:
A desvantagem é que isso explode sua memória por um grande
m
oumax(A)
.Aqui está a versão mais não comentada e comentada:
fonte
MATLAB
fonte