คำนวณฮิสโตแกรมการประมาณค่าเอนโทรปีของสตริง


19

เขียนโปรแกรมหรือฟังก์ชั่นที่ประมาณค่าเอนโทรปีของแชนนอนของสตริงที่กำหนด

ถ้าสตริงมีnตัวอักษรวันที่ แตกต่างกันตัวอักษรx ฉันเป็นฉัน TH ตัวละครที่แตกต่างกันและP (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 ไม่สตริงใด ๆ ที่ประเภทสตริงภาษาของคุณรองรับ
orlp

น่าเสียดายที่ Mathematica Entropyนับจำนวนบิตต่อตัวละครไม่ใช่ผลรวมของสตริง โอ้ดี ...
2012rcampion

คำตอบ:


2

เยลลี่11 8 ไบต์

ċЀ÷Ll.S

ลองออนไลน์!


ฉันจะถามได้อย่างไรว่าคุณใส่ตัวละครเหล่านั้นได้อย่างไร? ด้วยการคัดลอกและวาง?
Bálint

อย่างน้อยบน Linux พวกมันสามารถพิมพ์บนแป้นพิมพ์สากลของสหรัฐอเมริกาได้
Dennis

11

Python 3.3+, 64 ไบต์

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

ได้math.log2จากการแก้ปัญหาของ mbomb007


ดังนั้น @orlp ไม่ได้ให้สูตรแบบง่ายกับเราใช่มั้ย ... ?
mbomb007

@ mbomb007 ขึ้นอยู่กับวัตถุประสงค์ที่คุณต้องการทำให้ง่ายขึ้น การเขียนในแง่ของความน่าจะเป็นและตัวละครที่แตกต่างนั้นเป็นเรื่องธรรมดา แต่สำหรับการตีกอล์ฟมันสั้นกว่าที่จะใช้นับและย้ำกับตัวละครทั้งหมด
xnor

1
Pyth ตอบคำถามด้วยสูตรของคุณ: pyth.herokuapp.com/… 8 bytes
Maltysen

2

APL, 18 14 ไบต์

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

นี่คือรถไฟฟังก์ชั่น monadic ที่ไม่มีชื่อที่ยอมรับสตริงทางด้านขวาและส่งกลับค่าจริง

เช่นเดียวกับทุกสิ่งที่ดีในชีวิตนี้ใช้สูตร XNOR ของ เราได้เมทริกซ์ของบูลีนที่สอดคล้องกับการเกิดของตัวละครแต่ละตัวในสตริงโดยใช้∘.=⍨ผลรวมตามแกนแรก ( +/) เพื่อให้ได้จำนวนที่เกิดขึ้นของตัวละครแต่ละตัวหารความยาวของสตริงโดยแต่ละตัวจากนั้นนำ log ฐาน 2 ( 2⍟) และผลรวม

ลองที่นี่

บันทึกแล้ว 4 ไบต์ขอบคุณเดนนิส!



1

JavaScript (ES6), 67 ไบต์

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

ฉันต้องใช้~-s.splitเพราะยอมรับสตริงมากกว่า regexps ตามปกติmapเต้นreducebyte

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

1

Perl 5, 58 ไบต์

รูทีนย่อย:

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

หมวกของฉันให้xnorสำหรับสูตร


-Fไม่ทำงาน (ในสตรอเบอร์รี่อยู่แล้ว) $/เพราะมันรวมถึง
msh210



1

J - 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
ฉันไม่คิดว่านี่จะนับเป็นฟังก์ชั่น หากคุณกำหนดรหัสให้กับตัวแปรมันจะทำสิ่งที่แตกต่างอย่างสิ้นเชิง
Dennis

@Dennis จากสิ่งที่ฉันรวบรวมดูเหมือนว่า J ตีความมันเป็นสายโซ่ของการประพันธ์โดยใช้3 : '... y'ไวยากรณ์เดียวกันจะเป็นวิธีที่ถูกต้องในการกำหนดเป็นฟังก์ชั่น J ระบุว่าประเมินจากขวาไปซ้ายดังนั้นฉันจึงปรับโครงสร้างโค้ดของฉันใหม่เป็นรถไฟ ฉันไม่ชอบหมวก[:แต่ฉันไม่สามารถหาวิธีอื่นในการสร้างรถไฟ
ไมล์


0

Jolf, 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

Python 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ในตัวแปรทันทีที่คุณใช้เพียงครั้งเดียว
Maltysen

0

Java 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))))

การแปลคำตอบตัวประกอบของฉันดังนั้นจึงเป็นการแปลทางอ้อมของคำตอบ Python ของ Kenny Lau


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

Mathematica ขนาด 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

R, 67 ไบต์

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

คำอธิบาย

ใช้อินพุตจาก stdin และแยกเป็นรายการอักขระ (ไวยากรณ์ที่น่าสนใจนี้คือเหตุผลว่าทำไมความท้าทายของสายกอล์ฟถึงยากมากใน R ... )

         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

C #, 159 ไบต์

แข็งแรงเล่นกอล์ฟ:

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

Groovy ขนาด 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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.