J'ai eu besoin d'écrire une fonction qui calcule l'entropie de blocs d'une série de symboles donnée pour une taille de bloc donnée et j'ai été surpris de la brièveté du résultat. Je vous mets donc au défi de coder une telle fonction. Je ne vous dis pas ce que j'ai fait pour l'instant (et dans quelle langue), mais je le ferai dans une semaine environ, si personne ne propose les mêmes ou meilleures idées en premier.
Définition de l'entropie du bloc:
Étant donné une séquence de symboles A = A_1,…, A_n et une taille de bloc m:
- Un bloc de taille m est un segment de m éléments consécutifs de la séquence de symboles, c'est-à-dire A_i,…, A_ (i + m − 1) pour tout i approprié.
- Si x est une séquence de symboles de taille m, N (x) désigne le nombre de blocs de A qui sont identiques à x.
- p (x) est la probabilité qu'un bloc de A soit identique à une séquence de symboles x de taille m, c'est-à-dire p (x) = N (x) / (n − m + 1)
- Enfin, l'entropie des blocs pour la taille de bloc m de A est la moyenne de −log (p (x)) sur tous les blocs x de taille m dans A ou (ce qui est équivalent) la somme de −p (x) · log (p (x)) sur chaque x de taille m se produisant dans A. (Vous pouvez choisir n'importe quel logarithme raisonnable que vous souhaitez.)
Restrictions et clarifications:
- Votre fonction doit prendre comme argument la séquence de symboles A ainsi que la taille de bloc m.
- Vous pouvez supposer que les symboles sont représentés sous forme d'entiers à base zéro ou dans un autre format pratique.
- Votre programme devrait être capable de prendre n'importe quel argument raisonnable en théorie et en réalité devrait être capable de calculer l'exemple de cas (voir ci-dessous) sur un ordinateur standard.
- Les fonctions et bibliothèques intégrées sont autorisées, tant qu'elles n'effectuent pas de grandes parties de la procédure en un seul appel, c'est-à-dire extraire tous les blocs de taille m de A, compter le nombre d'occurrences d'un bloc x donné ou calculer les entropies à partir d'une séquence de valeurs p - vous devez faire ces choses vous-même.
Tester:
[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]
Les premières entropies de blocs de cette séquence sont (pour le logarithme naturel):
- 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)))
.Réponses:
Mathematica -
8178757267656256 octetsJe n'ai jamais joué au golf à Mathematica auparavant, donc je suppose qu'il y a place à amélioration. Celui-ci n'est pas tout à fait conforme aux règles en raison des fonctions
Partition
etTally
, mais il est assez soigné, j'ai donc pensé le publier de toute façon.Cela fonctionne avec n'importe quel ensemble de symboles et peut être utilisé comme
Voici une version quelque peu non golfée:
Il fonctionnera probablement plus rapidement si je postule
N
directement au résultat deTally
.Soit dit en passant, Mathematica a en fait une
Entropy
fonction, qui la réduit à 28 octets , mais c'est certainement contraire aux règles.En revanche, voici une version 128 octets qui réimplémente
Partition
etTally
:Non golfé:
la source
Partition
etTally
ne sont pas des cas limites, ils enfreignent purement et simplement les règles, car ils «extraient tous les blocs de taille m de A» et «comptent le nombre d'occurrences d'un bloc x donné», respectivement, en un seul appel. Pourtant, après tout ce que je sais de Mathematica, je ne serais pas surpris s'il y avait une solution décente sans eux.Partition
etTally
.Perl, 140 octets
Le script Perl suivant définit une fonction
E
qui prend la séquence de symboles, suivie de la taille du segment comme arguments.Version non golfée avec test
Résultat:
Symboles:
Les symboles ne sont pas limités aux entiers, car une correspondance de modèle basée sur des chaînes est utilisée. La représentation sous forme de chaîne d'un symbole ne doit pas contenir de virgule, car elle est utilisée comme délimiteur. Bien sûr, différents symboles doivent avoir des représentations de chaînes différentes.
Dans la version golfée, la représentation sous forme de chaîne des symboles ne doit pas contenir de caractères spéciaux de motifs. Les quatre octets supplémentaires
\Q
...\E
ne sont pas nécessaires pour les nombres.la source
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}
; où$s
est une référence,$r
et%h
sont réinitialisés à undef avec la 1ère affectation, les listes sont des clés de hachage (avec peu d'aide$;
, et certainesx
- malheureusement), et un peu moins compliquées en général, je pense.values %h
n'est pas nécessaire, votre solution n'a donc besoin que de 106 octets.Python
127 152B138BAjusté pour ne plus enfreindre les règles et avoir un algorithme légèrement plus mignon. Ajusté pour être plus petit
Ancienne version:
Mon tout premier script Python! Voyez-le en action: http://pythonfiddle.com/entropy
la source
count
fonction est carrément contraire aux règles, car elle "compte le nombre d'occurrences d'un bloc x donné".;
si nécessaire). Les crochets de la dernière ligne ne sont pas non plus nécessaires.and 1 or 0
) n'est pas nécessaire. Vous pouvez également enregistrer certains caractères en prédéfinissantrange(N)
.Python avec Numpy,
146143 octetsComme promis, voici ma propre solution. Il nécessite une entrée d'entiers non négatifs:
L'inconvénient est que cela éclate votre mémoire pour un grand
m
oumax(A)
.Voici la version principalement non golfée et commentée:
la source
MATLAB
la source