Una vez necesitaba escribir una función que calcule la entropía de bloques de una serie de símbolos dada para un tamaño de bloque dado y me sorprendió lo corto que fue el resultado. Por lo tanto, te desafío a codegolf tal función. No te estoy diciendo lo que hice por ahora (y en qué idioma), pero lo haré en una semana más o menos, si a nadie se le ocurrieron las mismas o mejores ideas primero.
Definición de la entropía de bloque:
Dada una secuencia de símbolos A = A_1, ..., A_n y un tamaño de bloque m:
- Un bloque de tamaño m es un segmento de m elementos consecutivos de la secuencia de símbolos, es decir, A_i, ..., A_ (i + m − 1) para cualquier i apropiado.
- Si x es una secuencia de símbolos de tamaño m, N (x) indica el número de bloques de A que son idénticos a x.
- p (x) es la probabilidad de que un bloque de A sea idéntico a una secuencia de símbolos x de tamaño m, es decir, p (x) = N (x) / (n − m + 1)
- Finalmente, la entropía de bloque para el tamaño de bloque m de A es el promedio de −log (p (x)) sobre todos los bloques x de tamaño m en A o (que es equivalente) la suma de −p (x) · log (p (x)) sobre cada x de tamaño m que ocurre en A. (Puede elegir cualquier logaritmo razonable que desee).
Restricciones y aclaraciones:
- Su función debe tomar la secuencia de símbolos A, así como el tamaño de bloque m como argumento.
- Puede suponer que los símbolos se representan como enteros basados en cero o en otro formato conveniente.
- Su programa debería ser capaz de tomar cualquier argumento razonable en teoría y en realidad debería ser capaz de calcular el caso de ejemplo (ver más abajo) en una computadora estándar.
- Las funciones y bibliotecas incorporadas están permitidas, siempre que no realicen grandes porciones del procedimiento en una llamada, es decir, extraigan todos los bloques de tamaño m de A, contando el número de ocurrencias de un bloque dado x o calculando las entropías a partir de una secuencia de valores p: tienes que hacer esas cosas tú mismo.
Prueba:
[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]
Las primeras entropías de bloque de esta secuencia son (para el 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)))
.Respuestas:
Mathematica -
8178757267656256 bytesNo he jugado golf en Mathematica antes, así que supongo que hay margen de mejora. Este no se ajusta a las reglas debido a las funciones
Partition
yTally
, pero es bastante bueno, así que pensé en publicarlo de todos modos.Esto funciona con cualquier conjunto de símbolos, y puede usarse como
Aquí hay una versión un tanto descuidada:
Probablemente se ejecutará más rápido si aplico
N
directamente al resultado deTally
.Por cierto, Mathematica realmente tiene una
Entropy
función, que reduce esto a 28 bytes , pero eso definitivamente va en contra de las reglas.Por otro lado, aquí hay una versión de 128 bytes que se vuelve a implementar
Partition
yTally
:Sin golf:
fuente
Partition
yTally
no son casos límite, están rompiendo las reglas directamente, ya que están "extrayendo todos los bloques de tamaño m de A" y "contando el número de ocurrencias de un bloque dado x", respectivamente, en una llamada. Aún así, después de todo lo que sé sobre Mathematica, no me sorprendería si hubiera una solución decente sin ellos.Partition
yTally
.Perl, 140 bytes
El siguiente script de Perl define una función
E
que toma la secuencia de símbolos, seguida del tamaño del segmento como argumentos.Versión sin golf con prueba
Resultado:
Símbolos:
Los símbolos no están restringidos a enteros, porque se usa la coincidencia de patrones basada en cadenas. La representación de cadena de un símbolo no debe contener la coma, ya que se utiliza como delimitador. Por supuesto, diferentes símbolos deben tener diferentes representaciones de cadena.
En la versión de golf, la representación de cadena de los símbolos no debe contener caracteres especiales de patrones. Los cuatro bytes adicionales
\Q
...\E
no son necesarios para los números.fuente
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}
; donde$s
es una referencia,$r
y%h
se restablecen a undef con la primera asignación, las listas son claves hash (con poca ayuda de$;
, y algunasx
, desafortunadamente), y un poco menos complicadas en general, creo.values %h
no es necesario, por lo tanto, su solución solo necesita 106 bytes.Python
127 152B138BAjustado para no romper más las reglas y tener un algoritmo ligeramente más lindo. Ajustado para ser más pequeño
Versión antigua:
¡Mi primer script de Python! Véalo en acción: http://pythonfiddle.com/entropy
fuente
count
función es totalmente contrario a las reglas, ya que es "contar el número de ocurrencias de un bloque x dado".;
si es necesario). Tampoco se necesitan los corchetes en la última línea.and 1 or 0
) es innecesaria. Además, puede guardar algunos caracteres predefiniendorange(N)
.Python con Numpy,
146143 BytesComo prometí, aquí está mi propia solución. Requiere una entrada de enteros no negativos:
La desventaja es que este estalla la memoria para un gran
m
omax(A)
.Aquí está la versión mayormente no comentada y comentada:
fuente
MATLAB
fuente