एक स्ट्रिंग के हिस्टोग्राम एन्ट्रापी आकलन की गणना करें


19

एक प्रोग्राम या फ़ंक्शन लिखें जो किसी दिए गए स्ट्रिंग के शैनन एंट्रोपी का अनुमान लगाता है।

एक स्ट्रिंग है, तो n वर्ण, d अलग वर्ण, x मैं है मैं वें विशिष्ट चरित्र, और पी (एक्स मैं ) स्ट्रिंग में उस चरित्र घटित की संभावना है, तो है कि स्ट्रिंग के लिए हमारे शैनन एन्ट्रापी अनुमान द्वारा दिया जाता है:

H = -n \ sum \ limit_ {i = 1} ^ d P (x_i) \ log_2 P (x_i)

इस चुनौती में अनुमान के लिए, हम मानते हैं कि एक स्ट्रिंग में होने वाले चरित्र की संभावना कुल वर्णों की संख्या से विभाजित होने की संख्या है।

आपके उत्तर की अवधि के बाद कम से कम 3 अंकों के लिए सटीक होना चाहिए।


परीक्षण के मामलों:

"This is a test.", 45.094
"00001111", 8.000
"cwmfjordbankglyphsvextquiz", 122.211
"             ", 0.0

मेरी सामान्य चुनौतियों का विरोध, यह एक जटिल लग रहा है, लेकिन वास्तव में काफी सरल है :)
orlp

संबंधित: codegolf.stackexchange.com/q/24316
msh210

क्या इनपुट स्ट्रिंग के लिए मुद्रण योग्य ASCII ग्रहण करना सुरक्षित है?
AdmBorkBork

@TimmyD No. कोई भी स्ट्रिंग जो आपकी भाषा के स्ट्रिंग प्रकार का समर्थन करती है।
orlp

दुर्भाग्य से, मैथेमेटिका Entropyप्रति चरित्र बिट्स गिनता है, स्ट्रिंग के लिए कुल नहीं; ओह ठीक है ...
२०१२ आर्कम्पियन २६'१६

जवाबों:


2

जेली, 11 8 बाइट्स

ċЀ÷Ll.S

इसे ऑनलाइन आज़माएं!


क्या मैं पूछ सकता हूं कि आप उन पात्रों को कैसे दर्ज करते हैं? कॉपी और पेस्ट के साथ?
बैलिंट

कम से कम लिनक्स पर, वे सभी अमेरिकी अंतर्राष्ट्रीय कीबोर्ड पर टाइप किए जा सकते हैं।
डेनिस

11

पायथन 3.3+, 64 बाइट्स

import math
lambda s:sum(math.log2(len(s)/s.count(c))for c in s)

Mbomb007 के घोलmath.log2 से मिला ।


तो @orlp ने हमें पूरी तरह से सरलीकृत सूत्र नहीं दिया, एह ...?
mbomb007

@ mbomb007 इस बात पर निर्भर करता है कि आप किस उद्देश्य को सरल बना रहे हैं। संभावनाओं और अलग-अलग पात्रों के संदर्भ में इसे लिखना एक परिभाषा के रूप में स्वाभाविक है, लेकिन गोल्फिंग के लिए सभी वर्णों के साथ गणना और पुनरावृति के साथ काम करना कम है।
xnor

1
अपने सूत्र के साथ तीखा जवाब: pyth.herokuapp.com/… 8 बाइट्स
माल्टीसेन

2

एपीएल, 18 14 बाइट्स

+/2⍟≢÷(+/∘.=⍨)

यह एक अनाम, मोनैडिक फ़ंक्शन ट्रेन है जो दाईं ओर एक स्ट्रिंग को स्वीकार करता है और एक वास्तविक रिटर्न देता है।

जीवन में सभी अच्छी चीजों की तरह, यह xnor के सूत्र का उपयोग करता है । हम स्ट्रिंग के प्रत्येक वर्ण की घटनाओं के अनुरूप बूलियन का एक मैट्रिक्स प्राप्त करते हैं ∘.=⍨, पहले अक्ष के साथ इसे जोड़ते हैं ( +/) प्रत्येक वर्ण की घटनाओं की संख्या प्राप्त करने के लिए, प्रत्येक द्वारा स्ट्रिंग की लंबाई को विभाजित करें, फिर लॉग बेस 2 लें ( 2⍟) और योग।

इसे यहाँ आज़माएँ

डेनिस के लिए धन्यवाद 4 बाइट्स सहेजे गए!



1

जावास्क्रिप्ट (ईएस 6), 67 बाइट्स

s=>[...s].map(c=>t+=Math.log2(s.length/~-s.split(c).length),t=0)&&t

मुझे उपयोग करने की आवश्यकता है ~-s.splitक्योंकि यह regexps के बजाय तार को स्वीकार करता है। हमेशा की तरह, एक बाइट द्वारा mapधड़कता reduceहै।

s=>[...s].reduce((t,c)=>t+Math.log2(s.length/~-s.split(c).length),0)

1

पर्ल 5, 58 बाइट्स

एक सबरूटीन:

{for$a(@a=split'',pop){$t+=(log@a/grep/\Q$a/,@a)/log 2}$t}

सूत्र के लिए मेरी टोपी की एक टिप xnor


-Fकाम नहीं करता (स्ट्राबेरी में, वैसे भी) क्योंकि इसमें शामिल है $/
msh210



1

जे - 18 16 14 बाइट्स

1#.2^.#%1#.=/~

डेनिस की विधि में विचार का उपयोग करते हुए संक्षिप्त।

प्रयोग

   f =: 1#.2^.#%1#.=/~
   f 'This is a test.'
45.0936
   f '00001111'
8
   f 'cwmfjordbankglyphsvextquiz'
122.211
   f '             '
0

व्याख्या

1#.2^.#%1#.=/~  Input: string S
           =/~  Create a table testing for equality
        1#.     Convert each row from a list of base 1 digits to decimal
                This is equivalent to taking the sum and forms a list of tallies
      #         Get the length of S
       %        Divide the length by each tally
   2^.          Log base 2 of each
1#.             "Sum" those values and return

1
मुझे नहीं लगता कि यह एक फ़ंक्शन के रूप में गिना जाता है। यदि आप किसी वैरिएबल को कोड असाइन करते हैं, तो यह पूरी तरह से कुछ अलग करता है।
डेनिस

@ डेनिस मैं जो इकट्ठा करता हूं, उससे प्रतीत होता है कि J इसे रचनाओं की एक श्रृंखला के रूप में व्याख्या करता है, 3 : '... y'उसी वाक्य रचना के साथ इसे एक फ़ंक्शन के रूप में परिभाषित करने का एक वैध तरीका होगा। जे का कहना है कि यह दाएं-बाएं से मूल्यांकन करता है, इसलिए मैंने एक ट्रेन के रूप में अपने कोड को वापस ले लिया है। मुझे टोपी पसंद नहीं है [:लेकिन मुझे ट्रेन बनाने का कोई और तरीका नहीं मिल रहा है।
मील


0

जोल्फ, 26 बाइट्स

_*liuΜGμiEd*γ/l miLeHlimzγ

यहाँ यह कोशिश करो! (ध्यान दें कि परीक्षण सूट फ़ंक्शन को बोर्क किया गया है।)

व्याख्या

_*liuΜGμiEd*γ/l miLeHlimzγ
       μi                   unique members of i
      G  E                  split on ""
     Μ    d                 map over function
               _miLeH       match i with regex escaped member
             /l      li     divide length of (^) by length of i
            γ               γ = (^)
           *           mzγ  (^) * log_2(γ)
 *li                        (^) * length of i
_                           negate

0

पायथन 3.3+, 95 91 89 85 बाइट्स

सरल उपाय। संस्करण 3.3 का उपयोग करना आवश्यक है math.log2

import math
def f(s):C=s.count;return-sum(C(x)*math.log2(C(x)/len(s))for x in set(s))

इसे ऑनलाइन आज़माएं


क्या आपको लगता है कि यहां कुछ अनावश्यक है? n*sum(s.count(c)/n
orlp

@orlp धन्यवाद मैंने मूल रूप से प्रायिकता खोजने के लिए एक अलग कार्य किया था, लेकिन इसे दो बार अंदर चिपकाया था और चार्ट को बचाने के लिए इसे हटा दिया था।
mbomb007

nअब आपको एक चर में स्टोर करने की आवश्यकता नहीं है कि आप इसे केवल एक बार उपयोग करें।
माल्टसेन

0

जावा 7, 207 बाइट्स

double C(String x,Map<Character,Integer>f){double H=0,g;for(char c:x.toCharArray())f.put(c,f.containsKey(c)?f.get(c)+1:1);for(char c:f.keySet()){g=f.get(c);H+=g*Math.log(g/x.length())/Math.log(2);}return-H;}

विस्तृत ऑनलाइन प्रयास करें

double log2(double d) { return Math.log(d) / Math.log(2); }

double C(String x, Map<Character,Integer>f)
{
    double H=0,g;

    // frequency
    for(char c : x.toCharArray())
    {
        f.put(c, f.containsKey(c) ? f.get(c)+1 : 1);
    }

    // calculate entropy
    for(char c : f.keySet())
    {
        g = f.get(c);
        H += g * log2(g / x.length());
    }

    return -H;
}

0

फैक्टर, 98 बाइट्स

[ [ length ] [ dup [ [ = ] curry dupd count ] { } map-as nip ] bi [ / log 2 log / ] with map sum ]

यह इस पायथन उत्तर का सीधा अनुवाद है । मैं रात के खाने पर एक स्पष्टीकरण जोड़ दूँगा।


0

रैकेट, 130 बाइट्स

:सी

#lang racket
(require math)(λ(S)(let([s(string->list S)])(sum(map(λ(c)(/(log(/(length s)(count(λ(x)(char=? c x))s)))(log 2)))s))))

मेरे फैक्टर उत्तर का अनुवाद, इसलिए यह केनी लाउ के पायथन उत्तर का अप्रत्यक्ष अनुवाद है।


0

k (32 बाइट्स)

{-+/c*(log c%n:+/c:#:'=x)%log 2}

या qअनुवाद में , यह सब छोटा नहीं है, लेकिन स्पष्ट है:

{neg sum c*2 xlog c%n:sum c:count each group x}

0

गणितज्ञ, 45 बाइट्स

Tr[Log[2,Tr@#/#]#]&@Values@CharacterCounts@#&

प्रयोग

यह सटीक परिणाम देता है इसलिए हम उनके साथ अनुमानित करते हैं N

  f = Tr[Log[2,Tr@#/#]#]&@Values@CharacterCounts@#&
  f["This is a test."]//N
45.0936
  f["00001111"]//N
8.
  f["cwmfjordbankglyphsvextquiz"]//N
122.211
  f["             "]//N
0.

0

आर, 67 बाइट्स

l=length(i<-strsplit(readline(),"")[[1]]);-sum(log2(l/table(i)[i]))

व्याख्या

स्टड से इनपुट लें और इसे पात्रों की सूची में विभाजित करें। (यह क्लिंक सिंटैक्स यही है कि आर में स्ट्रिंग गोल्फ चुनौतियां इतनी कठिन हैं ...)

         i<-strsplit(readline(),"")[[1]])

यह असाइनमेंट एक lengthकमांड के अंदर छिपा हुआ है , इसलिए हमें एक की कीमत के लिए दो असाइनमेंट मिलते हैं। हमारे पास i, पात्रों की सूची और l, इसकी लंबाई है।

l=length(i<-strsplit(readline(),"")[[1]]);

अब हम एन्ट्रापी की गणना करते हैं। R का एक अच्छा फंक्शन है tableजो सभी अनूठे मूल्यों की गिनती देता है। इनपुट के लिए This is a test, table(i)रिटर्न

> table(i)
i
  . a e h i s t T 
3 1 1 1 1 2 3 2 1

यह वर्णों द्वारा अनुक्रमित है, जो अच्छा है, क्योंकि हम तब iप्रत्येक वर्ण की गिनती प्राप्त करने के लिए एक सूचकांक के रूप में उपयोग कर सकते हैं , जैसे:

> table(i)[i]
i
T h i s   i s   a   t e s t . 
1 1 2 3 3 2 3 3 1 3 2 1 3 2 1 

कोड के बाकी तो एक छोटी सी के आसपास फ़्लॉपी सूत्र का एक सरल कार्यान्वयन है।

                                           -sum(log2(l/table(i)[i]))

दो बाइट्स सहेजें (आपका सबमिशन TIO पर काम नहीं करता है)
JayCe


0

सी #, 159 बाइट्स

golfed:

string f(string s){var l=s.Length;double sum=0;foreach(var item in s.GroupBy(o=>o)){double p=(double)item.Count()/l;sum+=p*Math.Log(p,2);}return(sum*=-l)+"";}}

Ungolfed:

string f(string s)
{
  var l = s.Length;
  double sum = 0;
  foreach (var item in s.GroupBy(o => o))
  {
    double p = (double)item.Count() / l;
    sum += p * Math.Log(p, 2);
  }
  return (sum *= -l) + "";
}

परीक्षा:

var codeGolf = new StringHistogramEntropyEstimation();
    Console.WriteLine(codeGolf.f("This is a test.")); //45.0935839298008
    Console.WriteLine(codeGolf.f("00001111")); //8
    Console.WriteLine(codeGolf.f("cwmfjordbankglyphsvextquiz")); //122.211432671668
    Console.WriteLine(codeGolf.f("             ")); //0

0

ग्रूवी, 100 बाइट्स

{a->n=a.size();a.toList().unique().collect{p=a.count(it)/n;p*(Math.log(p)/Math.log(2.0f))}.sum()*-n}

टेस्ट:

This is a test. = 45.09358393449714
00001111 = 8.0
cwmfjordbankglyphsvextquiz = 122.21143275636976
aaaaaaaa = -0.0
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.