Ortalama bit: ortalama bir zorluk


30

N> = 1 olan bir tamsayı verildiğinde, ortalama bit sayısını 0 - N - 1 arasında bir tamsayıda verir

Şartname

  • Çıktı, 0 ile N-1 arasındaki her bir tamsayının ikili gösterimindeki bit sayısının toplamı olarak N ile bölünerek hesaplanabilir.
  • Bir tamsayının ikili gösterimi, ikili bağlamda 0 olarak gösterilen sıfır dışında, bu bağlamda baştaki sıfırlara sahip değildir.
  • Çıktı en az 7 önemli rakam için doğru olmalıdır.

Örnek

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

Ortalama bit sayısı = (1 + 1 + 2 + 2 + 3 + 3) / 6 = 2

Test durumları

Giriş => çıkış

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

Afiş Parçacığı

( buradan )

Toplamı (ortalamayı bulmak için bölmeden önce) OEIS'te bir sekans olduğunu unutmayın .


6
Güzel isim, çok cılız .
Rɪᴋᴇʀ

3
Bilmeyen herkes için, açıklamaları olan çözümleri daha çok büyütmem daha olasıdır
trichoplax

4
Yeterli püf noktası değil, bunun mükemmel olması için biraz daha fazlasına ihtiyacınız var .
clismique

1
Sanıyorum ki "her sayı" derken "her tam sayı " mı demek istiyorsunuz ?
Cyoce

@Cyoce evet, bunu belirttiğiniz için teşekkür ederiz - Açıklığa kavuşturmak için düzenleme yaptım.
trichoplax

Yanıtlar:


13

Pyth, 6 bayt

.Oml.B

Burada çevrimiçi deneyin .

.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

İlk etapta ortak ama lider panosunda görünmüyordun - Ben düzeltmek için başlığında küçük bir düzenleme yaptım.
trichoplax

9

Jöle, 6 bayt

R’BFL÷

Çevrimiçi deneyin!

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 bayt

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

açıklama

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

İdeone üzerinde örnek çalışması .


6

Python 3, 43 bayt

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

OEIS sayfasındaki formülü kullanır . Şaşırtıcı bir şekilde, adlandırılmış bir fonksiyon atama nedeniyle bir şekilde burada daha ucuzdur x.

46 bayt için alternatif yaklaşım:

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

Ne yazık ki, -~çünkü gerekli (0).bit_length()olan 0, ama o zaman bile çok uzun bir bayt olurdu.


6

Julia, 27 bayt

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

Çevrimiçi deneyin!

Nasıl çalışır

*Julia'da dize bitiştirme olduğundan , bir dizi dizgiyi bitiştirmek prodiçin kullanılabilir. İsteğe bağlı olarak, fiili "ürünü" almadan önce ikincisi üzerinde eşleştiği ilk argüman olarak bir işlev görür, bu nedenle prod(bin,0:n-1)istenen aralıktaki tüm tam sayıların ikili gösteriminin dizesidir. Uzunluğun n ile alınması endofve n'ye bölünmesi , ortalama değeri verir.


5

Julia, 28 bayt

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

Yana binotomatik diziler üzerinde eşleşmiyor, Kullandığımız ceil(log2(n))bit sayısını almak için n-1. Bu iyi a:bsonuç verir, çünkü Julia'nın gösterimi her iki ucunda da bulunur, yani 2:n2'den 2'ye kadar bir aralıktır n, ancak aralıktaki sayılar için bit sayısını gerçekten hesaplıyoruz 1:n-1. Maalesef, 20 hesap yapmak için fazladan bir işlem yapmamız gerekiyor .

Çevrimiçi deneyin!


5

MATL, 9 bayt

q:ZlksG/Q

Çevrimiçi Deneyin!

Tüm test durumları ile değiştirilmiş sürüm

açıklama

    % 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

Çekin !! (dolgu)
David,

@David Aslında, seninki haklıydı. Girişi başında çoğaltmak diğer değerler için işe yaramaz ... G/Qsonunda ihtiyacın var .
beher

5

MATL, 9 bayt

:qBYszQG/

Çevrimiçi deneyin!

açıklama

: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

Jöle, 8 bayt

Kısa değil, ama ilginç bir algoritma ve ilk Jelly gönderim:

Rl2Ċ»1S÷

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

4

Jöle, 10 bayt

BL©2*2_÷+®

Sp3000'ün önerisinden.

Burada dene.

Jöle, 11 bayt

æḟ2’Ḥ÷_BL$N

Çok kısa değil ama bazı ipuçlarına ihtiyacım var.

Burada dene.

Sp3000'in cevabındakiyle aynı formülü kullanmak . (Geometrik ilerlemeyi ayırt ederek kendin elde etmek çok zor değil.)


Referansınız için Jelly cevabıma bakın .
Leaky Nun

@LeakyNun Farklı bir yaklaşım kullanıyor, ki bu sizinkinden daha kısa olacağını sanmıyorum. Ama _BL$Nçok uzun görünüyordu ...
jimmy23013

Yani temelde, kodunuz "en yakın 2, eksi 1, çift, girişe göre bölme, eksi girişin ikili uzunluğu, negatif" değerine kadar olan taban mı?
Leaky Nun

@LeakyNun Evet ..
jimmy23013

3
Sadece marjinal açıdan daha iyi:BL©2*2_÷+®
Sp3000

4

Java, 135 95 90 bayt

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

Arayüzden kurtulabileceğinizi ve sadece bir fonksiyon veya lambda oluşturabileceğinizi düşünüyorum. Ayrıca stdout'a yazdırmak yerine değeri geri getirebilirsiniz
Frozn

Tamam, bu kuralları uygulayacağım.
Shaun Wild

Bence izin verilmeli. OP hiçbir şey belirtmediğinden, standart G / Ç kurallarının geçerli olduğunu düşünüyorum .
Frozn

Evet, bir işlev iyi - eksiksiz bir programa ihtiyacınız yok. Skor tablosunun skoru ilk satırda
topladığına dikkat

@trichoplax Hala son yer. Java'yı kişisel olarak suçluyorum ...
Shaun Wild

3

Python 3, 46 Bayt

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

Gibi ara

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

5 numaralı giriş için başarısız olduğu için harita revizyonunu geri almalıydım.


3

05AB1E, 9 7 bayt

Kod:

L<bJg¹/

Açıklama:

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

Çevrimiçi deneyin

Düzenleme: @Adnan sayesinde 2 bayt kaydedildi


@Adnan: Teşekkürler!
J.'yi

3

C #, 87 bayt

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

C # cevabı yazdım çünkü bir tane görmedim. Bu benim bunlardan birine ilk gönderim, bu yüzden yanlış bir şey yapıyorum, lütfen bana bildirin.


Programming Puzzles ve Code Golf'a hoş geldiniz. Bu harika bir ilk cevap, +1. Bir bayttan tasarruf doubleetmek floatiçin değiştirebilir misiniz , yoksa hassasiyete mi ihtiyacınız var?
wizzwizz4 18

2
@ wizzwizz4 Teşekkürler! Ben de aynı düşünceyi yaşadım, ancak Average () ikiye katladı. Dönüş tipimi float olarak değiştirirsem, açıkça double'ı atmam ve bunun üzerine 7 byte kazanmam gerekir.
58’de

2

JavaScript (ES7), 38 32 bayt

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

@ Sp3000'in formülünü kullanma (önceki sürüm özyinelemeli bir çözümdü). 34 bayt için ES6 sürümü:

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

Formül açıklaması: N = 55 durumunu düşünün. İkili sayıları yazarsak (yerden tasarruf için dikey olarak), şunu alırız:

                                11111111111111111111111
                111111111111111100000000000000001111111
        11111111000000001111111100000000111111110000000
    111100001111000011110000111100001111000011110000111
  11001100110011001100110011001100110011001100110011001
0101010101010101010101010101010101010101010101010101010

Bu dikdörtgenin boyutudur nl ortalama sadece bu yüzden lt ama biz boşlukları hariç tutmanız gerekir. Her boşluk sırası bir öncekinden iki kat daha fazladır, bu nedenle toplam 2 + 4 + 8 + 16 + 32 = 64 - 2 = 2 1 - 2'dir.


2

J, 21 17 15 bayt

@Dennis sayesinde 17 bayttan 15 bayta kadar.

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

Birisi bunu golf etmeme yardım edebilir mi?

Ungolfed versiyonu

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

İkili rakamlarıyla listesini stringifying tarafından, alternatif bir yaklaşım denedik ve 25 byte ile çıktı: %~>:@#@([:":10#.[:#:i.)-]. Çözümünüz oldukça uygun görünüyor.
Conor O'Brien

2

Perl 6 ,  34  32 bayt

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

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

Açıklama:

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

Ölçek:

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 bayt

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

Hangi sayı biçimlerinin çıktıda kabul edilebilir olduğuna göre oranlar tamam gibi görünüyor.

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

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

ungolfed (ve açıklama kolaylığı için biraz yeniden yazılmıştır)

(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

kullanılan eski cevap (şamandıra):

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

çıktı şöyle:

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

Kesirlerin veya oranların kabul edilebilir olup olmadığı sorusu daha önce gündeme gelmemişti. Bu zorluk için , temerrüdun ne olması gerektiği konusunda ne fikir birliğine varıldığını kabul edeceğim .
trichoplax

1

Minkolang 0.15 , 23 bayt

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

Burada dene!

açıklama

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.

Oldukça basit uygulama.


1

JavaScript ES5, 55 bayt

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

açıklama

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 bayt

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

... Hoon'un kayan nokta çekirdeğini ilk kullandığımda bunun gerçekten olduğuna eminim. Aslında Hoon'da yazılı olan SoftFloat'a çıkan bir uygulama, çünkü Hoon'daki tek veri türü atomlar ve hücreler.

Bir atom alan bir fonksiyon yarat r. [0 .. (r - 1)] 'den bir liste oluşturun, sayının ikili logaritmasını alarak listenin üzerinde haritalayın ve ardından listeyi üzerinde gezdirin ++add. Kat çıkışını ve her iki dönüştürme riçin @rqolan (dört hassas kayan nokta sayısı) ++sun:rq, ve daha sonra diğer tek bölün.

Bu pasajdaki en garip şey :.^rqsonunda. a:bHoon'da "a'yı b bağlamında değerlendir" anlamına gelir. ++rqbir kütüphane gibi dörtlü hassas uygulamayı içeren çekirdek. Yani koşmak (sun 5):rq, yapmakla aynı şeydir (sun:rq 5).

Neyse ki, Hoon'daki göbekler yuva yapan bebekler gibidir; ++rqçekirdeği elde etmek için kolu değerlendirdiğinizde, stdlib'in tamamını de ekler, böylece sadece tanımlanmış silahlarla sıkışmak yerine yuvarlanma, dönme ve uçma ve bu eğlenceli şeyleri alırsınız ++rq. Ne yazık ki, rq , bağlamında ++addolmamakla birlikte, kayan nokta ekleme olduğunu yeniden tanımlıyor r. .(tüm mevcut bağlamda), ancak öyle.

Bir bağlamdaki bir ifadeyi değerlendirirken, derleyici ilk önce uzuv derinliğini arar. Bizim durumumuzda içine bakmadan önce a:[. rq]tüm mevcut bağlamda bakacaktı . Böylece , kayan nokta sayıları yerine atomlar üzerinde çalışan işleve bakacağız ... ama olacak . Hoon, kullanmanın ilk bulunan referansı görmezden geleceği ve ikincisini arayacağı bir özelliğe sahiptir .arqadddiv^name

Buradan, snippet'imizi hem güncel bağlamımızla hem de dörtlü hassas şamandıra kütüphanesi ile değerlendirmek için a^beşit olmanın syntatik şekerini kullanıyor [a b], atomik dalgayı lehine görmezden geliyor ++div:rq.

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

1

Aslında, 7 bayt:

;r♂├Σl/

Çevrimiçi deneyin!

Açıklama:

;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

Yeni keşfettiğim bir hata olmasaydı, bu çözüm 6 bayt için işe yarayacaktı:

r♂├♂læ

æ yerleşik ortalama komutu.


Bu 10 bayt değil mi? Bytesizematters.com adresinde kontrol ettim.
m654

1
@ m654 Aslında UTF-8 kullanmıyor, CP437 kullanıyor (veya buna benzer bir şey).
Alex A.

@AlexA. Oh, bunu bilmiyordum.
m654

1
@ m654 Bytesizematters pratikte bulunmayan (ve yapamayan ) tamamen yapılmış bir kodlamayı kullanır . UTF-8 için mothereff.in/byte-counter dosyasını kullanın .
Dennis,

@Dennis Bilgi için teşekkürler, aklımda tutacağım.
m654


1

PowerShell v2 +, 64 bayt

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

Spesifikasyonun çok basit bir şekilde uygulanması. Döngüler 0için $n-1birlikte |%{...}. Her yineleme, biz [convert]bizim giriş numarası $_bir dize tabanına 2ve amaçlarını almak length. Bunu biriktirdik $o. Döngülerden sonra, basitçe bölünerek $o/$n, bunu boru hattında bıraktık ve çıktı çok açık.

Çünkü sürece bu olduğu gibi, o, Sp & diğerleri kullandığınızı formülü daha doğrusu daha kısa [math]::Ceiling()ve [math]::Log()gülünç uzun. PowerShell'deki temel dönüştürme işlemi çok kolaydır.


1

Perl 5.10, 54 bayt

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

Hemen hemen anlaşılır. sprintf"%b"ek kitaplıklar kullanmadan ikili sayı olarak Perl'de çıktı almak için temiz bir yoldur.

Çevrimiçi deneyin!


1

CJam, 13 12 11 bayt

Bir bayt @ Sp3000 ve diğeri @ jimmy23013 sayesinde kaydedildi

rd_,2fbs,\/

Çevrimiçi deneyin!

açıklama

Basit. Tanımı uygular.

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 bayt

/uΜr0xdlBH

Burada dene!

açıklama

/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 bayt

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

2
Fonksiyonu çağırmanıza gerek yoktur, tanımlanmış bir fonksiyon tamamdır. Güzel ilk mesaj.
Rɪᴋᴇʀ

1

J, 15 bayt

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

Bu, monadik bir fiildir ve şu şekilde kullanılır:

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

Burada dene!

açıklama

Gerçekten meydan okuma özelliğini uyguladım. Başka yaklaşımlar da var, fakat hepsinin daha uzun olduğu ortaya çıktı.

%~[:+/#@#:"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.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.