平均ビット:平均的な課題


30

整数N> = 1の場合、0からN-1の整数の平均ビット数を出力します

仕様

  • 出力は、0からN-1までの各整数のバイナリ表現のビット数の合計をNで割って計算できます。
  • 整数のバイナリ表現には、このコンテキストでは先行ゼロがありません。ただし、ゼロはバイナリで0として表されます。
  • 出力は、少なくとも7つの有効数字まで正確でなければなりません。

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

平均ビット数=(1 + 1 + 2 + 2 + 3 + 3)/ 6 = 2

テストケース

入力=>出力

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

リーダーボードスニペット

ここから)

合計(平均を求めるために分割する前)はOEISのシーケンスであることに注意してください。


6
素敵な名前、とてもおかしい
Rɪᴋᴇʀ

3
知らない人のために、私は説明で解決策を
支持

4
駄洒落が足りません。これを完璧にするにはもう少し必要です。
clismique

1
「各数字」とは「各整数」を意味すると思いますか?
チョイス

@Cyoceはい、それを指摘してくれてありがとう-私は明確にするために編集しました。
-trichoplax

回答:




7

オクターブ、29バイト

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

説明

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

ideoneでのサンプル実行。


6

Python 3、43バイト

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

OEISページの式を使用します。驚くべきことに、名前付き関数はに割り当てられているため、ここではなんとなく安くなっていますx

46バイトの代替アプローチ:

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

残念ながら、は-~が必要なので、が必要(0).bit_length()ですが0、それでも1バイトは長すぎます。


6

ジュリア、27バイト

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

オンラインでお試しください!

使い方

*Juliaでは文字列の連結なのでprod、文字列の配列を連結するために使用できます。オプションで、実際の「製品」を取得する前に2番目の関数にマップする関数を最初の引数として受け取ります。したがってprod(bin,0:n-1)、目的の範囲のすべての整数のバイナリ表現の文字列も同様です。長さをnendofで割って平均を求めます。


5

ジュリア、28バイト

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

以来bin、自動的に配列の上にマッピングされていない、我々は、使用しているceil(log2(n))のビット数を取得しますn-1。ジュリアのa:b表記法は両端を含むため2:n2〜の範囲であるため、これはうまく機能しnますが、実際には範囲内の数値のビット数を計算しています1:n-1。残念ながら、私たちは余分に取り組む必要があります2 0を考慮するためにをする必要があります。

オンラインでお試しください!


5

MATL、9バイト

q:ZlksG/Q

オンラインでお試しください!

すべてのテストケースを含む修正版

説明

    % 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

スナップ!!(フィラー)
デビッド

@David実際、あなたのものは正しかった。最初に入力を複製しても、他の値では機能しません... G/Q最後に必要です。
ビーカー

5

MATL、9バイト

:qBYszQG/

オンラインでお試しください!

説明

: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

ゼリー、8バイト

短くはありませんが、興味深いアルゴリズム、そして私の最初のゼリーの提出:

Rl2Ċ»1S÷

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

4

ゼリー、10バイト

BL©2*2_÷+®

Sp3000の提案から。

ここで試してみてください。

ゼリー、11バイト

æḟ2’Ḥ÷_BL$N

それほど短くはありませんが、いくつかのヒントが必要です。

ここで試してみてください。

Sp3000の回答と同じ式を使用します。(幾何学的進行を区別することにより、自分で取得することはそれほど難しくありません。)


あなたの参考のために私のゼリーの答えを見てください。
リーキー修道女

@LeakyNun異なるアプローチを使用していますが、あなたのアプローチよりも短くなるとは思いません。しかし、_BL$Nかなり長いように見えた
...-jimmy23013

それで基本的に、あなたのコードは「最も近い2のべき乗からマイナス1、倍、入力で除算、入力のバイナリ長さをマイナス、負」ですか?
リーキー修道女

@LeakyNunはい
。– jimmy23013

3
わずかに良いだけ:BL©2*2_÷+®
Sp3000

4

Java、135 95 90バイト

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

インターフェイスを削除して、関数またはラムダを作成することができると思います。また、値をstdoutに出力する代わりに返すことができます
-Frozn

さて、これらのルールを使用して再実装します。
ショーンワイルド

許されるべきだと思う。OPは何も指定しなかったため、標準のI / Oルールが適用されると思います。
-Frozn

はい、機能は問題ありません-完全なプログラムは必要ありません。リーダーボードが最初の行でスコアを
取得する

@trichoplaxまだ最後の場所。私は...個人的にJavaのを非難
ショーン・ワイルド

3

Python 3、46バイト

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

のように呼ぶ

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

5の入力で失敗したため、マップリビジョンを元に戻す必要がありました


3

05AB1E、9 7バイト

コード:

L<bJg¹/

説明:

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

オンラインで試す

編集:@Adnanのおかげで2バイト節約


@アドナン:ありがとう!Jを忘れた
エミグナ

3

C#、87バイト

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

表示されなかったため、C#の回答を作成しました。これはこれらの1つへの私の最初の投稿です。


プログラミングパズルとコードゴルフへようこそ。これは素晴らしい最初の回答、+ 1です。に変更doublefloatて1バイトを保存できますか、それとも精度が必要ですか?
wizzwizz4

2
@ wizzwizz4ありがとう!私は同じ考えを持っていましたが、Average()はdoubleを返します。戻り値の型をfloatに変更した場合、doubleを明示的にキャストし、その上で7バイトを獲得する必要があります。
レイブ

2

JavaScript(ES7)、38 32バイト

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

@ sp3000の式を使用(以前のバージョンは再帰的なソリューションでした)。34バイトのES6バージョン:

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

式の説明:N = 55の場合を考えます。(スペースを節約するために)2進数を書き込むと、次のようになります。

                                11111111111111111111111
                111111111111111100000000000000001111111
        11111111000000001111111100000000111111110000000
    111100001111000011110000111100001111000011110000111
  11001100110011001100110011001100110011001100110011001
0101010101010101010101010101010101010101010101010101010

この長方形のサイズはnlなので、平均はちょうどlですが、空白を除外する必要があります。空白の各行は前の2倍の長さなので、合計は2 + 4 + 8 + 16 + 32 = 64-2 = 2 l -2です。


2

J、21 17 15バイト

@Dennisのおかげで17バイトから15バイトになりました。

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

誰でもこれをゴルフするのを手伝ってもらえますか?...

ゴルフされていないバージョン

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

2進数のリストを文字列化することにより、別の方法を試しましたが、25バイトで出てきました%~>:@#@([:":10#.[:#:i.)-]。ソリューションはかなり最適に見えます。
コナーオブライエン

2

Perl 6の 34の  32バイト

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

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

説明:

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

テスト:

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バイト

(+/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バイト

どの数値形式が出力で受け入れられるかによると、比率は問題ないように見えます。

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

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

ungolfed(説明を簡単にするためにわずかに書き直し)

(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

(float)を使用した古い回答:

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

出力は次のようになります。

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

分数または比率が許容できるかどうかの問題は、これまで提起されていませんでした。この挑戦のために、私はデフォルトがどうあるべきであるかに関してコンセンサスに達するどんなものも受け入れます
-trichoplax


1

JavaScript ES5、55バイト

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

説明

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

フーン、71バイト

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

... Hoonの浮動小数点コアを使用したのは、これが実際には初めてだと確信しています。Hoonのデータ型は原子とセルのみであるため、実際にはHoonで記述された実装でSoftFloatに出力されます。

アトムを受け取る関数を作成しますr。[0 ..(r-1)]からリストを作成し、数値の2進対数を取得してリストをマッピングし、でリストを折り返し++addます。変換倍の出力との両方r@rq(4倍精度浮動小数点数)と++sun:rqし、次いで他のずつ分割します。

このスニペットで最も奇妙なのは:.^rq、最後です。a:bHoonでは、「bのコンテキストでaを評価する」という意味です。++rqライブラリなど、4倍精度の実装全体を含むコアです。したがって、実行(sun 5):rqは実行と同じです(sun:rq 5)

幸いなことに、Hoonのコアは入れ子人形のようなものです。++rqコアを取得するためにアームを評価すると、stdlib全体が追加されます。そのため、で定義されたアームだけで立ち往生するのはなく、ロール、ターン、湾などの楽しいものを保持できます++rq。不幸なことに、rqは++add代わりに浮動小数点加算を再定義しr、そのコンテキストには含まれません。.(ただし、現在のコンテキスト全体)はそうします。

コンテキスト内の式を評価する場合、コンパイラーは深さ優先で四肢を探します。私たちの場合、a:[. rq]それは現在のコンテキスト全体aを見てから見ることになりrqます。だから、add原子の代わりに、浮動小数点数に働く機能を検索します...しかし、そうでしょうdiv。Hoonには、^nameが最初に見つかった参照を無視し、2番目の参照を探すあります。

そこから、単にa^b等しいというシンタックスシュガーを使用[a b]して、現在のコンテキストと4倍精度浮動小数点ライブラリの両方でスニペットを評価し、アトミックdivを無視し++div:rqます。

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

1

実際には、7バイト:

;r♂├Σl/

オンラインでお試しください!

説明:

;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

If it weren't for a bug that I just discovered, this solution would work for 6 bytes:

r♂├♂læ

æ is the builtin mean command.


Isn't this 10 bytes? I checked at bytesizematters.com.
m654

1
@m654 Actually doesn't use UTF-8, it uses CP437 (or something like that).
Alex A.

@AlexA. Oh, didn't know that.
m654

1
@m654 Bytesizematters uses a completely made up encoding that does not (and cannot) exist in practice. For UTF-8, use mothereff.in/byte-counter.
Dennis

@Dennis Thanks for the info, I'll keep that in mind.
m654


1

PowerShell v2+, 64 bytes

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

Very straightforward implementation of the spec. Loops from 0 to $n-1 with |%{...}. Each iteration, we [convert] our input number $_ to a string base2 and take its length. We accumulate that in $o. After the loops, we simply divide $o/$n, leaving that on the pipeline, and output is implicit.

As long as this is, it's actually shorter than the formula that Sp & others are using, since [math]::Ceiling() and [math]::Log() are ridiculously wordy. Base conversion in PowerShell is yucky.


1

Perl 5.10, 54 bytes

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

Pretty much straightforward. sprintf"%b" is a neat way to output a number in binary in Perl without using additional libraries.

Try it online!


1

CJam, 13 12 11 bytes

One byte saved thanks to @Sp3000, and another thanks to @jimmy23013

rd_,2fbs,\/

Try it online!

Explanation

Straightforward. Applies the definition.

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 bytes

/uΜr0xdlBH

Try it here!

Explanation

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

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

2
You don't need to call the function, leaving it as a defined function is okay. Nice first post.
Rɪᴋᴇʀ

1

J, 15 bytes

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

This is a monadic verb, used as follows:

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

Try it here!

Explanation

I implemented the challenge spec pretty literally. There are other approaches, but all turned out to be longer.

%~[:+/#@#:"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.
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.