Một bit, một nibble hoặc byte?


45

Lấy cảm hứng từ thử thách này

Cho một số nguyên trong phạm vi 0 <= n < 2**64, xuất ra thùng chứa có kích thước tối thiểu mà nó có thể vừa với

  • bit: 1
  • nhấm nháp: 4
  • byte: 8
  • ngắn: 16
  • int: 32
  • dài: 64

Testcase:

0 -> 1
1 -> 1
2 -> 4
15 -> 4
16 -> 8
123 -> 8
260 -> 16
131313 -> 32
34359750709 -> 64

Đây là , vì vậy câu trả lời ngắn nhất bằng byte sẽ thắng.


10
Điều này sẽ dễ dàng hơn đáng kể nếu 2cũng là một đầu ra ...
ETHproductions

1
@ETHproductions Nó sẽ nhưng than ôi, nó không (tôi mất rất nhiều thời gian để viết một thuật toán đã làm điều đó)
Blue

Tôi ước tôi hiểu vấn đề. ... Đợi đã, tất cả những gì nó muốn là số lượng bit cần thiết để chứa số, được làm tròn đến cấu trúc cơ bản tiếp theo?
z0rberg

2
Cảm ơn! Tôi nhận ra nó khi tôi viết bình luận và chỉnh sửa nó quá muộn. Tôi đoán tôi cần một con vịt cao su để nói chuyện với ...
z0rberg

2
@Daniel các câu trả lời ở đây có một cách tiếp cận hoàn toàn khác với câu hỏi khác. Khi tôi nói 'lấy cảm hứng từ' nó không có nghĩa là 'trùng lặp'. Không có câu trả lời nào có thể được sửa đổi một cách tầm thường để có giá trị cho câu hỏi này
Blue

Câu trả lời:


3

05AB1E , 10 byte

bg.²îD1Q+o

Giải trình

bg         Push the length of the binary representation of input without leading zeros
  .²î      Push x = ceil(log2(length))
     D1Q+  Add 1 if x == 1 or add 0 otherwise
         o Push pow(2,x) and implicitly display it

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


22

Python, 39 byte

f=lambda n:4**(n>1)*(n<16)or 2*f(n**.5)

Đếm số lần người ta phải lấy căn bậc hai nở bên dưới 16, với một số vỏ đặc biệt để tránh đầu ra là 2.

Nếu bao gồm 2, chúng ta có thể làm

f=lambda n:n<2or 2*f(n**.5)

với True cho 1.


41 byte:

f=lambda n,i=1:i*(2**i>n)or f(n,i<<1+i%2)

Liên tiếp nhân đôi số mũ icho đến khi 2**i>n. Bỏ qua từ i=1đến i=4bằng cách thay đổi một bit bổ sung khi ilà số lẻ.

Alt 45 byte:

f=lambda n,i=4:4**(n>1)*(2**i>n)or 2*f(n,i*2)

7
Tôi không bao giờ hết ngạc nhiên về cách bạn có thể đưa ra rất nhiều giải pháp cho một vấn đề. Về cơ bản là một lập trình viên, tôi đã học cách tìm ra giải pháp cho một vấn đề và làm việc với nó cho đến khi nó hoạt động. Đoán tôi vẫn còn nhiều điều để tìm hiểu về golf! Sự tôn trọng.
ElPedro

@xnor, làm thế nào để trả lời đầu tiên của bạn đầu ra 1khi căn bậc hai của 0 hoặc 1 luôn luôn là 1 (đệ quy vô hạn trong or 2*f(n**.5))?
dfer Nam

2
@dfernan Tôi tin rằng phần sau orchỉ được đánh giá nếu phần trước đánh giá thành một cái gì đó sai lệch (không). Với n = 0 và với n = 1, n>1ước lượng False, được coi là 0 trong biểu thức số và n<16ước tính True, được coi là một trong một biểu thức số. Vậy 4**(n>1)*(n<16)là 1.
trichoplax

1
@trichoplax, đúng vậy. Cảm ơn đã giải thích.
dfer Nam

12

J, 19 byte

Động từ monadic lấy số ở bên phải và phun ra kích thước container. Có một vài cách viết tương đương để tôi viết cả hai.

2^2(>.+1=>.)@^.#@#:
2^s+1=s=.2>.@^.#@#:

Giải thích bằng vụ nổ:

2^2(>.+1=>.)@^.#@#: NB. takes one argument on the right...
                 #: NB. write it in binary
               #@   NB. length (i.e. how many bits did that take?)
  2          ^.     NB. log base 2 of that
   (>.     )@       NB. ceiling
      +1=>.         NB. +1 if needed (since no container is two bits wide)
2^                  NB. base 2 exponential

Điều thú vị là chúng ta thấy hai cách khác nhau để lấy cơ sở log 2 trong J. Cách thứ nhất là hiển nhiên 2^., đó là logarit số. Thứ hai là #@#:, có thể được đọc là "độ dài của biểu diễn cơ sở 2". Điều này gần như tương đương với một sàn cộng với log-base-2, ngoại trừ đó #:0là danh sách một yếu tố 0, đó chính xác là những gì chúng ta muốn. Nhịp này 1+2<.@^.1&>.bằng 8 byte.

Đang sử dụng tại REPL:

   f =: 2^2(>.+1=>.)@^.#@#:
   f 131313
32
   f 34359750709
64
   (,.f"0) 0 1 2 15 16 123 260
  0  1
  1  1
  2  4
 15  4
 16  8
123  8
260 16

Giải pháp 20 byte cũ, quá thông minh.

2&^.(>.+1=>.&.)@#@#: NB. takes one argument on the right...
                #@#: NB. how many bits
2&^.                 NB. log base 2 of that
     >.              NB. ceiling
       +1=>.         NB. +1 if needed (since no container is two bits wide)
    (       &.)      NB. undo log base 2

9

Python, 53 50 49 byte

lambda n:[w for w in[1,4,8,16,32,64]if n<2**w][0]

1
lambda n:[w for w in[1,4,8,16,32,64]if n<2**w][0]ngắn hơn một byte
Blue

Chỉ là để gửi một cái gì đó tương tự. +1
ElPedro

8

Toán học, 44 39 38 byte

Cảm ơn @orlp cho 5 byte và @MartinEnder cho 1 byte.

FirstCase[{1,4,8,16,32,64},x_/;2^x>#]&

Tìm các phần tử đầu tiên trong danh sách {1, 4, 8, 16, 32, 64}sao cho số 2 ^ lớn hơn số đầu vào.


8

Pip , 19 byte

(a<2**_FI2**,7RM2i)

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

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

                     a is 1st cmdline arg, i is 0 (implicit)
         2**,7       Construct powers of 2 from 0 to 6 [1 2 4 8 16 32 64]
              RM2    Remove 2
       FI            Filter for elements for which:
 a<2**_                a is less than 2 to that element
(                i)  Get 0th item of resulting list and autoprint

7

JavaScript (ES7), 35 byte

n=>[1,4,8,16,32,64].find(b=>2**b>n)

2
Một phiên bản đệ quy như f=(n,b=1)=>2**b>n&&b-2?b:f(n,b*2)nên ngắn hơn một chút.
Arnauld

6

Toán học, 46 43 38 byte

Cảm ơn JungHwan Min và Martin Ender vì đã tiết kiệm được 3 byte! Cảm ơn ngenisis cho một khoản tiết kiệm lớn 5 byte!

2^⌈Log2@BitLength@#⌉/.{2->4,0->1}&

Hàm không tên lấy một số nguyên không âm làm đầu vào và trả về một số nguyên dương. BitLength@#tính toán số bit trong đầu vào, sau đó 2^⌈Log2@...⌉tính công suất nhỏ nhất của 2, ít nhất bằng số bit. Cuối cùng, /.{2->4,0->1}quan tâm đến trường hợp đặc biệt không có "niblit" giữa bit và nybble, đồng thời sửa câu trả lời cho đầu vào kỳ lạ 0.


2
Lưu 3 byte bằng cách sử dụng BitLength@#thay vì ⌊1+Log2@#⌋. Sau đó, thay vì thay thế bằng 1bạn có thể thay thế 0, hãy lưu 2 byte khác và trước tiên bạn bị ràng buộc.
ngenisis

1
Điều này thực sự có thể được thực hiện hoàn toàn với BitLength. Xem câu trả lời của tôi
ngenisis

4

Julia, 40 byte

n->filter(x->n<big(2)^x,[1;2.^(2:6)])[1]

Đây là một hàm ẩn danh tạo ra một mảng các lũy thừa từ 2 đến 6, ngoại trừ 2 và chỉ lọc nó cho các phần tử x sao cho 2 x lớn hơn đầu vào. Yếu tố đầu tiên là câu trả lời. Thật không may, điều này đòi hỏi phải quảng bá 2 đến a BigIntđể tránh tràn trên x = 64.

Điều này thực sự khá giống với câu trả lời Python của orlp, mặc dù tôi đã không nhìn thấy nó trước khi đưa ra phương pháp này.

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


4

Perl 6 , 30 byte

{first 1+<*>$_,1,4,8,16,32,64}

+<là toán tử dịch chuyển bit trái của Perl 6, mà nhiều ngôn ngữ khác gọi <<.


4

Haskell, 31 byte

f n=[2^i|i<-0:[2..],2^2^i>n]!!0

Alt 32 byte:

f n|n<2=1|n<16=4|1>0=2*f(sqrt n)

2

Java, 143 byte.

int f(long a){a=Long.toBinaryString(a).length();if(a<2)return 1;if(a<5)return 4;if(a<9)return 8;if(a<17)return 16;if(a<33)return 32;return 64;}

1
Tôi biết tôi có thể làm điều này ngắn hơn, Io làm điều đó khi tôi ở máy tính.
Pavel

2
lưu 50 byte: return a<2?1:a<5?4:a<9?8:a<17?16:a<33?32:64;
Mindwin

@Mindwin Tôi biết, nhưng tôi đang đi du lịch và sẽ không có quyền truy cập vào máy tính trong một thời gian. Tôi sẽ đi xung quanh nó.
Pavel

Điểm số có làm cho nó một ... tình yêu byte ?
Kỹ sư Toast

2

Haskell, 43 byte

f x=head$filter((>x).(2^))$[1,4,8,16,32,64]

2

Ruby, 39 36 byte

->n{2**[0,*2..6].find{|p|2**2**p>n}}

Cảm ơn GB đã giúp đỡ golf


Cũng nên làm việc mà không có dấu ngoặc đơn. Ngoài ra, danh sách có thể là 0,2,3,4,5,6 và sử dụng 1 << 2 ** p.
GB

... bởi vì sau đó bạn có thể sử dụng 0, * 2..6.
GB

2

Java 8, 65 55 byte

Đây là một biểu thức lambda có một longvà trả về một int. Chưa bao giờ chơi golf trong Java trước đây, vì vậy điều này có thể dễ dàng đánh bại:

x->{int i=1;while(Math.pow(2,i)<=x)i<<=1+i%2;return i;}

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


Đối với 47 byte , chúng ta có thể có:

x->{int i=1;while(1L<<i<=x)i<<=1+i%2;return i;}

Tuy nhiên, 1L<<itràn ra cho các giá trị trả về lớn hơn 32, do đó, điều này không thành công cho testcase cuối cùng.


1
Điều này trả về 4khi được kiểm tra 16khi nó được yêu cầu trả về 8. Ngoài ra, bạn vẫn có thể chơi giải pháp này bằng cách xóa các dấu ngoặc xung quanh i<<=1+i%2;mà không có {}s, vòng lặp while sẽ chỉ thực hiện dòng tiếp theo
Kritixi Lithos

@KritixiLithos nên được sửa ngay bây giờ - xin lỗi, Java của tôi đã bị rỉ sét ...
FlipTack

2

Toán học, 30 byte

2^(f=BitLength)[f@#-1]/. 2->4&

Giải trình:

Hãy Nlà tập hợp các số nguyên không âm. Xác định hai chức năng trên N, BitLengthNextPowernhư sau:

BitLength(n) := min {x in N : 2^x - 1 >= n}
NextPower(n) := 2^(min {x in N : 2^x >= n})

Giải pháp này về cơ bản tính toán NextPower(BitLength(n))cho một số nguyên n >= 0. Đối với n > 0, chúng ta có thể thấy rằng NextPower(n) = 2^BitLength(n-1), vì vậy NextPower(BitLength(n)) = 2^BitLength(BitLength(n)-1).

Bây giờ, Mathicala tích BitLengthhợp sẵn đồng ý với định nghĩa mà tôi đưa ra n >= 0. Đối với n < 0, BitLength[n] == BitLength[BitNot[n]] == BitLength[-1-n], vì vậy BitLength[-1] == BitLength[0] == 0. Vì vậy, chúng tôi nhận được câu trả lời mong muốn 1cho n==0.

Vì chúng ta bỏ qua từ bit đến nibble, chúng ta phải thay thế câu trả lời 2bằng 4.


1
Xây dựng độc đáo! (Xấu hổ vì không gian là cần thiết.)
Greg Martin

2

bash, 49 byte 48 byte

for((y=1;$[y==2|$1>=1<<y];$[y*=2])){ :;};echo $y

hoặc là

for((y=1;$[y==2|$1>=1<<y];)){ y=$[y*2];};echo $y

Lưu trong một tập lệnh và chuyển số được kiểm tra làm đối số.

Chỉnh sửa: Đã thay thế | | với |, hoạt động vì các đối số luôn là 0 hoặc 1.

Lưu ý: Điều này hoạt động cho các số nguyên lên đến số nguyên dương lớn nhất mà phiên bản bash của bạn có thể xử lý. Nếu tôi có thời gian, tôi sẽ sửa đổi nó để hoạt động lên đến 2 ^ 64-1 trong các phiên bản bash sử dụng số học có chữ ký 32 bit.

Trong khi đó, đây là một giải pháp 64 byte hoạt động với số lượng lớn tùy ý (trong bất kỳ phiên bản bash nào):

for((x=`dc<<<2o$1n|wc -c`;$[x==2||x&(x-1)];$[x++])){ :;};echo $x

2

Xếp chồng lên nhau, 34 30 byte

@n 1 2 6|>2\^,:n 2 log>keep 0#

hoặc là

{!1 2 6|>2\^,:n 2 log>keep 0#}

Đầu tiên nhận đầu vào trên ĐKDV và để lại đầu ra trên ĐKDV; thứ hai là một chức năng. Hãy thử nó ở đây!

Giải trình

@n 1 2 6|>2\^,:n 2 log>keep 0#
@n                               set TOS to `n`
   1 2 6|>2\^,                   equiv. [1, ...2 ** range(2, 6)]
              :                  duplicate it
               n                 push `n`
                 2 log           log base-2
                      >          element-wise `>`
                       keep      keep only truthy values
                            0#   yield the first element

Đây là một ví dụ về nó hoạt động trên thay thế :

> 8    (* input *)
(8)
> @n 1 2 6|>2\^,:n 2 log>keep 0#    (* function *)
(4)
>    (* output *)
(4)

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

> {!1 2 6|>2\^,:n 2 log>keep 0#} @:f
()
> (0 1 2 15 16 123 260 131313 34359750709) $f map
((1 1 4 4 8 8 16 32 64))
> 

Hoặc, như một chương trình đầy đủ:

{!1 2 6|>2\^,:n 2 log>keep 0#} @:f

(0 1 2 15 16 123 260 131313 34359750709) $f map

out

2

Vợt 45 byte

(findf(λ(x)(>(expt 2 x)m))'(1 4 8 16 32 64))

Ung dung:

(define (f m)
  (findf (λ (x) (> (expt 2 x) m))          ; find first function
         '(1 4 8 16 32 64)))

Các phiên bản khác:

(define (f1 m)
  (for/last ((i '(1 4 8 16 32 64))         ; using for loop, taking last item
             #:final (> (expt 2 i) m))     ; no further loops if this is true
    i))

và sử dụng độ dài chuỗi:

(define (f2 m)
  (for/last
      ((i '(1 4 8 16 32 64))
       #:final (<= (string-length
                    (number->string m 2))  ; convert number to binary string
                   i))
    i))

Kiểm tra:

(f 0)
(f 1)
(f 2)
(f 15)
(f 16)
(f 123)
(f 260)
(f 131313)
(f 34359750709)

Đầu ra:

1
1
4
4
8
8
16
32
64

1

Octave, 40 36 31 29 byte

Chức năng ẩn danh đơn giản. Giả định rằng giá trị đầu vào là một số nguyên - xem cảnh báo ở cuối.

@(a)(b=2.^[0 2:6])(a<2.^b)(1)

Mã này hoạt động như sau:

  • Đầu tiên, một mảng có độ dài bit được phép (1,4,8,16,32,64) được tạo và lưu vào b.

  • Tiếp theo, chúng tôi tìm thấy số bit cần thiết để lưu trữ số đầu vào abằng cách so sánh với kích thước tối đa của mỗi thùng chứa bđể xem cái nào đủ lớn.

  • Sau đó chúng tôi sử dụng vector chỉ số kết quả để trích xuất kích thước container từ bmột lần nữa.

  • Cuối cùng, chúng ta lấy phần tử đầu tiên trong mảng kết quả sẽ là vùng chứa nhỏ nhất có thể.

Bạn có thể thử nó trực tuyến ở đây .

Đơn giản chỉ cần chạy mã sau đây, và sau đó làm ans(x).


Nhắc nhở duy nhất với điều này là độ chính xác kép được sử dụng cho các hằng số theo mặc định, điều đó có nghĩa là nó chỉ hoạt động với các số có giá trị cao nhất có thể biểu thị bằng độ nổi chính xác kép nhỏ hơn 2 ^ 64.

Điều này có thể được sửa bằng cách đảm bảo rằng số được cung cấp cho hàm là một số nguyên chứ không phải là một số kép. Điều này có thể đạt được bằng cách gọi hàm ví dụ với : ans(uint64(x)).


1

PHP, 49 46 44 byte

echo(2**ceil(log(log(1+$argn,2),2))-2?:2)+2;

Chạy như thế này:

echo 16 | php -R 'echo(2**ceil(log(log(1+$argv[1],2),2))-2?:2)+2;';echo

Giải trình

echo                       # Output the result of the expression
  (
    2**                    # 2 to the power
      ceil(log(            # The ceiling of the power of 2 of bitsize
        log(1+$argn,2),    # Number of bits needed
        2
      ))
      - 2 ?:               # Subtract 2 (will be added back again)
      2;                   # If that results in 0, result in 2 (+2=4).
  ) + 2                    # Add 2.

Tinh chỉnh

  • Đã lưu 3 byte bằng cách thoát khỏi $r=nhiệm vụ
  • Đã lưu 2 byte bằng cách sử dụng -Rđể $argncung cấp

1

CJam , 18 byte

2ri2b,2mLm]_({)}|#

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

Giải trình

2                   Push 2
 ri                 Read an integer from input
   2b,              Get the length of its binary representation
      2mLm]         Take the ceiling of the base-2 log of the length
           _(       Duplicate it and decrement it
             {)}|   Pop the top element, if it's 0, increment the next element
                     Effectively, if ceil(log2(input)) was 1, it's incremented to 2,
                     otherwise it stays the same.
                 #  Raise 2 to that power

0

C, 71 52 byte

i;f(long long n){for(i=1;n>>i;i*=2);return i-2?i:4;}

Sẽ không một đầu vào (1<<15)+1hoặc nhiều hơn phá vỡ điều này vì hành vi đã ký của long long? Loại bạn thực sự muốn là uint64_tmà đòi hỏi #include <stdint.h>đó là vẫn là người thua cuộc so với unsigned long long! Tiêu đề là nguyên nhân của việc chơi golf trong c.
dmckee

@dmckee Tôi đoán nó có thể phá vỡ nó, nhưng nó dường như hoạt động ít nhất trên máy tính của tôi. Không tìm thấy một ví dụ sẽ không hoạt động. Tôi đã nghĩ đến việc sử dụng unsigned long longhoặc uint64_t, nhưng vì nó dường như hoạt động với long longtôi.
Steadybox

0

QBIC , 27 byte

:~a<2|_Xq]{~a<2^t|_Xt\t=t*2

Giải trình

:        Get cmd line parameter N, call it 'a'
~a<2     IF 'a' is 0 or 1 (edge case)
|_Xq]    THEN quit, printing 1 ('q' is auto-initialised to 1). ']' is END-IF
{        DO - infinite loop
    2^t  't' is our current number of bits, QBIC sets t=4 at the start of the program.
         2^t gives the maximum number storable in t bytes.
 ~a<     IF the input fits within that number,
|_Xt     THEN quit printing this 't'
\t=t*2   ELSE jump to the next bracket (which are spaced a factor 2 apart, from 4 up)
         DO-loop is auto-closed by QBIC.


0

PHP, 43 byte

for(;1<<2**$i++<=$argn;);echo 2**$i-=$i!=2;

Chạy với echo <number> | php -R '<code>'.

vòng lặp $icho đến khi 2**(2**$i)lớn hơn đầu vào. (Tinh chỉnh: <<thay vì **loại bỏ parens)
Sau vòng lặp, $ i là một mức quá cao; do đó, nó được giảm trước khi tính toán đầu ra
- nhưng không phải cho $i==2.

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.