Bit trung bình: một thách thức trung bình


30

Cho một số nguyên N> = 1, xuất số bit trung bình trong một số nguyên từ 0 đến N - 1

Đặc điểm kỹ thuật

  • Đầu ra có thể được tính bằng tổng số bit trong biểu diễn nhị phân của mỗi số nguyên từ 0 đến N-1, chia cho N.
  • Biểu diễn nhị phân của một số nguyên không có số 0 đứng đầu trong ngữ cảnh này, ngoại trừ 0, được biểu thị bằng 0 trong nhị phân.
  • Đầu ra phải chính xác đến ít nhất 7 con số quan trọng.

Thí dụ

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

Số bit trung bình = (1 + 1 + 2 + 2 + 3 + 3) / 6 = 2

Các trường hợp thử nghiệm

Đầu vào => đầu ra

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

Bảng xếp hạng

(từ đây )

Lưu ý rằng tổng (trước khi chia để tìm giá trị trung bình) là một chuỗi trên OEIS .


6
Tên đẹp, rất hay .
Rɪᴋᴇʀ

3
Đối với bất kỳ ai không biết, tôi có nhiều khả năng nâng cao giải pháp bằng một lời giải thích
trichoplax

4
Không đủ chơi chữ, bạn cần thêm một chút để điều này trở nên hoàn hảo.
clismique

1
Tôi giả sử rằng "mỗi số" bạn có nghĩa là "mỗi số nguyên "?
Cyoce

@Cyoce có, cảm ơn bạn đã chỉ ra điều đó - Tôi đã chỉnh sửa để làm rõ.
trichoplax

Câu trả lời:


13

Bình thường, 6 byte

.Oml.B

Hãy thử trực tuyến tại đây .

.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

Vị trí chung đầu tiên nhưng bạn không hiển thị trên bảng xếp hạng - Tôi đã thực hiện một chỉnh sửa nhỏ cho tiêu đề để sửa nó.
trichoplax

9

Thạch, 6 byte

R’BFL÷

Hãy thử trực tuyến!

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 byte

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

Giải trình

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

Mẫu chạy trên ideone .


6

Python 3, 43 byte

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

Sử dụng công thức trên trang OEIS . Đáng ngạc nhiên, một chức năng được đặt tên bằng cách nào đó rẻ hơn ở đây vì sự phân công x.

Cách tiếp cận khác cho 46 byte:

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

Thật không may, -~là cần thiết vì (0).bit_length()0, nhưng thậm chí sau đó nó muốn được một byte quá lâu.


6

Julia, 27 byte

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

Hãy thử trực tuyến!

Làm thế nào nó hoạt động

*là nối chuỗi trong Julia, nên prodcó thể được sử dụng để nối một chuỗi các chuỗi. Nó tùy ý nhận một hàm làm đối số thứ nhất mà nó ánh xạ lên đối số thứ hai trước khi lấy "sản phẩm" thực tế, do đó, prod(bin,0:n-1)chuỗi biểu diễn nhị phân của tất cả các số nguyên trong phạm vi mong muốn. Lấy độ dài với endofvà chia cho n mang lại giá trị trung bình.


5

Julia, 28 byte

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

binkhông tự động ánh xạ qua các mảng, chúng tôi đang sử dụng ceil(log2(n))để lấy số lượng bit n-1. Điều này diễn ra tốt đẹp vì a:bký hiệu của Julia được bao gồm ở cả hai đầu, do đó, 2:nphạm vi từ 2 đến n, nhưng chúng tôi thực sự đang tính toán số bit cho các số trong phạm vi 1:n-1. Thật không may, mặc dù vậy, chúng ta cần phải xử lý thêm 2vào tài khoản 0.

Hãy thử trực tuyến!


5

MATL, 9 byte

q:ZlksG/Q

Hãy thử trực tuyến!

Phiên bản sửa đổi với tất cả các trường hợp thử nghiệm

Giải trình

    % 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

Chộp !! (phụ)
David

@David Thật ra, bạn đã đúng. Sao chép đầu vào ở đầu không hoạt động đối với các giá trị khác ... bạn cần G/Qở cuối.
cốc

5

MATL, 9 byte

:qBYszQG/

Hãy thử trực tuyến!

Giải trình

: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

Thạch, 8 byte

Không ngắn hơn, nhưng thuật toán thú vị, và lần gửi Jelly đầu tiên của tôi:

Rl2Ċ»1S÷

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

4

Thạch, 10 byte

BL©2*2_÷+®

Từ đề xuất của Sp3000.

Hãy thử nó ở đây.

Thạch, 11 byte

æḟ2’Ḥ÷_BL$N

Không ngắn lắm nhưng tôi cần một số lời khuyên.

Hãy thử nó ở đây.

Sử dụng công thức tương tự như trong câu trả lời của Sp3000 . (Không khó để tự mình lấy nó, bằng cách phân biệt tiến trình hình học.)


Nhìn vào câu trả lời Jelly của tôi để bạn tham khảo.
Leaky Nun

@LeakyNun Đó là cách sử dụng một cách tiếp cận khác, mà tôi không nghĩ nó sẽ ngắn hơn của bạn. Nhưng _BL$Ndường như khá dài ...
jimmy23013

Vậy về cơ bản, mã của bạn là "sàn tới công suất gần nhất là 2, trừ 1, gấp đôi, chia cho đầu vào, trừ đi độ dài nhị phân của đầu vào, âm"?
Nữ tu bị rò rỉ

@LeakyNun Có ..
jimmy23013

3
Chỉ tốt hơn một chút: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);}

Tôi nghĩ bạn có thể thoát khỏi giao diện và chỉ cần tạo một hàm hoặc lambda. Ngoài ra, bạn có thể trả lại giá trị thay vì in nó ra thiết bị xuất chuẩn
Frozn

Được rồi, tôi sẽ thực hiện với các quy tắc đó.
Shaun Wild

Tôi nghĩ nó nên được cho phép. Vì OP không chỉ định bất cứ điều gì tôi nghĩ rằng các quy tắc I / O tiêu chuẩn được áp dụng.
Frozn

Có một chức năng là tốt - bạn không cần một chương trình hoàn chỉnh. Lưu ý rằng bảng xếp hạng lấy điểm trên dòng đầu tiên, vì vậy điểm của bạn hiện hiển thị là 135 thay vì 95.
trichoplax

@trichoplax Vẫn là nơi cuối cùng. Tôi đổ lỗi cho Java cá nhân ...
Shaun Wild

3

Python 3, 46 byte

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

Gọi nó như thế

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

Tôi đã phải hoàn nguyên bản sửa đổi bản đồ vì nó không thành công cho đầu vào của 5


3

05AB1E, 9 7 byte

Mã số:

L<bJg¹/

Giải trình:

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

Dùng thử trực tuyến

Chỉnh sửa: đã lưu 2 byte nhờ @Adnan


@Ad Nam: Cảm ơn! Quên về J.
Emigna

3

C #, 87 byte

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

Tôi đã viết câu trả lời C # vì tôi không thấy câu trả lời. Đây là bài viết đầu tiên của tôi cho một trong số này, vì vậy xin vui lòng cho tôi biết nếu tôi làm gì sai.


Chào mừng bạn đến với Câu đố lập trình và Code Golf. Đây là một câu trả lời đầu tiên tuyệt vời, +1. Bạn có thể thay đổi doubleđể floatlưu một byte, hoặc bạn cần độ chính xác?
wizzwizz4

2
@ wizzwizz4 Cảm ơn! Tôi có cùng suy nghĩ, nhưng Average () trả lại gấp đôi. Nếu tôi thay đổi kiểu trả về của mình thành float thì tôi phải bỏ rõ ràng gấp đôi và nhận được 7 byte trên đó.
raive

2

JavaScript (ES7), 38 32 byte

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

Sử dụng công thức của @ sp3000 (phiên bản trước là một giải pháp đệ quy). Phiên bản ES6 cho 34 byte:

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

Giải thích về công thức: Xét trường hợp N = 55. Nếu chúng ta viết các số nhị phân (theo chiều dọc để tiết kiệm không gian), chúng ta sẽ nhận được:

                                11111111111111111111111
                111111111111111100000000000000001111111
        11111111000000001111111100000000111111110000000
    111100001111000011110000111100001111000011110000111
  11001100110011001100110011001100110011001100110011001
0101010101010101010101010101010101010101010101010101010

Kích thước của hình chữ nhật này là nl vì vậy trung bình chỉ là l nhưng chúng ta cần loại trừ các khoảng trống. Mỗi hàng trống dài gấp đôi so với trước đó nên tổng số là 2 + 4 + 8 + 16 + 32 = 64 - 2 = 2 l - 2.


2

J, 21 17 15 byte

Từ 17 byte đến 15 byte nhờ @Dennis.

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

Ai có thể giúp tôi chơi cái này không? ...

Phiên bản ung dung

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

Tôi đã thử một cách tiếp cận khác, bằng cách xâu chuỗi danh sách các số nhị phân và đưa ra 25 byte : %~>:@#@([:":10#.[:#:i.)-]. Giải pháp của bạn trông khá tối ưu.
Conor O'Brien

2

Perl 6 ,  34  32 byte

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

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

Giải trình:

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

Kiểm tra:

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

APL Dyalog , 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

Có vẻ như tỷ lệ là ok theo định dạng số nào được chấp nhận trong đầu ra?

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

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

không viết lại (và viết lại một chút để dễ giải thích)

(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

câu trả lời cũ đã sử dụng (float):

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

đầu ra giống như:

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

Câu hỏi liệu phân số hoặc tỷ lệ có thể chấp nhận được đã không được nêu ra trước đây. Đối với thử thách này, tôi sẽ chấp nhận bất cứ sự đồng thuận nào đạt được về mặc định .
trichoplax

1

Chồn 0,15 , 23 byte

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

Hãy thử nó ở đây!

Giải trình

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.

Thực hiện khá đơn giản.


1

JavaScript ES5, 55 byte

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

Giải trình

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

... Tôi khá chắc chắn rằng đây thực sự là lần đầu tiên tôi sử dụng lõi điểm nổi của Hoon. Đây thực sự là một triển khai được viết bằng Hoon phản ứng với SoftFloat, vì các loại dữ liệu duy nhất trong Hoon là các nguyên tử và tế bào.

Tạo một hàm lấy một nguyên tử , r. Tạo một danh sách từ [0 .. (r - 1)], ánh xạ qua danh sách lấy logarit nhị phân của số, sau đó gấp lại danh sách đó với ++add. Chuyển đổi cả đầu ra của nếp gấp và rsang @rq(số dấu phẩy động chính xác bốn) với++sun:rq , sau đó chia cho nhau.

Điều kỳ lạ nhất trong đoạn trích này là :.^rqở cuối. a:btrong Hoon có nghĩa là "đánh giá a trong bối cảnh của b". ++rqlà cốt lõi chứa toàn bộ triển khai chính xác bốn, giống như một thư viện. Vì vậy, chạy (sun 5):rqlà điều tương tự như làm (sun:rq 5).

May mắn thay, lõi trong Hoon giống như búp bê làm tổ; khi bạn đánh giá cánh tay ++rqđể có được những cốt lõi, nó cho biết thêm toàn bộ stdlib đến nó như là tốt, vì vậy bạn có thể giữ cho cuộn và quay lại vịnh và tất cả những gì vui vẻ thứ thay vì bị mắc kẹt với chỉ tay theo quy định tại ++rq. Thật không may, rq định nghĩa lại ++addđể thêm dấu phẩy động thay vào đó, cùng với việc không có rtrong bối cảnh của nó. .(toàn bộ bối cảnh hiện tại), tuy nhiên.

Khi đánh giá một biểu thức trong một ngữ cảnh, trình biên dịch sẽ tìm độ sâu chi trước. Trong trường hợp của chúng tôi, a:[. rq]nó sẽ xem xét toàn bộ bối cảnh hiện tại atrước khi chuyển sang tìm kiếm rq. Vì vậy, addsẽ tìm kiếm chức năng hoạt động trên các nguyên tử thay vì số dấu phẩy động ... nhưng cũng sẽ như vậy div. Hoon cũng có một tính năng trong đó việc sử dụng ^namesẽ bỏ qua tham chiếu được tìm thấy đầu tiên và tìm kiếm thứ hai.

Từ đó, chỉ đơn giản là sử dụng đường tổng hợp a^bbằng để [a b]đánh giá đoạn trích của chúng tôi với cả bối cảnh hiện tại và thư viện phao chính xác bốn góc, bỏ qua div nguyên tử có lợi ++div:rq.

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

1

Trên thực tế, 7 byte:

;r♂├Σl/

Hãy thử trực tuyến!

Giải trình:

;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

Nếu đó không phải là lỗi mà tôi vừa phát hiện, giải pháp này sẽ hoạt động với 6 byte:

r♂├♂læ

æ là lệnh có nghĩa là dựng sẵn.


Đây có phải là 10 byte không? Tôi đã kiểm tra tại byteizematters.com.
m654

1
@ m654 Trên thực tế không sử dụng UTF-8, nó sử dụng CP437 (hoặc đại loại như thế).
Alex A.

@AlexA. Ồ, không biết điều đó.
m654

1
@ m654 Bytesizematters sử dụng mã hóa hoàn toàn được tạo ra mà không (và không thể ) tồn tại trong thực tế. Đối với UTF-8, hãy sử dụng mẹeff.in/byte-count .
Dennis

@Dennis Cảm ơn thông tin, tôi sẽ ghi nhớ điều đó.
m654


1

PowerShell v2 +, 64 byte

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

Rất đơn giản thực hiện các thông số kỹ thuật. Vòng lặp từ 0đến $n-1với |%{...}. Mỗi lần lặp, chúng [convert]tôi nhập số $_vào một chuỗi cơ sở 2và lấy số đó length. Chúng tôi tích lũy mà trong $o. Sau các vòng lặp, chúng ta chỉ cần chia$o/$n , để lại trên đường ống và đầu ra là ẩn.

Miễn là điều này, nó thực sự ngắn hơn công thức mà Sp & những người khác đang sử dụng, kể từ khi [math]::Ceiling()[math]::Log()thật lố bịch. Chuyển đổi cơ sở trong PowerShell là may mắn.


1

Perl 5.10, 54 byte

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

Khá nhiều đơn giản. sprintf"%b"là một cách gọn gàng để xuất một số nhị phân trong Perl mà không cần sử dụng các thư viện bổ sung.

Hãy thử trực tuyến!


1

CJam, 13 12 11 byte

Một byte được lưu nhờ vào @ Sp3000 và một byte khác nhờ @ jimmy23013

rd_,2fbs,\/

Hãy thử trực tuyến!

Giải trình

Nói thẳng ra. Áp dụng định nghĩa.

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

Swift, 72 byte

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

2
Bạn không cần gọi hàm, để nó là hàm xác định là được. Đẹp bài đầu tiên.
Rɪᴋᴇʀ

1

J, 15 byte

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

Đây là một động từ đơn âm, được sử dụng như sau:

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

Hãy thử nó ở đây!

Giải trình

Tôi thực hiện các thách thức spec khá theo nghĩa đen. Có những cách tiếp cận khác, nhưng tất cả hóa ra dài hơn.

%~[:+/#@#:"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.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.