Entropy: Difference between revisions
Content deleted Content added
→Ksh: add |
|||
(15 intermediate revisions by 10 users not shown) | |||
Line 243:
=={{header|Arturo}}==
<syntaxhighlight lang="rebol">entropy: function [s][
t: #[]
Line 385 ⟶ 384:
{{out}}
<pre>1.8464393</pre>
==={{header|uBasic/4tH}}===
{{Trans|QBasic}}
uBasic/4tH is an integer BASIC only. So, fixed point arithmetic is required go fulfill this task. Some loss of precision is unavoidable.
<syntaxhighlight lang="basic">If Info("wordsize") < 64 Then Print "This program requires a 64-bit uBasic" : End
s := "1223334444"
u := ""
x := FUNC(_Fln(FUNC(_Ntof(2)))) ' calculate LN(2)
For i = 0 TO Len(s)-1
k = 0
For j = 0 TO Len(u)-1
If Peek(u, j) = Peek(s, i) Then k = 1
Next
If k = 0 THEN u = Join(u, Char (Peek (s, i)))
Next
Dim @r(Len(u)-1)
For i = 0 TO Len(u)-1
c = 0
For J = 0 TO Len(s)-1
If Peek(u, i) = Peek (s, j) Then c = c + 1
Next
q = FUNC(_Fdiv(c, Len(s)))
@r(i) = FUNC(_Fmul(q, FUNC(_Fdiv(FUNC(_Fln(q)), x))))
Next
e = 0
For i = 0 To Len(u) - 1
e = e - @r(i)
Next
Print Using "+?.####"; FUNC(_Ftoi(e))
End
_Fln Param (1) : Return (FUNC(_Ln(a@*4))/4)
_Fmul Param (2) : Return ((a@*b@)/16384)
_Fdiv Param (2) : Return ((a@*16384)/b@)
_Ntof Param (1) : Return (a@*16384)
_Ftoi Param (1) : Return ((10000*a@)/16384)
_Ln
Param (1)
Local (2)
c@=681391
If (a@<32768) Then a@=SHL(a@, 16) : c@=c@-726817
If (a@<8388608) Then a@=SHL(a@, 8) : c@=c@-363409
If (a@<134217728) Then a@=SHL(a@, 4) : c@=c@-181704
If (a@<536870912) Then a@=SHL(a@, 2) : c@=c@-90852
If (a@<1073741824) Then a@=SHL(a@, 1) : c@=c@-45426
b@=a@+SHL(a@, -1) : If (AND(b@, 2147483648)) = 0 Then a@=b@ : c@=c@-26573
b@=a@+SHL(a@, -2) : If (AND(b@, 2147483648)) = 0 Then a@=b@ : c@=c@-14624
b@=a@+SHL(a@, -3) : If (AND(b@, 2147483648)) = 0 Then a@=b@ : c@=c@-7719
b@=a@+SHL(a@, -4) : If (AND(b@, 2147483648)) = 0 Then a@=b@ : c@=c@-3973
b@=a@+SHL(a@, -5) : If (AND(b@, 2147483648)) = 0 Then a@=b@ : c@=c@-2017
b@=a@+SHL(a@, -6) : If (AND(b@, 2147483648)) = 0 Then a@=b@ : c@=c@-1016
b@=a@+SHL(a@, -7) : If (AND(b@, 2147483648)) = 0 Then a@=b@ : c@=c@-510
a@=2147483648-a@;
c@=c@-SHL(a@, -15)
Return (c@)</syntaxhighlight>
{{Out}}
<pre>1.8461
0 OK, 0:638</pre>
=={{header|BBC BASIC}}==
Line 427 ⟶ 493:
=={{header|C}}==
<syntaxhighlight lang="c">#include <stdio.h>
#include <stdlib.h>
Line 666 ⟶ 731:
=={{header|Common Lisp}}==
Not very Common Lisp-y version:
<syntaxhighlight lang="lisp">(defun entropy (string)
(let ((table (make-hash-table :test 'equal))
Line 690 ⟶ 753:
for freq/length = (/ freq length)
sum (* freq/length (log freq/length 2))))))</syntaxhighlight>
=={{header|Crystal}}==
Line 778 ⟶ 815:
{{out}}
<pre>1.84644</pre>
=={{header|Delphi}}==
{{libheader| StrUtils}}
Line 844 ⟶ 882:
readln;
end.</syntaxhighlight>
=={{header|EasyLang}}==
<syntaxhighlight lang=text>
func entropy s$ .
len d[] 255
for c$ in strchars s$
d[strcode c$] += 1
.
for cnt in d[]
if cnt > 0
prop = cnt / len s$
entr -= (prop * log10 prop / log10 2)
.
.
return entr
.
print entropy "1223334444"
</syntaxhighlight>
=={{header|EchoLisp}}==
<syntaxhighlight lang="scheme">
Line 881 ⟶ 938:
</syntaxhighlight>
=={{header|Elena}}==
{{trans|C#}}
ELENA
<syntaxhighlight lang="elena">import system'math;
import system'collections;
Line 903 ⟶ 959:
var table := Dictionary.new();
input.forEach::(ch)
{
var n := table[ch];
Line 917 ⟶ 973:
var freq := 0;
table.forEach::(letter)
{
freq := letter.toInt().realDiv(input.Length);
Line 1,019 ⟶ 1,075:
>entropy("1223334444")
1.84643934467</syntaxhighlight>
=={{header|Excel}}==
This solution uses the <code>LAMBDA</code>, <code>LET</code>, and <code>MAP</code> functions introduced into the Microsoft 365 version of Excel in 2021. The <code>LET</code> function is able to use functions as first class citizens. Taking advantage of this makes the solution much simpler. The solution below looks for the string in cell <code>A1</code>.
<syntaxhighlight lang="excel">
=LET(
_MainS,A1,
_N,LEN(_MainS),
_Chars,UNIQUE(MID(_MainS,SEQUENCE(LEN(_MainS),1,1,1),1)),
calcH,LAMBDA(_c,(_c/_N)*LOG(_c/_N,2)),
getCount,LAMBDA(_i,LEN(_MainS)-LEN(SUBSTITUTE(_MainS,_i,""))),
_CharMap,MAP(_Chars,LAMBDA(a, calcH(getCount(a)))),
-SUM(_CharMap)
)
</syntaxhighlight>
_Chars uses the <code>SEQUENCE</code> function to split the text into an array. The <code>UNIQUE</code> function then returns a list of unique characters in the string.
<code>calcH</code> applies the calculation described at the top of the page that will then be summed for each character
<code>getCount</code> uses the <code>SUBSTITUTE</code> method to count the occurrences of a character within the string.
If you needed to re-use this calculation then you could wrap it in a <code>LAMBDA</code> function within the name manager, changing <code>A1</code> to a variable name (e.g. <code>String</code>):
<syntaxhighlight lang="excel">
ShannonEntropyH2=LAMBDA(String,LET(_MainS,String,_N,LEN(_MainS),_Chars,UNIQUE(MID(_MainS,SEQUENCE(LEN(_MainS),1,1,1),1)),calcH,LAMBDA(_c,(_c/_N)*LOG(_c/_N,2)),getCount,LAMBDA(_i,LEN(_MainS)-LEN(SUBSTITUTE(_MainS,_i,""))),_CharMap,MAP(_Chars,LAMBDA(a, calcH(getCount(a)))),-SUM(_CharMap)))
</syntaxhighlight>
Then you can just use the named lambda. E.g. If A1 = 1223334444 then:
<syntaxhighlight lang="excel">
=ShannonEntropyH2(A1)
</syntaxhighlight>
Returns 1.846439345
=={{header|F_Sharp|F#}}==
Line 1,078 ⟶ 1,165:
=={{header|Fortran}}==
Please find the GNU/linux compilation instructions along with sample run among the comments at the start of the FORTRAN 2008 source. This program acquires input from the command line argument, thereby demonstrating the fairly new get_command_argument intrinsic subroutine. The expression of the algorithm is a rough translated of the j solution. Thank you.
<syntaxhighlight lang="fortran">
Line 1,214 ⟶ 1,300:
=={{header|Fōrmulæ}}==
{{FormulaeEntry|page=https://formulae.org/?script=examples/Entropy}}
'''Solution'''
[[File:Fōrmulæ - Entropy 01.png]]
'''Test case'''
[[File:Fōrmulæ - Entropy 02.png]]
[[File:Fōrmulæ - Entropy 03.png]]
[[File:Fōrmulæ - Entropy 04.png]]
[[File:Fōrmulæ - Entropy 05.png]]
=={{header|Go}}==
Line 1,338 ⟶ 1,434:
=={{header|Icon}} and {{header|Unicon}}==
Hmmm, the 2nd equation sums across the length of the string (for the
example, that would be the sum of 10 terms). However, the answer cited
Line 1,475 ⟶ 1,570:
2
3
4</pre>
;Another variant
<syntaxhighlight lang="javascript">const entropy = (s) => {
const split = s.split('');
Line 1,555 ⟶ 1,651:
=={{header|Julia}}==
{{works with|Julia|0.6}}
<syntaxhighlight lang="julia">entropy(s) = -sum(x -> x * log(2, x), count(x -> x == c, s) / length(s) for c in unique(s))
@show entropy("1223334444")
Line 1,563 ⟶ 1,658:
<pre>entropy("1223334444") = 1.8464393446710154
entropy([1, 2, 3, 1, 2, 1, 2, 3, 1, 2, 3, 4, 5]) = 2.103909910282364</pre>
=={{header|K}}==
{{works with|ngn/k}}
<syntaxhighlight lang="k">entropy: {(`ln[#x]-(+/{x*`ln@x}@+/{x=\:?x}x)%#x)%`ln@2}
entropy "1223334444"</syntaxhighlight>
{{out}}
<pre>1.8464393446710161</pre>
=={{header|Kotlin}}==
<syntaxhighlight lang="
fun log2(d: Double) = Math.log(d) / Math.log(2.0)
Line 1,598 ⟶ 1,701:
for (sample in samples) println("${sample.padEnd(36)} -> ${"%18.16f".format(shannon(sample))}")
}</syntaxhighlight>
{{out}}
<pre>
Line 1,613 ⟶ 1,715:
=={{header|Ksh}}==
{{works with|ksh93}}
<syntaxhighlight lang="ksh">function entropy {
typeset -i i len=${#1}
Line 1,852 ⟶ 1,955:
{{out}}
<pre> 1.8464394E+00</pre>
=={{header|NetRexx}}==
{{trans|REXX}}
Line 1,953 ⟶ 2,057:
=={{header|Objeck}}==
<syntaxhighlight lang="objeck">use Collection;
Line 2,015 ⟶ 2,118:
=={{header|OCaml}}==
;By using a map, purely functional
<syntaxhighlight lang="ocaml">module CharMap = Map.Make(Char)
let entropy s =
let count map c =
CharMap.update c (function Some n -> Some (n +. 1.) | None -> Some 1.) map
and calc _ n sum =
sum +. n *. Float.log2 n
in
let sum = CharMap.fold calc (String.fold_left count CharMap.empty s) 0.
and len = float (String.length s) in
Float.log2 len -. sum /. len
let () =
entropy "1223334444" |> string_of_float |> print_endline</syntaxhighlight>
;By using a mutable Hashtbl
<syntaxhighlight lang="ocaml">
(* pre-bake & return an inner-loop function to bin & assemble a character frequency map *)
let get_fproc (m: (char, int) Hashtbl.t) :(char -> unit) =
Line 2,046 ⟶ 2,164:
-1.0 *. List.fold_left (fun b x -> b +. calc x) 0.0 relative_probs
</syntaxhighlight>
{{out}}
<pre>1.84643934467</pre>
=={{header|Oforth}}==
<syntaxhighlight lang="oforth">: entropy(s) -- f
| freq sz |
Line 2,108 ⟶ 2,223:
=={{header|Pascal}}==
Free Pascal (http://freepascal.org).
<syntaxhighlight lang="pascal">
PROGRAM entropytest;
Line 2,216 ⟶ 2,329:
=={{header|PHP}}==
<syntaxhighlight lang="php"><?php
Line 2,365 ⟶ 2,477:
=={{header|Prolog}}==
{{works with|Swi-Prolog|7.3.3}}
This solution calculates the run-length encoding of the input string to get the relative frequencies of its characters.
<syntaxhighlight lang="prolog">:-module(shannon_entropy, [shannon_entropy/2]).
Line 2,620 ⟶ 2,729:
=={{header|R}}==
<syntaxhighlight lang="rsplus">
entropy <- function(str) {
Line 2,932 ⟶ 3,040:
</pre>
=={{header|
{{works with|Halcyon Calc|4.2.7}}
{| class="wikitable"
! Code
! Comments
|-
|
≪
DUP SIZE 2 LN → str len log2
≪ { 255 } 0 CON
1 len '''FOR''' j
str j DUP SUB
NUM DUP2 GET 1 + PUT
'''NEXT'''
0 1 255 '''FOR''' j
'''IF''' OVER j GET
'''THEN''' LAST len / DUP LN log2 / * + '''END'''
'''NEXT'''
NEG SWAP DROP
≫ ≫ '<span style="color:blue">NTROP</span>' STO
|
<span style="color:blue">NTROP</span> ''( "string" -- entropy )''
Initialize local variables
Initialize a vector with 255 counters
For each character in the string...
... increase the counter according to ASCII code
For each non-zero counter
calculate term
Change sign and forget the vector
|}
The following line of code delivers what is required:
"1223334444" <span style="color:blue">NTROP</span>
{{out}}
<pre>
1: 1.84643934467
</pre>
=={{header|Ruby}}==
<syntaxhighlight lang="ruby">def entropy(s)
counts = s.chars.tally
Line 3,139 ⟶ 3,288:
1.84644
</pre>
=={{header|SETL}}==
<syntaxhighlight lang="setl">program shannon_entropy;
print(entropy "1223334444");
op entropy(symbols);
hist := {};
loop for symbol in symbols do
hist(symbol) +:= 1;
end loop;
h := 0.0;
loop for count = hist(symbol) do
f := count / #symbols;
h -:= f * log f / log 2;
end loop;
return h;
end op;
end program; </syntaxhighlight>
{{out}}
<pre>1.84643934467102</pre>
=={{header|Sidef}}==
Line 3,170 ⟶ 3,339:
Entropy "1223334444" ;
val it = 1.846439345: real
=={{header|Swift}}==
<syntaxhighlight lang="swift">import Foundation
Line 3,210 ⟶ 3,380:
=={{header|V (Vlang)}}==
===Vlang: Map version===
<syntaxhighlight lang="v (vlang)">import math
Line 3,248 ⟶ 3,417:
=={{header|Wren}}==
{{trans|Go}}
<syntaxhighlight lang="
var m = {}
for (c in s) {
|