中位数:平均挑战


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
对于不认识的人,我更有可能提出解释来支持解决方案
trichoplax

4
没有足够的双关语,你需要一点更多的这是完美的。
clismique '16

1
我假设用“每个数字”表示“每个整数 ”?
Cyoce

@Cyoce是的,谢谢您指出-我已进行编辑以澄清问题。
trichoplax

Answers:


13

Pyth,6个字节

.Oml.B

在这里在线尝试

.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

并列第一名,但您并未出现在排行榜上-我对标题进行了较小的修改以解决该问题。
trichoplax

9

果冻,6个字节

R’BFL÷

在线尝试!

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

八度,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!)

样品在亚乙基酮上运行。


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,所以必须是,但是即使那样也将是一个字节太长。


6

朱莉娅,27个字节

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

在线尝试!

怎么运行的

由于*在Julia中是字符串连接,prod因此可用于连接字符串数组。它可以选择将一个函数作为第一个参数,在获取实际的“乘积”之前,它会映射到第二个参数,因此prod(bin,0:n-1)所需范围内的所有整数的二进制表示形式的字符串也是如此。将长度endof乘以n除以n得出平均值。


5

朱莉娅,28个字节

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

由于bin不会自动映射到数组,因此我们ceil(log2(n))用于获取中的位数n-1。这样做很好,因为Julia的a:b符号在两端都包含在内,2:n范围从2到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的答案相同的公式。(通过区分几何级数,自己获得不是很困难。)


请查看我的果冻答案,以供参考。
Leaky Nun

@LeakyNun它使用不同的方法,我认为它不会比您的方法更短。但是_BL$N似乎很长……
jimmy23013 '16

因此,基本上,您的代码是“最接近2的幂,减去1,两倍,除以输入,再减去输入的二进制长度,负数”?
Leaky Nun

@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);}

我认为您可以摆脱接口,只需创建一个函数或lambda。您也可以返回值,而不是将其打印到stdout
Frozn

好的,我将用这些规则重新实施。
肖恩·怀尔德

我认为应该允许。由于OP没有指定任何内容,因此我认为适用标准I / O规则
Frozn

是的,功能很好-您不需要完整的程序。请注意,排行榜在第一行获得分数,因此您的分数目前显示为135,而不是
95。– trichoplax

@trichoplax仍然排在最后。我个人归咎于Java ...
肖恩·怀德(Shaun Wild)

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个字节


@Adnan:谢谢!忘记了J.
Emigna '16

3

C#,87个字节

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

我写了一个C#答案,因为没有看到答案。这是我第一次发布这些信息,因此,如果我做错了任何事情,请告诉我。


欢迎使用编程难题和Code Golf。这是一个很好的第一答案,+ 1。您可以更改doublefloat保存一个字节,还是需要精度?
wizzwizz4 2016年

2
@ wizzwizz4谢谢!我也有同样的想法,但是Average()返回了两倍。如果我将返回类型更改为float,则必须显式转换double并在其上获得7个字节。
raive

2

JavaScript(ES7),38 32字节

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

使用@ sp3000的公式(以前的版本是递归解决方案)。ES6版本为34个字节:

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

公式解释:考虑N = 55的情况。如果我们写二进制数字(以节省空间),我们得到:

                                11111111111111111111111
                111111111111111100000000000000001111111
        11111111000000001111111100000000111111110000000
    111100001111000011110000111100001111000011110000111
  11001100110011001100110011001100110011001100110011001
0101010101010101010101010101010101010101010101010101010

此矩形的大小为nl,因此平均值仅为l,但我们需要排除空格。每行空白是前一行的两倍,因此总数为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

我尝试了另一种方法,即对二进制数列表进行字符串化处理,结果得到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

松散(为便于说明,略有改写)

(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

使用的旧答案(浮动):

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

输出就像:

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

分数或比率是否可以接受的问题以前从未提出过。对于这项挑战,我将接受就默认值应该达成的任何共识。
trichoplax

1

Minkolang 0.15,23个字节

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

在这里尝试!

说明

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.

非常简单的实现。


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

Hoon,71个字节

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

...我很确定这实际上是我第一次使用Hoon的浮点核心。实际上,这是用Hoon编写的实现,可以喷射到SoftFloat,因为Hoon中唯一的数据类型是原子和单元。

创建一个接受原子的函数r。从[0 ..(r-1)]创建一个列表,使用数字的二进制对数映射到列表上,然后使用折叠该列表++add。将fold和的输出转换r@rq(四进制浮点数)++sun:rq,然后将一个由另一个。

此代码段中最奇怪的是:.^rq最后一个。a:b在Hoon中的意思是“根据b评估a”。++rq是包含整个四精度实现(如库)的核心。所以跑步(sun 5):rq和做运动是一样的(sun:rq 5)

幸运的是,Hoon的核心就像是套娃娃。当您评估手臂++rq以获取核心时,它也会向其中添加整个stdlib,因此您可以保持滚动和移动以及所有其他有趣的东西,而不必只限于在中定义的手臂++rq。不幸的是,rq重新定义++add为浮点添加,并且r上下文中没有。.(整个当前上下文)可以。

在上下文中评估表达式时,编译器将查找肢体深度优先。就我们而言,a:[. rq]它将在整个当前上下文中进行a查找rq。因此,add将查找适用于原子而不是浮点数的函数,但也会如此div。Hoon还具有使用^name将忽略找到的第一个参考,而寻找第二个。

从那里开始,它只是使用a^b等于的句法糖[a b]来评估当前上下文和四精度浮点库的代码段,而忽略了原子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

如果不是我刚刚发现的错误,此解决方案将使用6个字节:

r♂├♂læ

æ 是内置的平均值命令。


这不是10个字节吗?我检查了bytesizematters.com。
m654

1
@ m654实际上不使用UTF-8,而是使用CP437(或类似的东西)。
Alex A.

@AlexA。哦,不知道。
m654

1
@ m654 Bytesizematters使用一个完全组成的编码,该编码在实践中存在(也不能存在)。对于UTF-8,请使用mothereff.in/byte-counter
丹尼斯

@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.
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.