Tìm số lượng các số 0 đứng đầu trong một số nguyên 64 bit


18

Vấn đề:

Tìm số lượng số 0 đứng đầu trong số nguyên có chữ ký 64 bit

Quy tắc:

  • Đầu vào không thể được coi là chuỗi; nó có thể là bất cứ điều gì trong đó toán học và các phép toán bitwise điều khiển thuật toán
  • Đầu ra phải được xác nhận dựa trên biểu diễn số nguyên có chữ ký 64 bit, bất kể ngôn ngữ
  • Quy tắc golf mặc định áp dụng
  • Mã ngắn nhất tính bằng byte

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

Các xét nghiệm này giả định hai số nguyên đã ký bổ sung. Nếu ngôn ngữ / giải pháp của bạn thiếu hoặc sử dụng một đại diện khác của các số nguyên đã ký, vui lòng gọi ra và cung cấp các trường hợp kiểm tra bổ sung có thể có liên quan. Tôi đã bao gồm một số trường hợp thử nghiệm có độ chính xác gấp đôi, nhưng xin vui lòng đề xuất bất kỳ trường hợp nào khác cần được liệt kê.

input                output   64-bit binary representation of input (2's complement)
-1                   0        1111111111111111111111111111111111111111111111111111111111111111
-9223372036854775808 0        1000000000000000000000000000000000000000000000000000000000000000
9223372036854775807  1        0111111111111111111111111111111111111111111111111111111111111111
4611686018427387903  2        0011111111111111111111111111111111111111111111111111111111111111
1224979098644774911  3        0001000011111111111111111111111111111111111111111111111111111111
9007199254740992     10       0000000000100000000000000000000000000000000000000000000000000000
4503599627370496     11       0000000000010000000000000000000000000000000000000000000000000000
4503599627370495     12       0000000000001111111111111111111111111111111111111111111111111111
2147483648           32       0000000000000000000000000000000010000000000000000000000000000000
2147483647           33       0000000000000000000000000000000001111111111111111111111111111111
2                    62       0000000000000000000000000000000000000000000000000000000000000010
1                    63       0000000000000000000000000000000000000000000000000000000000000001
0                    64       0000000000000000000000000000000000000000000000000000000000000000

13
Chào mừng đến với PPCG! Lý do đằng sau "đầu vào không thể được coi là chuỗi" là gì? Điều này không đủ tiêu chuẩn cho tất cả các ngôn ngữ không thể xử lý số nguyên 64 bit và không có khả năng dẫn đến nhiều câu trả lời lấy số nguyên, bởi vì đây là cách đơn giản khi có sẵn.
Arnauld

1
Chúng ta có thể trở lại Falsethay vì 0?
Jo King

4
@Arnauld Đã có những câu hỏi tương tự ở đây và trên các trang web khác đặc biệt yêu cầu các giải pháp dựa trên chuỗi, nhưng không có gì mở ra câu hỏi cho các phép toán và logic. Hy vọng của tôi là thấy một loạt các cách tiếp cận khác nhau cho vấn đề này chưa được trả lời ở nơi khác. Điều này có nên được mở cho các giải pháp chuỗi cũng như bao gồm tất cả?
Dave

4
Một số CPU bao gồm x86 và ARM có hướng dẫn cụ thể cho việc này (x86 thực sự có một số). Tôi đã luôn tự hỏi tại sao các ngôn ngữ lập trình không phơi bày tính năng này vì trong hầu hết các ngôn ngữ lập trình ngày nay bạn không thể gọi các hướng dẫn lắp ráp.
slebetman

1
@ user202729 Tôi nghĩ rằng tôi đã nói từ này kém: 'Đầu ra phải được xác thực dựa trên biểu diễn số nguyên có chữ ký 64 bit của số đó, bất kể ngôn ngữ nào' trong một số nguyên có chữ ký 64 bit. Tôi đoán tôi đã thực hiện ràng buộc đó để loại bỏ các số nguyên có dấu và không dấu.
Dave

Câu trả lời:


41

Ngôn ngữ máy x86_64 trên Linux, 6 byte

0:       f3 48 0f bd c7          lzcnt  %rdi,%rax
5:       c3                      ret

Yêu cầu bộ xử lý Haswell hoặc K10 trở lên có lzcnthướng dẫn.

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


20
Nội dung tấn công lại / s
Logern 10/12/18

1
Tôi khuyên bạn nên chỉ định quy ước gọi được sử dụng (mặc dù bạn đã nói trên Linux)
qwr 12/12/18

@qwr Trông giống như quy ước gọi SysV vì tham số được truyền theo% rdi và được trả về% rax.
Logern 15/12/18

24

Lục giác , 78 70 byte

2"1"\.}/{}A=<\?>(<$\*}[_(A\".{}."&.'\&=/.."!=\2'%<..(@.>._.\=\{}:"<><$

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

Đây không phải là thách thức quá tầm thường đối với một ngôn ngữ thực tế? ;)

chiều dài bên 6. Tôi không thể lắp nó trong một hình lục giác dài 5 cạnh.

Giải trình


3
Tôi đã cười rất nhiều vào "lời giải thích". : D
Eric Duminil

1
Tôi nghĩ rằng bạn có thể đã xử lý quá mức số âm / không. Tôi đã xoay sở để điều chỉnh một chương trình tương tự vào chiều dài bên 5 bằng cách không thực hiện phép tính 2 ^ 64 đó. Nó rõ ràng không phải là golf tốt, mặc dù!
FryAmTheEggman

@fry À đúng rồi, số âm luôn có 0 số 0 đứng đầu ... điều này chắc chắn dẫn đến chương trình ngắn hơn vì tạo 2 ^ 64 dài.
dùng202729

12

Python , 31 byte

lambda n:67-len(bin(-n))&~n>>64

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

Expresson là bitwise &của hai phần:

67-len(bin(-n)) & ~n>>64

Các 67-len(bin(-n))câu trả lời chính xác cho đầu vào không âm. Nó lấy độ dài bit và trừ đi từ 67, tức là hơn 3 so với 64 để bù cho -0btiền tố. Phủ định là một mẹo để điều chỉnh cho n==0việc sử dụng phủ định nó không tạo ra- dấu hiệu phía trước.

Các & ~n>>64làm cho câu trả lời thay vì được 0cho tiêu cực n. Khi n<0, ~n>>64bằng 0 (trên số nguyên 64 bit), do đó, và với nó mang lại 0. Khi n>=0, việc ~n>>64đánh giá -1và làm &-1không có hiệu lực.


Python 2 , 36 byte

f=lambda n:n>0and~-f(n/2)or(n==0)*64

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

Thay thế số học.


9

Java 8, 32 26 byte.

Long::numberOfLeadingZeros

Nội dung FTW.

-6 byte nhờ Kevin Cruijssen

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


À, hoàn toàn quên mất numberOfLeadingZeros.. Bạn có thể đánh gôn tới 28 byte btw:n->n.numberOfLeadingZeros(n)
Kevin Cruijssen

2
Trên thực tế, Long::numberOfLeadingZerosthậm chí còn ngắn hơn (26 byte).
Kevin Cruijssen

6
Ồ, điều đó không xảy ra rất thường xuyên khi Java đánh bại Python. Chúc mừng!
Eric Duminil

9

C (gcc) , 14 byte

__builtin_clzl

Hoạt động tốt trên tio

C (gcc) , 35 29 byte

f(long n){n=n<0?0:f(n-~n)+1;}

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

Hơn Dennis cho 6 byte

Cờ trình biên dịch C (gcc) , 29 byte của David Foerster

-Df(n)=n?__builtin_clzl(n):64

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


3
Đáng lưu ý rằng nó chỉ dành cho các máy 64 bit (hoặc bất kỳ máy nào khác có LP64 / ILP64 / v.v. ABI)
Ruslan

1
Geez, nó thậm chí còn ngắn hơn bất kỳ việc sử dụng GCC tích hợp__builtin_clzl nào mà tôi có thể đưa ra .
David Foerster

@Ruslan: điểm hay, trên các hệ thống có long32 bit (bao gồm cả Windows x64), bạn cần __builtin_clzll(dài không dấu). godbolt.org/z/MACCKf . (Không giống như intrinsics Intel, GNU C builtins được hỗ trợ không phụ thuộc vào hoạt động là doable với hướng dẫn một máy On 32-bit x86, biên dịch clzll đến một chi nhánh hoặc cmov để làm. lzcnt(low half)+32Hoặc lzcnt(high half)Or. bsrNếu lzcntkhông có sẵn.
Peter Cordes

Các trường hợp kiểm tra bao gồm "0" nhưng __builtin_clz(l)(l)là hành vi không xác định cho 0: "Nếu x bằng 0, kết quả không xác định."
MCCCS

1
@MCCCS Nếu nó hoạt động, nó được tính. Đó cũng là lý do tại sao tôi giữ câu trả lời cuối cùng
l4m2

6

Perl 6 , 35 28 26 byte

-2 byte nhờ nwellnhof

{to .fmt("%064b")~~/^0*/:}

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

Khối mã ẩn danh lấy một số và trả về một số. Điều này chuyển đổi số thành một chuỗi nhị phân và đếm các số 0 đứng đầu. Nó hoạt động cho các số âm bởi vì ký tự đầu tiên là một -ví dụ -00000101, vì vậy không có số 0 đứng đầu.

Giải trình:

{                        }  # Anonymous code block
    .fmt("%064b")           # Format as a binary string with 64 digits
                 ~~         # Smartmatch against
                   /^0*/    # A regex counting leading zeroes
 to                     :   # Return the index of the end of the match

6

JavaScript (Node.js) , 25 byte

Đưa đầu vào là một chữ BigInt.

f=x=>x<0?0:x?f(x/2n)-1:64

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

0


Sẽ không n=>n<1?0:n.toString(2)-64thực hiện như vậy?
Ismael Miguel

@IsmaelMiguel Tôi cho rằng bạn có ý đó n=>n<1?0:n.toString(2).length-64, nhưng dù sao thì nó cũng không hoạt động. Điều này sẽ , tôi nghĩ.
Arnauld

1
@IsmaelMiguel Không phải lo lắng. :) Thực sự có thể có .toString()cách tiếp cận hoạt động, nhưng chúng ta vẫn cần một chữ BigInt làm đầu vào. Mặt khác, chúng ta chỉ có 52 bit mantissa, dẫn đến kết quả không hợp lệ khi độ chính xác bị mất .
Arnauld

1
Thực tế là hậu tố BigInt có cùng ký tự với tham số của bạn rất khó hiểu ...
Neil

1
@Neil Mã không thể đọc được trên PPCG ?? Điều này là không thể! Đã sửa! : p
Arnauld





4

05AB1E , 10 9 byte

·bg65αsd*

I / O đều là số nguyên

Hãy thử trực tuyến hoặc xác minh tất cả các trường hợp thử nghiệm .

Giải trình:

·         # Double the (implicit) input
          #  i.e. -1 → -2
          #  i.e. 4503599627370496 → 9007199254740992
 b        # Convert it to binary
          #  i.e. -2 → "ÿ0"
          #  i.e. 9007199254740992 → 100000000000000000000000000000000000000000000000000000
  g       # Take its length
          #  i.e. "ÿ0" → 2
          #  i.e. 100000000000000000000000000000000000000000000000000000 → 54
   65α    # Take the absolute different with 65
          #  i.e. 65 and 2 → 63
          #  i.e. 65 and 54 → 11
      s   # Swap to take the (implicit) input again
       d  # Check if it's non-negative (>= 0): 0 if negative; 1 if 0 or positive
          #  i.e. -1 → 0
          #  i.e. 4503599627370496 → 1
        * # Multiply them (and output implicitly)
          #  i.e. 63 and 0 → 0
          #  i.e. 11 and 1 → 11

4

Haskell , 56 byte

Cảm ơn xnor vì đã phát hiện ra một sai lầm!

f n|n<0=0|1>0=sum.fst.span(>0)$mapM(pure[1,0])[1..64]!!n

Có thể phân bổ khá nhiều bộ nhớ, hãy thử trực tuyến!

Có thể bạn muốn kiểm tra nó với hằng số nhỏ hơn: Hãy thử 8-bit!

Giải trình

Thay vì sử dụng mapM(pure[0,1])[1..64]để chuyển đổi đầu vào thành nhị phân, chúng tôi sẽ sử dụng mapM(pure[1,0])[1..64]để tạo ra các chuỗi đảo ngược{0,1}64theo thứ tự từ điển. Vì vậy, chúng tôi chỉ có thể tổng hợp1tiền tố s bằng cách sử dụng sum.fst.span(>0).


3

Powershell, 51 byte

param([long]$n)for(;$n-shl$i++-gt0){}($i,65)[!$n]-1

Kịch bản thử nghiệm:

$f = {

param([long]$n)for(;$n-shl$i++-gt0){}($i,65)[!$n]-1

}

@(
    ,(-1                   ,0 )
    ,(-9223372036854775808 ,0 )
    ,(9223372036854775807  ,1 )
    ,(4611686018427387903  ,2 )
    ,(1224979098644774911  ,3 )
    ,(9007199254740992     ,10)
    ,(4503599627370496     ,11)
    ,(4503599627370495     ,12)
    ,(2147483648           ,32)
    ,(2147483647           ,33)
    ,(2                    ,62)
    ,(1                    ,63)
    ,(0                    ,64)
) | % {
    $n,$expected = $_
    $result = &$f $n
    "$($result-eq$expected): $result"
}

Đầu ra:

True: 0
True: 0
True: 1
True: 2
True: 3
True: 10
True: 11
True: 12
True: 32
True: 33
True: 62
True: 63
True: 64

3

Java 8, 38 byte

int f(long n){return n<0?0:f(n-~n)+1;}

Nhập dưới dạng long(số nguyên 64 bit), đầu ra dưới dạngint (số nguyên 32 bit).

Câu trả lời C (gcc) của cảng @ l4m2 .

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

Giải trình:

 int f(long n){       // Recursive method with long parameter and integer return-type
   return n<0?        //  If the input is negative:
           0          //   Return 0
          :           //  Else:
           f(n-~n)    //   Do a recursive call with n+n+1
                  +1  //   And add 1

EDIT: Có thể là 26 byte bằng cách sử dụng nội dung Long::numberOfLeadingZerosnhư được hiển thị trong câu trả lời Java 8 của @lukeg .


3

APL + THẮNG, 34 byte

+/×\0=(0>n),(63⍴2)⊤((2*63)××n)+n←⎕

Giải trình:

n←⎕ Prompts for input of number as integer

((2*63)××n) If n is negative add 2 to power 63

(63⍴2)⊤ Convert to 63 bit binary

(0>n), Concatinate 1 to front of binary vector if n negative, 0 if positive

+/×\0= Identify zeros, isolate first contiguous group and sum if first element is zero

3

C # (Trình biên dịch tương tác Visual C #) , 42 byte

x=>x!=0?64-Convert.ToString(x,2).Length:64

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

C # (Trình biên dịch tương tác Visual C #) , 31 byte

int c(long x)=>x<0?0:c(x-~x)+1;

Thậm chí ngắn hơn, dựa trên câu trả lời C (gcc) của @ l4m2. Không bao giờ biết rằng bạn có thể khai báo các chức năng như vậy, cảm ơn @Dana!

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


1
Tôi nghĩ điều này là hợp lệ? tio.run/##ZZA/ từ
dana

3

Thạch ,  10  9 byte

-1 nhờ một mánh khóe gọn gàng của Erik the Outgolfer (hiện tại không phải là tiêu cực )

ḤBL65_×AƑ

Liên kết đơn âm chấp nhận một số nguyên (trong phạm vi) mang lại một số nguyên.

Hãy thử trực tuyến! Hoặc xem bộ thử nghiệm .


10 là ḤBL65_ɓ>-×

Đây là một giải pháp 10 byte khác, mà tôi thích vì nó nói là "BOSS" ...

BoṠS»-~%65

Bộ thử nghiệm ở đây

...BoṠS63r0¤i , BoṠS63ŻṚ¤iHoặc BoṠS64ḶṚ¤icũng sẽ làm việc.


10 byter khác (từ Dennis) là æ»64ḶṚ¤Äċ0(một lần nữa æ»63r0¤Äċ0æ»63ŻṚ¤Äċ0cũng sẽ hoạt động)



@EriktheOutgolfer Tôi tự nghĩ rằng "phải có một cách chơi golf để nhân lên bằng isNonNegative" và không nghĩ gì về công việc Ƒnhanh chóng cả, rất tốt!
Jonathan Allan

1
Trên thực tế, tôi đã lý thuyết hóa khá lâu rồi. Được cảnh báo rằng nó không vector hóa! ;-) Đó thực sự là "làm phẳng và sau đó kiểm tra xem tất cả các yếu tố là không âm".
Erik the Outgolfer 11/12/18

2

Perl 5 , 37 byte

sub{sprintf("%064b",@_)=~/^0*/;$+[0]}

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

Hoặc 46 byte này nếu không cho phép "chuỗi hóa": sub z

sub{my$i=0;$_[0]>>64-$_?last:$i++for 1..64;$i}

s/length$&/$+[0]/(-3 byte);)
Dada

IMO, bạn không được phép xóa subtừ khóa khỏi các câu trả lời có chứa các hàm Perl 5.
nwellnhof

Tôi đã thấy những gì tương tự như loại bỏ subtrong câu trả lời cho các ngôn ngữ khác, perl6, powershell và nhiều hơn nữa.
Kjetil S.

Trong Perl6, tôi nghĩ bạn không cần sub{}phải tạo một phụ (ẩn danh?), Điều này giải thích tại sao nó bị bỏ sót trong các câu trả lời của Perl6. Tôi đồng ý với @nwellnhof rằng bạn không được phép xóa sub. (khi tôi vẫn còn hoạt động, như một năm trước hoặc lâu hơn, đó là quy tắc)
Dada

thay đổi ngay bây giờ Và bao gồm $+[0].
Kjetil S.

2

Swift (trên nền tảng 64 bit), 41 byte

Khai báo một bao đóng được gọi là fchấp nhận và trả về một Int. Giải pháp này chỉ hoạt động một cách chính xác nền tảng 64-bit, nơi Intđược typealiased để Int64. (Trên nền tảng 32 bit, Int64có thể được sử dụng rõ ràng cho loại tham số của bao đóng, thêm 2 byte.)

let f:(Int)->Int={$0.leadingZeroBitCount}

Trong Swift, ngay cả kiểu số nguyên cơ bản là một đối tượng bình thường được khai báo trong thư viện chuẩn. Điều này có nghĩa là Intcó thể có các phương thức và thuộc tính, chẳng hạn như leadingZeroBitCount(được yêu cầu trên tất cả các loại tuân thủ FixedWidthIntegergiao thức của thư viện chuẩn ).


hấp dẫn. làm tôi nhớ đến Rust. tôi nghĩ rằng nó nên được tính là 20 byte, .leadZeroBitCount
không sáng

2

Haskell , 24 byte

f n|n<0=0
f n=1+f(2*n+1)

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

Điều này về cơ bản giống như giải pháp Java của Kevin Cruijssen, nhưng tôi thấy nó độc lập.

Đối số nên có kiểu Intcho bản dựng 64 bit, hoặcInt64 cho bất cứ thứ gì.

Giải trình

Nếu đối số là âm, kết quả là ngay lập tức 0. Nếu không, chúng ta dịch chuyển sang trái, điền vào các đối số , cho đến khi chúng ta đạt đến một số âm. Việc điền đó cho phép chúng tôi tránh trường hợp đặc biệt cho 0.

Chỉ để tham khảo, đây là cách rõ ràng / hiệu quả:

34 byte

import Data.Bits
countLeadingZeros



1

Perl 5 -p , 42 byte

1while$_>0&&2**++$a-1<$_;$_=0|$_>=0&&64-$a

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

Dài hơn một giải pháp dựa trên chuỗi bit, nhưng là một giải pháp dựa trên toán học đàng hoàng.


Không thực sự hoạt động nếu tôi không nhầm
Dada

@Dada Tôi thấy rằng có một vài trường hợp phân chia dấu phẩy động không hoàn toàn đúng. Tôi intgọi trong một cuộc gọi sẽ giải quyết vấn đề.
Xcali

Xin lỗi, tôi đã thất bại trong quá khứ sao chép của mình. Đây là những gì tôi muốn gửi;)
Dada

1

APL (NARS), 15 ký tự, 30 byte

{¯1+1⍳⍨⍵⊤⍨64⍴2}

kiểm tra vài con số để xem cách sử dụng:

  f←{¯1+1⍳⍨⍵⊤⍨64⍴2}
  f ¯9223372036854775808
0
  f 9223372036854775807
1


1

K (ngn / k) , 6 byte

64-#2\

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

2\ mã hóa đối số trong nhị phân

# chiều dài

64- trừ 64


# = length... trông chuỗi dựa trên
Titus

2
@Titus 2\ đưa ra danh sách các số nguyên và #tìm độ dài của nó. không có chuỗi có liên quan ở đây.
ngn

1

PHP, 50 46 byte

for(;0<$n=&$argn;$n>>=1)$i++;echo$n<0?0:64-$i;

Chạy như ống với -Rhoặc thử trực tuyến ,

<?=$argn<0?0:0|64-log($argn+1,2);có vấn đề làm tròn số; Vì vậy, tôi đã đi đường dài.


1

Ngôn ngữ Wolfram (Mathicala) , 41 byte

Công thức cho các số dương chỉ là 63-Floor@Log2@#& . Quy tắc thay thế được sử dụng cho các trường hợp đặc biệt của đầu vào số 0 và âm.

Đầu vào không cần phải là số nguyên có chữ ký 64 bit. Điều này sẽ có hiệu quả lấy sàn của đầu vào để biến nó thành một số nguyên. Nếu bạn nhập một số bên ngoài giới hạn bình thường cho số nguyên 64 bit, nó sẽ trả về một số âm cho biết cần bao nhiêu bit nữa để lưu số nguyên này.

63-Floor@Log2[#/.{_?(#<0&):>2^63,0:>.5}]&

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

Giải pháp của @ LegionMammal978 ngắn hơn một chút với 28 byte. Đầu vào phải là một số nguyên. Theo tài liệu: "thực sự BitLength[n]là một phiên bản hiệu quả của Floor[Log[2,n]]+1." Nó tự động xử lý trường hợp không báo cáo chính xác 0thay vì-∞ .

Ngôn ngữ Wolfram (Mathicala) , 28 byte

Boole[#>=0](64-BitLength@#)&

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


1
Boole[#>=0](64-BitLength@#)&là một bit tốt ngắn hơn ở 28 byte. Nó sử dụng khái niệm cơ bản giống như của bạn, nhưng áp dụng BitLengthBoole.
LegionMammal978

Tôi hoàn toàn quên mất BitLpm!
Kelly Lowder

1

bitNumber - math.ceil (math.log (số) / math.log (2))

ví dụ: 64 bit SỐ: 9223372036854775807 math.ceil (math.log (9223372036854775807) / math.log (2)) ANS: 63


Nếu bạn có thể thêm tên ngôn ngữ này, điều đó sẽ rất tuyệt, vì mọi người có thể bỏ phiếu trả lời không có tên ngôn ngữ được bao gồm
Jono 2906
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.