Les bits moyens: un défi moyen


30

Étant donné un entier N> = 1, sortir le nombre moyen de bits dans un entier de 0 à N - 1

spécification

  • La sortie peut être calculée comme la somme du nombre de bits dans la représentation binaire de chaque entier de 0 à N-1, divisée par N.
  • La représentation binaire d'un entier n'a pas de zéros de tête dans ce contexte, à l'exception de zéro, qui est représenté par 0 en binaire.
  • La sortie doit être précise à au moins 7 chiffres significatifs.

Exemple

N = 6

0: 0   : 1 bit
1: 1   : 1 bit
2: 10  : 2 bits
3: 11  : 2 bits
4: 100 : 3 bits
5: 101 : 3 bits

Nombre moyen de bits = (1 + 1 + 2 + 2 + 3 + 3) / 6 = 2

Cas de test

Entrée => sortie

1 => 1
2 => 1
3 => 1.3333333
4 => 1.5
5 => 1.8
6 => 2
7 => 2.1428571

Extrait de classement

(d' ici )

Notez que la somme (avant de diviser pour trouver la moyenne) est une séquence sur OEIS .


6
Joli nom, très chétif .
Rɪᴋᴇʀ

3
Pour ceux qui ne le savent pas, je suis plus susceptible de voter pour des solutions avec une explication
trichoplax

4
Pas assez de jeux de mots, il vous en faut un peu plus pour que cela soit parfait.
clismique

1
Je suppose que par "chaque nombre" vous voulez dire "chaque entier "?
Cyoce

@Cyoce oui, merci de l'avoir signalé - j'ai édité pour clarifier.
trichoplax

Réponses:


13

Pyth, 6 octets

.Oml.B

Essayez-le en ligne ici .

.Oml.BdUQ              Filling in implict vars

.O                     Average of list
 m   UQ                Map over [0..input)
  l                    Length of
   .B                  Binary string representation of int
    d                  Lambda var

Joint première place mais vous n'apparaissiez pas dans le classement - j'ai apporté une modification mineure à l'en-tête pour le corriger.
trichoplax

9

Gelée, 6 octets

R’BFL÷

Essayez-le en ligne!

R’BFL÷  Main monadic chain. Argument: n

R       yield [1, 2, ..., n]
 ’      decrement; yield [0, 1, ..., n-1]
  B     convert to binary; yield [[0], [1], [1,0], [1,1], ...]
   F    flatten list; yield [0, 1, 1, 0, 1, 1, ...]
    L   length of list
     ÷  divide [by n]

7

Octave, 29 octets

@(n)1+sum(fix(log2(1:n-1)))/n

Explication

              log2(1:n-1)       % log2 of numbers in range [1..n-1]
                                % why no 0? because log2(0) = -Inf  :/
          fix(           )      % floor (more or less, for positive numbers)
      sum(                )     % sum... wait, didn't we miss a +1 somewhere?
                                % and what about that missing 0?
                           /n   % divide by n for the mean
    1+                          % and add (1/n) for each of the n bit lengths 
                                % (including 0!)

Exemple de run sur ideone .


6

Python 3, 43 octets

def f(n):x=len(bin(n))-2;return(2-2**x)/n+x

Utilise la formule sur la page OEIS . Étonnamment, une fonction nommée est en quelque sorte moins chère ici en raison de l'affectation à x.

Approche alternative pour 46 octets:

lambda n:-~sum(map(int.bit_length,range(n)))/n

Malheureusement, -~est nécessaire car (0).bit_length()est 0, mais même alors ce serait un octet trop long.


6

Julia, 27 octets

n->endof(prod(bin,0:n-1))/n

Essayez-le en ligne!

Comment ça marche

Étant donné que *la concaténation de chaînes dans Julia, prodpeut être utilisée pour concaténer un tableau de chaînes. Il prend éventuellement une fonction comme premier argument qu'il mappe sur le second avant de prendre le "produit" réel, tout prod(bin,0:n-1)comme la chaîne de la représentation binaire de tous les entiers dans la plage souhaitée. Prendre la longueur avec endofet diviser par n donne la moyenne.


5

Julia, 28 octets

n->mean(ceil(log2([2;2:n])))

Puisque binne mappe pas automatiquement sur les tableaux, nous utilisons ceil(log2(n))pour obtenir le nombre de bits n-1. Cela fonctionne bien parce que la a:bnotation de Julia est inclusive aux deux extrémités, tout 2:ncomme une plage de 2 à n, mais nous calculons vraiment le nombre de bits pour les nombres dans la plage 1:n-1. Malheureusement, nous devons ajouter un supplément 2pour représenter 0.

Essayez-le en ligne!


5

MATL, 9 octets

q:ZlksG/Q

Essayez-le en ligne!

Version modifiée avec tous les cas de test

Explication

    % Implicitly grab input (N)
q:  % Create array from 1:N-1
Zl  % Compute log2 for each element of the array
k   % Round down to the nearest integer
s   % Sum all values in the array
G   % Explicitly grab input again
/   % Divide by the input
Q   % Add 1 to account for 0 in [0, ... N - 1]
    % Implicitly display the result

Casser!! (remplissage)
David

@David En fait, la vôtre était correcte. La duplication de l'entrée au début ne fonctionne pas pour d'autres valeurs ... vous avez besoin G/Qde la fin.
bécher

5

MATL, 9 octets

:qBYszQG/

Essayez-le en ligne!

Explication

:qBYszQG/
:               % take vector [1..n]
 q              % decrement by 1 to get [0..n-1]
  B             % convert from decimal to binary
   Ys           % cumulative sum (fills in 0's after first 1)
     z          % number of nonzero elements
      Q         % increment by 1 to account for zero
       G        % paste original input (n)
        /       % divide for the mean

5

Gelée, 8 octets

Pas un algorithme plus court mais intéressant, et ma première soumission Jelly:

Rl2Ċ»1S÷

R         1 to n
 l2       log2
   Ċ      ceiling
    »1    max of 1 and...
      S   sum
       ÷  divided by n

4

Gelée, 10 octets

BL©2*2_÷+®

D'après la suggestion du Sp3000.

Essayez-le ici.

Gelée, 11 octets

æḟ2’Ḥ÷_BL$N

Pas très court mais j'ai besoin de quelques conseils.

Essayez-le ici.

En utilisant la même formule que dans la réponse de Sp3000 . (Ce n'est pas très difficile de l'obtenir vous-même, en différenciant la progression géométrique.)


Regardez ma réponse Jelly pour votre référence.
Leaky Nun

@LeakyNun Il utilise une approche différente, qui, je pense, ne serait jamais plus courte que la vôtre. Mais cela _BL$Nsemblait assez long ...
jimmy23013

Donc, fondamentalement, votre code est "plancher à la puissance la plus proche de 2, moins 1, double, diviser par entrée, moins longueur binaire d'entrée, négatif"?
Leaky Nun

@LeakyNun Oui ..
jimmy23013

3
Seulement un peu mieux:BL©2*2_÷+®
Sp3000

4

Java, 135 95 90 octets

float a(int n){int i=0,t=0;for(;i<n;)t+=Integer.toString(i++,2).length();return t/(n+0f);}

Je pense que vous pouvez vous débarrasser de l'interface et simplement créer une fonction ou lambda. Vous pouvez également retourner la valeur au lieu de l'imprimer sur stdout
Frozn

D'accord, je vais réimplémenter avec ces règles.
Shaun Wild

Je pense que cela devrait être autorisé. Comme l'OP n'a rien spécifié, je pense que les règles d'E / S standard s'appliquent.
Frozn

Oui, une fonction est très bien - vous n'avez pas besoin d'un programme complet. Notez que le classement ramasse le score sur la première ligne, donc votre score est actuellement de 135 au lieu de 95.
trichoplax

@trichoplax Toujours dernière place. Je blâme Java personnellement ...
Shaun Wild

3

Python 3, 46 octets

lambda x:sum(len(bin(i))-2for i in range(x))/x

Appelez ça comme

f = lambda x: sum(len(bin(i))-2for i in range(x))/x
print(f(6))
# 2.0

J'ai dû annuler la révision de la carte car elle a échoué pour l'entrée de 5


3

05AB1E, 9 7 octets

Code:

L<bJg¹/

Explication:

L<         # range from 0..input-1
  b        # convert numbers to binary
   J       # join list of binary numbers into a string
    g      # get length of string (number of bits)
     ¹/    # divide by input

Essayez-le en ligne

Edit: sauvé 2 octets grâce à @Adnan


@Adnan: Merci! Oublié J.
Emigna

3

C #, 87 octets

double f(int n){return Enumerable.Range(0,n).Average(i=>Convert.ToString(i,2).Length);}

J'ai écrit une réponse C # parce que je n'en ai pas vu. Ceci est mon premier post à l'un de ceux-ci, alors faites-moi savoir si je fais quelque chose de mal.


Bienvenue dans Programming Puzzles et Code Golf. C'est une excellente première réponse, +1. Pourriez-vous changer doublepour floatenregistrer un octet, ou avez-vous besoin de la précision?
wizzwizz4

2
@ wizzwizz4 Merci! J'ai eu la même pensée, mais Average () renvoie un double. Si je change mon type de retour pour flotter, je dois explicitement lancer le double et gagner 7 octets sur cela.
raive

2

JavaScript (ES7), 38 32 octets

n=>(l=-~Math.log2(n))-(2**l-2)/n

Utilisation de la formule de @ sp3000 (la version précédente était une solution récursive). Version ES6 pour 34 octets:

n=>(l=-~Math.log2(n))-((1<<l)-2)/n

Explication de la formule: considérons le cas de N = 55. Si nous écrivons les nombres binaires (verticalement pour économiser de l'espace), nous obtenons:

                                11111111111111111111111
                111111111111111100000000000000001111111
        11111111000000001111111100000000111111110000000
    111100001111000011110000111100001111000011110000111
  11001100110011001100110011001100110011001100110011001
0101010101010101010101010101010101010101010101010101010

La taille de ce rectangle est nl donc la moyenne est juste l mais nous devons exclure les blancs. Chaque rangée de blancs est deux fois plus longue que la précédente, le total est donc de 2 + 4 + 8 + 16 + 32 = 64 - 2 = 2 l - 2.


2

J, 21 17 15 octets

De 17 octets à 15 octets grâce à @Dennis.

+/@:%~#@#:"0@i.

Quelqu'un peut-il m'aider à jouer au golf? ...

Version non golfée

range        =: i.
length       =: #
binary       =: #:
sum          =: +/
divide       =: %
itself       =: ~
of           =: @
ofall        =: @:
binarylength =: length of binary "0
average      =: sum ofall divide itself
f            =: average binarylength of range

J'ai essayé une autre approche, par stringifying la liste des chiffres binaires, et est sorti avec 25 octets: %~>:@#@([:":10#.[:#:i.)-]. Votre solution semble plutôt optimale.
Conor O'Brien

2

Perl 6 ,  34  32 octets

{$_ R/[+] map *.base(2).chars,^$_}

{$_ R/[+] map {(.msb||0)+1},^$_}

Explication:

{ 
  $_  # the input
  R/  # divides ( 「$a R/ $b」 is the same as 「$b / $a」 )
  [+] # the sum of:
  map
    {
      (
       .msb # the most significant digit (0 based)
       || 0 # which returns Nil for 「0.msb」 so use 0 instead
            # should be 「(.msb//0)」 but the highlighting gets it wrong
            # it still works because it has the same end result 
      ) 
      + 1   # make it 1 based
    },
    ^$_ # 「0 ..^ $_」 all the numbers up to the input, excluding the input
}

Tester:

use v6.c;

# give it a name
my &mean-bits = {$_ R/[+] map {(.msb||0)+1},^$_}

for 1..7 {
  say .&mean-bits
}

say '';

say mean-bits(7).perl;
say mean-bits(7).base-repeating(10);
1
1
1.333333
1.5
1.8
2
2.142857

<15/7>
(2. 142857)

2

Dyalog APL , 14 octets

(+/1⌈(⌈2⍟⍳))÷⊢

range ← ⍳
log   ← ⍟
log2  ← 2 log range
ceil  ← ⌈
bits  ← ceil log2
max   ← ⌈
fix0  ← 1 max bits
sum   ← +/
total ← sum fix0
self  ← ⊢
div   ← ÷
mean  ← sum div self

2

Clojure, 71 64 63 octets

Il semble que les ratios soient corrects selon Quels formats numériques sont acceptables en sortie?

(fn[n](/(inc(apply +(map #(.bitLength(bigint %))(range n))))n))

  • n = 1 => 1
  • n = 7 => 15/7

non golfé (et légèrement réécrit pour faciliter l'explication)

(fn [n]
 (->
  (->>
   (range n)                      ;;Get numbers from 0 to N
   (map #(.bitLength (bigint %))) ;;Cast numbers to BigInt so bitLength can be used
   (apply +)                      ;;Sum the results of the mapping
   (inc))                         ;;Increment by 1 since bitLength of 0 is 0
  (/ n)))                         ;;Divide the sum by N

ancienne réponse utilisée (float):

(fn[n](float(/(inc(apply +(map #(..(bigint %)bitLength)(range n))))n)))

la sortie est comme:

  • n = 1 => 1,0
  • n = 7 => 2,142857

La question de savoir si les fractions ou les ratios sont acceptables n'avait pas été soulevée auparavant. Pour ce défi, j'accepterai tout consensus sur ce que devrait être la valeur par défaut .
trichoplax

1

Minkolang 0,15 , 23 octets

n$z1z[i1+2l$M$Y+]kz$:N.

Essayez-le ici!

Explication

n$z                       Take number from input and store it in register (n)
   1                      Push 1 onto the stack
    z[                    For loop that repeats n times
      i1+                 Loop counter + 1
         2l$M             log_2
             $Y           Ceiling
               +          Add top two elements of stack
                ]         Close for loop
                 z$:      Float divide by n
                    N.    Output as number and stop.

Implémentation assez simple.


1

JavaScript ES5, 55 octets

n=>eval(`for(o=0,p=n;n--;o+=n.toString(2).length/p);o`)

Explication

n =>   // anonymous function w/ arg `n`
  for( // loop
      o=0,  // initalize bit counter to zero
      p=n   // copy the input
    ;n-- // will decrease input every iteration, will decrease until it's zero
    ;o+=    // add to the bitcounter
        n.toString(2)  // the binary representation of the current itearations's
                     .length // length
        /p   // divided by input copy (to avergage)
   );o       // return o variable  

1

Hoon , 71 octets

|=
r/@
(^div (sun (roll (turn (gulf 0 (dec r)) xeb) add)) (sun r)):.^rq

... Je suis presque sûr que c'est la première fois que j'utilise les noyaux à virgule flottante de Hoon. Il s'agit en fait d'une implémentation écrite en Hoon qui se propage à SoftFloat, car les seuls types de données dans Hoon sont des atomes et des cellules.

Créer une fonction qui prend un atome, r. Créez une liste à partir de [0 .. (r - 1)], cartographiez la liste en prenant le logarithme binaire du nombre, puis repliez cette liste avec ++add. Convertissez à la fois la sortie du pli et ren @rq(nombres à virgule flottante à quadruple précision) avec++sun:rq , puis divisez-les l'une par l'autre.

La chose la plus étrange dans cet extrait est :.^rqla fin. a:ben Hoon signifie "évaluer a dans le contexte de b". ++rqest le noyau qui contient l'intégralité de l'implémentation quad-précision, comme une bibliothèque. Donc courir (sun 5):rqc'est la même chose que faire(sun:rq 5) .

Heureusement, les noyaux de Hoon sont comme des poupées gigognes; lorsque vous évaluez le bras ++rqpour obtenir le noyau, il y ajoute également tout le stdlib, de sorte que vous pouvez continuer à rouler et à tourner et à gouffre et toutes ces choses amusantes au lieu d'être coincé avec uniquement les bras définis dans ++rq. Malheureusement, rq redéfinit ++addêtre un ajout à virgule flottante à la place, sans avoir rdans son contexte. .(tout le contexte actuel), cependant.

Lors de l'évaluation d'une expression dans un contexte, le compilateur recherche d'abord la profondeur du membre. Dans notre cas, a:[. rq]il chercherait dans tout le contexte actuel aavant de passer à la recherche rq. Il en addsera de même pour la fonction qui fonctionne sur les atomes au lieu des nombres à virgule flottante ... mais il en sera de même div. Hoon a également une fonctionnalité où l'utilisation ^nameignorera la première référence trouvée et recherchera la seconde.

À partir de là, il utilise simplement le sucre syntaxique a^bégal à [a b]pour évaluer notre extrait de code à la fois avec notre contexte actuel et la bibliothèque flottante à quadruple précision, ignorant la division atomique en faveur de ++div:rq.

> %.  7
  |=
  r/@
  (^div (sun (roll (turn (gulf 0 (dec r)) xeb) add)) (sun r)):.^rq
.~~~2.1428571428571428571428571428571428

1

En fait, 7 octets:

;r♂├Σl/

Essayez-le en ligne!

Explication:

;r♂├Σl/
;        duplicate input
 r       push range(0, n) ([0, n-1])
  ♂├     map binary representation
    Σ    sum (concatenate strings)
     l/  divide length of string (total # of bits) by n

S'il n'y avait pas un bug que je viens de découvrir, cette solution fonctionnerait pour 6 octets:

r♂├♂læ

æ est la commande moyenne intégrée.


N'est-ce pas 10 octets? J'ai vérifié sur bytesizematters.com.
m654

1
@ m654 En fait, n'utilise pas UTF-8, il utilise CP437 (ou quelque chose comme ça).
Alex A.

@AlexA. Oh, je ne savais pas ça.
m654

1
@ m654 Bytesizematters utilise un encodage entièrement composé qui n'existe pas (et ne peut pas ) exister dans la pratique. Pour UTF-8, utilisez mothereff.in/byte-counter .
Dennis

@Dennis Merci pour l'info, je garderai cela à l'esprit.
m654


1

PowerShell v2 +, 64 octets

param($n)0..($n-1)|%{$o+=[convert]::ToString($_,2).Length};$o/$n

Mise en œuvre très simple de la spécification. Boucles de 0à $n-1avec |%{...}. A chaque itération, nous entrons [convert]notre numéro $_dans une chaîne de base 2et prenons le sien length. Nous accumulons cela en $o. Après les boucles, nous divisons simplement$o/$n , laissant cela sur le pipeline, et la sortie est implicite.

Tant que cela est, il est en fait plus court que la formule utilisée par Sp & autres, car [math]::Ceiling()il [math]::Log()est ridiculement verbeux. La conversion de base dans PowerShell est dégoûtante.


1

Perl 5.10, 54 octets

for(1..<>){$u+=length sprintf"%b",$_;$n++}$u/=$n;say$u

Assez simple. sprintf"%b"est un bon moyen de sortir un nombre en binaire en Perl sans utiliser de bibliothèques supplémentaires.

Essayez-le en ligne!


1

CJam, 13 12 11 octets

Un octet enregistré grâce à @ Sp3000 et un autre grâce à @ jimmy23013

rd_,2fbs,\/

Essayez-le en ligne!

Explication

Simple. Applique la définition.

rd      e# read input and convert to double 
_       e# duplicate 
,       e# range from 0 to input minus 1
2fb     e# convert each element of the array to binary 
s       e# convert to string. This flattens the array
,       e# length of array 
\       e# swap 
/       e# divide 

1

Jolf, 10 octets

/uΜr0xdlBH

Essayez-le ici!

Explication

/uΜr0xdlBH
  Μr0x      map range 0..x
      dlBH  over lengths of binary elements
/u          divide sum of this
            by implicit input (x)

1

Swift, 72 octets

func f(n:Double)->Double{return n<1 ?1:f(n-1)+1+floor(log2(n))}
f(N-1)/N

2
Vous n'avez pas besoin d'appeler la fonction, la laisser comme fonction définie est correcte. Bon premier post.
Rɪᴋᴇʀ

1

J, 15 octets

%~[:+/#@#:"0@i.

Il s'agit d'un verbe monadique, utilisé comme suit:

   f =: %~[:+/#@#:"0@i.
   f 7
2.14286

Essayez-le ici!

Explication

J'ai implémenté la spécification de défi assez littéralement. Il existe d'autres approches, mais toutes se sont avérées plus longues.

%~[:+/#@#:"0@i.  Input is y
             i.  Range from 0 to y-1.
          "0@    For each number in this range:
      #@           Compute the length of
        #:         its base-2 representation.
  [:+/           Take the sum of the lengths, and
%~               divide by y.
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.