Bit medi: una sfida media


30

Dato un numero intero N> = 1, visualizza il numero medio di bit in un numero intero da 0 a N - 1

specificazione

  • L'output può essere calcolato come la somma del numero di bit nella rappresentazione binaria di ciascun numero intero da 0 a N-1, diviso per N.
  • La rappresentazione binaria di un numero intero non ha zeri iniziali in questo contesto, ad eccezione di zero, che è rappresentato come 0 in binario.
  • L'output deve essere accurato per almeno 7 cifre significative.

Esempio

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

Numero medio di bit = (1 + 1 + 2 + 2 + 3 + 3) / 6 = 2

Casi test

Input => output

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

Snippet della classifica

(da qui )

Si noti che la somma (prima di dividere per trovare la media) è una sequenza su OEIS .


6
Bel nome, molto puntuale .
Rɪᴋᴇʀ

3
Per chiunque non lo sappia, ho maggiori probabilità di votare soluzioni con una spiegazione
trichoplax,

4
Non abbastanza giochi di parole, hai bisogno di un po 'di più perché questo sia perfetto.
clismique,

1
Suppongo che per "ogni numero" intendi "ogni numero intero "?
Cyoce,

@Sì sì, grazie per averlo sottolineato - ho modificato per chiarire.
trichoplax,

Risposte:


13

Pyth, 6 byte

.Oml.B

Provalo online qui .

.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

Primo posto comune ma non ti sei presentato in classifica: ho apportato una modifica minore all'intestazione per risolverlo.
trichoplax,

9

Gelatina, 6 byte

R’BFL÷

Provalo online!

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

Ottava, 29 byte

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

Spiegazione

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

Esempio eseguito su ideone .


6

Python 3, 43 byte

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

Utilizza la formula nella pagina OEIS . Sorprendentemente, una funzione denominata è in qualche modo più economica qui a causa dell'assegnazione a x.

Approccio alternativo per 46 byte:

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

Sfortunatamente, -~è necessario poiché (0).bit_length()è 0, ma anche allora sarebbe un byte troppo lungo.


6

Julia, 27 byte

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

Provalo online!

Come funziona

Poiché *è la concatenazione di stringhe in Julia, prodpuò essere utilizzata per concatenare una matrice di stringhe. Opzionalmente prende una funzione come primo argomento da mappare sul secondo prima di prendere il "prodotto" reale, quindi prod(bin,0:n-1)è la stringa della rappresentazione binaria di tutti gli interi nell'intervallo desiderato. Prendendo la lunghezza con endofe dividendo per n si ottiene la media.


5

Julia, 28 byte

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

Poiché binnon esegue automaticamente la mappatura su array, stiamo utilizzando ceil(log2(n))per ottenere il numero di bit n-1. Questo funziona bene perché la a:bnotazione di Julia è inclusiva su entrambe le estremità, quindi 2:nè un intervallo da 2 a n, ma stiamo davvero calcolando il numero di bit per i numeri nell'intervallo 1:n-1. Purtroppo, però, dobbiamo aggiungere un extra 2per tenere conto di 0.

Provalo online!


5

MATL, 9 byte

q:ZlksG/Q

Provalo online!

Versione modificata con tutti i casi di test

Spiegazione

    % 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

Snap !! (riempimento)
David

@David In realtà, il tuo era corretto. La duplicazione dell'ingresso all'inizio non funziona per altri valori ... G/Qalla fine è necessario.
becher

5

MATL, 9 byte

:qBYszQG/

Provalo online!

Spiegazione

: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

Gelatina, 8 byte

Algoritmo non più breve, ma interessante, e la mia prima presentazione su Jelly:

Rl2Ċ»1S÷

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

4

Gelatina, 10 byte

BL©2*2_÷+®

Dal suggerimento di Sp3000.

Provalo qui.

Gelatina, 11 byte

æḟ2’Ḥ÷_BL$N

Non molto breve ma ho bisogno di alcuni consigli.

Provalo qui.

Usando la stessa formula della risposta di Sp3000 . (Non è molto difficile ottenerlo da soli, differenziando la progressione geometrica.)


Guarda la mia risposta Jelly per il tuo riferimento.
Leaky Nun,

@LeakyNun Sta usando un approccio diverso, che non credo sarebbe mai più corto del tuo. Ma _BL$Nsembrava abbastanza lungo ...
jimmy23013,

Quindi, fondamentalmente, il tuo codice è "piano alla potenza più vicina di 2, meno 1, doppio, dividi per input, meno lunghezza binaria di input, negativo"?
Leaky Nun,

@LeakyNun Sì ..
jimmy23013

3
Solo leggermente migliore:BL©2*2_÷+®
Sp3000,

4

Java, 135 95 90 byte

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

Penso che tu possa sbarazzarti dell'interfaccia e semplicemente creare una funzione o lambda. Inoltre puoi restituire il valore invece di stamparlo su stdout
Frozn,

Ok, mi metterò in atto con quelle regole.
Shaun Wild,

Penso che dovrebbe essere permesso. Poiché l'OP non ha specificato nulla, penso che si applichino le regole I / O standard .
Frozn,

Sì, una funzione va bene - non è necessario un programma completo. Nota che la classifica raccoglie il punteggio sulla prima riga, quindi il tuo punteggio attualmente mostra 135 invece di 95.
trichoplax

@trichoplax Ancora l'ultimo posto. Incolpo Java personalmente ...
Shaun Wild

3

Python 3, 46 byte

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

Chiamalo come

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

Ho dovuto ripristinare la revisione della mappa perché non è riuscita per l'immissione di 5


3

05AB1E, 9 7 byte

Codice:

L<bJg¹/

Spiegazione:

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

Provalo online

Modifica: salvato 2 byte grazie a @Adnan


@Adnan: grazie! Dimenticato J.
Emigna,

3

C #, 87 byte

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

Ho scritto una risposta in C # perché non ne ho vista una. Questo è il mio primo post in uno di questi, quindi per favore fatemi sapere se sto facendo qualcosa di sbagliato.


Benvenuti in Programming Puzzle and Code Golf. Questa è un'ottima prima risposta, +1. Potresti passare doublea floatper salvare un byte o hai bisogno della precisione?
wizzwizz4,

2
@wizzwizz4 Grazie! Ho avuto lo stesso pensiero, ma Average () restituisce un doppio. Se cambio il mio tipo di ritorno in float, allora devo esplicitamente lanciare il doppio e guadagnare 7 byte su quello.
Raive

2

JavaScript (ES7), 38 32 byte

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

Usando la formula di @ sp3000 (la versione precedente era una soluzione ricorsiva). Versione ES6 per 34 byte:

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

Spiegazione della formula: considerare il caso di N = 55. Se scriviamo i numeri binari (in verticale per risparmiare spazio), otteniamo:

                                11111111111111111111111
                111111111111111100000000000000001111111
        11111111000000001111111100000000111111110000000
    111100001111000011110000111100001111000011110000111
  11001100110011001100110011001100110011001100110011001
0101010101010101010101010101010101010101010101010101010

La dimensione di questo rettangolo è nl quindi la media è solo l ma dobbiamo escludere gli spazi vuoti. Ogni riga di spazi vuoti è doppia rispetto alla precedente, quindi il totale è 2 + 4 + 8 + 16 + 32 = 64 - 2 = 2 l - 2.


2

J, 21 17 15 byte

Da 17 byte a 15 byte grazie a @Dennis.

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

Qualcuno può aiutarmi a giocare a golf? ...

Versione Ungolfed

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

Ho provato un approccio alternativo, dal stringifying l'elenco dei numeri binari, ed è venuto fuori con 25 byte: %~>:@#@([:":10#.[:#:i.)-]. La tua soluzione sembra piuttosto ottimale.
Conor O'Brien,

2

Perl 6 ,  34  32 byte

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

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

Spiegazione:

{ 
  $_  # 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
}

Test:

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 byte

(+/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 byte

Sembra che i rapporti siano ok secondo Quali formati numerici sono accettabili nell'output?

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

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

non golfato (e leggermente riscritto per facilitare la spiegazione)

(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

vecchia risposta che ha usato (float):

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

l'output è come:

  • n = 1 => 1.0
  • n = 7 => 2.142857

La questione se le frazioni o i rapporti siano accettabili non era stata sollevata prima. Per questa sfida accetterò qualunque consenso venga raggiunto su quale dovrebbe essere il valore predefinito .
trichoplax,

1

Minkolang 0,15 , 23 byte

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

Provalo qui!

Spiegazione

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.

Implementazione piuttosto diretta.


1

JavaScript ES5, 55 byte

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

Spiegazione

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 byte

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

... Sono abbastanza sicuro che questa sia in realtà la prima volta che uso i nuclei in virgola mobile di Hoon. In realtà è un'implementazione scritta in Hoon che si riversa su SoftFloat, poiché gli unici tipi di dati in Hoon sono atomi e celle.

Creare una funzione che prende un atomo, r. Creare un elenco da [0 .. (r - 1)], mappare l'elenco prendendo il logaritmo binario del numero, quindi piegare l'elenco con ++add. Converti sia l'output della piega cher in@rq (numeri in virgola mobile di precisione quadrupla) con++sun:rq , quindi dividi uno per l'altro.

La cosa più strana in questo frammento è :.^rqla fine. a:bin Hoon significa "valutare a nel contesto di b". ++rqè il nucleo che contiene l'intera implementazione quad-precision, come una libreria. Così in esecuzione(sun 5):rq è la stessa cosa che fare(sun:rq 5) .

Fortunatamente, i nuclei di Hoon sono come delle bambole che nidificano; quando valuti il ​​braccio ++rqper ottenere il nucleo, aggiunge anche l'intero stdlib, in modo da poter continuare a rotolare, girare e abboccare e tutte quelle cose divertenti invece di essere bloccato con solo le braccia definite ++rq. Sfortunatamente, rq ridefinisce ++addinvece l'aggiunta in virgola mobile, non avendo rnel suo contesto. .(l'intero contesto attuale), tuttavia.

Quando si valuta un'espressione in un contesto, il compilatore cerca la profondità dell'arto per prima. Nel nostro caso a:[. rq]cercherebbe nell'intero contesto attuale aprima di passare a guardare dentro rq. Quindi addcercherà la funzione che funziona sugli atomi anziché sui numeri in virgola mobile ... ma così sarà div. Hoon ha anche una funzione in cui l'utilizzo ^nameignorerà il primo riferimento trovato e cercherà il secondo.

Da lì, sta semplicemente usando lo zucchero sintatico a^bdell'essere pari a [a b]valutare il nostro frammento sia con il nostro contesto attuale sia con la libreria float quad-precisione, ignorando il div atomico a favore ++div:rq.

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

1

In realtà, 7 byte:

;r♂├Σl/

Provalo online!

Spiegazione:

;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

Se non fosse per un bug che ho appena scoperto, questa soluzione funzionerebbe per 6 byte:

r♂├♂læ

æ è il comando medio incorporato.


Non sono 10 byte? Ho controllato su bytesizematters.com.
m654,

1
@ m654 In realtà non usa UTF-8, usa CP437 (o qualcosa del genere).
Alex A.

@AlexA. Oh, non lo sapevo.
m654,

1
@ m654 Bytesizematters utilizza una codifica completamente inventata che non esiste (e non può ) in pratica. Per UTF-8, utilizzare mothereff.in/byte-counter .
Dennis,

@Dennis Grazie per le informazioni, lo terrò a mente.
m654,

1

Vitsy, 26 byte

Questo è un primo tentativo, lo scriverò di più e aggiungerò una spiegazione in seguito.

0vVV1HV1-\[2L_1+v+v]v1+V/N

Provalo online!


1

PowerShell v2 +, 64 byte

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

Implementazione molto semplice delle specifiche. Cicli da 0a $n-1con |%{...}. Ogni iterazione, abbiamo il [convert]nostro numero di input $_in una base di stringa 2e prendiamo il suo length. Lo accumuliamo in $o. Dopo i loop, ci dividiamo semplicemente$o/$n , lasciandolo sulla pipeline e l'output è implicito.

Finché è così, in realtà è più breve della formula che Sp e altri stanno usando, poiché [math]::Ceiling()e [math]::Log()sono ridicolmente prolissi. La conversione di base in PowerShell è schifosa.


1

Perl 5,10, 54 byte

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

Praticamente semplice. sprintf"%b"è un modo semplice per generare un numero in binario in Perl senza usare librerie aggiuntive.

Provalo online!


1

CJam, 13 12 11 byte

Un byte salvato grazie a @ Sp3000 e un altro grazie a @ jimmy23013

rd_,2fbs,\/

Provalo online!

Spiegazione

Semplice. Applica la definizione

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 byte

/uΜr0xdlBH

Provalo qui!

Spiegazione

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

1

Rapido, 72 byte

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

2
Non è necessario chiamare la funzione, lasciarla come funzione definita va bene. Bel primo post.
Rɪᴋᴇʀ

1

J, 15 byte

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

Questo è un verbo monadico, usato come segue:

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

Provalo qui!

Spiegazione

Ho implementato le specifiche della sfida piuttosto letteralmente. Esistono altri approcci, ma tutti si sono rivelati più lunghi.

%~[:+/#@#:"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.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.