64 비트 정수에서 선행 0의 수를 구합니다


18

문제:

64 비트 부호있는 정수에서 선행 0 수를 찾습니다.

규칙 :

  • 입력을 문자열로 취급 할 수 없습니다. 수학 및 비트 연산이 알고리즘을 구동하는 모든 것이 될 수 있습니다.
  • 언어에 관계없이 출력은 숫자의 부호있는 64 비트 정수 표현에 대해 유효성을 검증해야합니다.
  • 기본 코드 골프 규칙이 적용됩니다
  • 바이트 단위의 최단 코드 승리

테스트 사례 :

이 테스트에서는 2의 보수 부호있는 정수를 가정합니다. 언어 / 솔루션에 부호없는 정수의 다른 표현이 없거나 사용하는 경우이를 호출하고 관련성이있는 추가 테스트 사례를 제공하십시오. 배정도를 다루는 몇 가지 테스트 사례를 포함 시켰지만, 나열해야 할 다른 것을 제안 해 주시기 바랍니다.

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
PPCG에 오신 것을 환영합니다! "입력을 문자열로 취급 할 수 없습니다" 뒤에있는 이유는 무엇입니까 ? 이것은 64 비트 정수를 처리 할 수없는 모든 언어를 실격시키고 정수를 사용하는 더 많은 답변 으로 이어질 가능성은 거의 없습니다.
Arnauld

1
False대신에 돌아갈 수 있을까요 0?
Jo King

4
@Arnauld 문자열 기반 솔루션을 특별히 요구하는 여기와 다른 사이트에는 이미 비슷한 질문이 있지만 수학 및 논리 연산에 대한 질문은 없습니다. 나는 아직 다른 곳에서는 대답하지 않은이 문제에 대한 다양한 접근 방식을보고 싶습니다. 이것이 포괄적 인 솔루션뿐만 아니라 문자열 솔루션으로 열어야합니까?
Dave

4
x86 및 ARM을 포함한 여러 CPU에는 이에 대한 특정 명령어가 있습니다 (x86에는 실제로 여러 개가 있음). 오늘날 대부분의 프로그래밍 언어에서는 어셈블리 명령어를 호출 할 수 없으므로 프로그래밍 언어가 왜이 기능을 제공하지 않는지 항상 궁금했습니다.
slebetman

1
@ user202729 나는 이것을 잘못 말한 것으로 생각합니다. 64 비트 부호있는 정수 부호있는 정수와 부호없는 정수를 제거하기 위해 그 제약 조건을 만들었다 고 생각합니다.
Dave

답변:


41

Linux의 x86_64 기계 언어, 6 바이트

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

lzcnt명령이있는 Haswell 또는 K10 이상의 프로세서가 필요합니다 .

온라인으로 사용해보십시오!


20
Builtins 파업 / s
로건

1
사용 된 호출 규칙을 지정하는 것이 좋습니다 (Linux에서는 말
했음

@qwr 매개 변수가 % rdi로 전달되고 % rax로 반환되므로 SysV 호출 규칙처럼 보입니다.
Logern

24

헥사 고니 , 78 70 바이트

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

온라인으로 사용해보십시오!

이 도전은 실제 언어에 비해 너무 사소하지 않습니까? ;)

측면 길이 6. 측면 길이 5 육각형에 맞지 않습니다.

설명


3
나는 "설명"에 정말 열심히 웃었다. : D
Eric Duminil

1
음수 / 0을 처리하는 것이 너무 복잡 할 수 있습니다. 나는 2 ^ 64의 무거운 계산을하지 않음 으로써 비슷한 프로그램 을 측면 길이 5에 맞출 수있었습니다 . 그래도 아직 골프는 잘되지 않습니다!
FryAmTheEggman

@fry 아 맞아, 음수는 항상 0의 선행 0을 가지고 있습니다 .2 ^ 64가 길기 때문에 프로그램이 짧아집니다.
user202729

12

파이썬 , 31 바이트

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

온라인으로 사용해보십시오!

Expresson은 &두 부분으로 비트 단위 입니다.

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

67-len(bin(-n))음이 아닌 입력에 대한 정확한 답을 제공합니다. 그것은 비트 길이를 취하고 67에서 빼고, 이것은 -0b접두사 를 보상하기 위해 64보다 3보다 큽니다 . 부정은 부정 을 앞두고 부호를 n==0만들지 않는다는 것을 사용 하도록 조정하는 트릭 -입니다.

& ~n>>64대신에 대답 0은 부정적 n이다. 경우 n<0, ~n>>64(64 비트 정수에서) 0과 동일하므로 준다와 한창 0. 때 n>=0(가), ~n>>64평가 -1및 수행 &-1에는 영향을주지 않습니다.


파이썬 2 , 36 바이트

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

온라인으로 사용해보십시오!

산술 대안.


9

Java 8, 32 26 바이트

Long::numberOfLeadingZeros

내장 FTW.

Kevin Cruijssen 덕분에 -6 바이트

온라인으로 사용해보십시오!


아, 완전히 잊어 numberOfLeadingZeros그것에 28 바이트 BTW ... 당신은 골프 할 수 있습니다n->n.numberOfLeadingZeros(n)
케빈 Cruijssen

2
실제로 Long::numberOfLeadingZeros는 더 짧습니다 (26 바이트).
케빈 크루이

6
와우, 자바가 파이썬을 능가하는 일은 자주 일어나지 않습니다. 축하합니다!
Eric Duminil

9

C (gcc) , 14 바이트

__builtin_clzl

Tio에서 잘 작동합니다

C (gcc) , 35 29 바이트

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

온라인으로 사용해보십시오!

6 바이트 동안 Dennis보다

C (gcc) 컴파일러 플래그, David Foerster의 29 바이트

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

온라인으로 사용해보십시오!


3
64 비트 컴퓨터 (또는 LP64 / ILP64 / etc. ABI가있는 다른 컴퓨터)에만 해당된다는 점에 주목할 가치가 있습니다.
Ruslan

1
의 모든 사용보다 더 짧다 이런, GCC는 내장에__builtin_clzl 있는 내가 할 수있는 .
David Foerster

@Ruslan : long32 비트 (Windows x64 포함) 인 시스템에서는 __builtin_clzll서명되지 않은 long long 이 필요합니다 . godbolt.org/z/MACCKf . (Intel 내장 함수와 달리 GNU C 내장은 하나의 머신 명령어로 수행 할 수있는 작업에 관계없이 지원됩니다. 32 비트 x86에서 clzll은 분기 또는 cmov로 컴파일하여 수행 lzcnt(low half)+32하거나 사용할 수없는 경우 lzcnt(high half)또는 사용할 수없는 bsr경우lzcnt
피터 코드

테스트 사례에는 "0"이 포함되지만 0에 __builtin_clz(l)(l)대해서는 정의되지 않은 동작입니다. "x가 0이면 결과가 정의되지 않습니다."
MCCCS December

1
@MCCCS 작동하면 계산됩니다. 그렇기 때문에 나는 마지막 대답을 계속합니다
l4m2

6

펄 6 , 35 28 26 바이트

nwellnhof 덕분에 -2 바이트

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

온라인으로 사용해보십시오!

숫자를 받아서 숫자를 반환하는 익명 코드 블록. 숫자를 이진 문자열로 변환하고 선행 0을 계산합니다. 첫 번째 문자가 -예 이므로 음수로 작동 -00000101하므로 선행 0이 없습니다.

설명:

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

자바 스크립트 (Node.js) , 25 바이트

입력을 BigInt 리터럴로 사용합니다.

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

온라인으로 사용해보십시오!

0


n=>n<1?0:n.toString(2)-64동일하게 수행 하지 않습니까?
Ismael Miguel

@IsmaelMiguel 나는 당신이 의미한다고 생각 n=>n<1?0:n.toString(2).length-64하지만 어쨌든 작동하지 않을 것입니다. 나는 그렇게 생각한다.
Arnauld

1
@IsmaelMiguel 걱정하지 마세요. :) 실제로 .toString()접근 방식을 사용할 수는 있지만 여전히 입력으로 BigInt 리터럴이 필요합니다. 그렇지 않으면, 우리는 52 비트의 가수만을 가지므로 정밀도가 손실되면 잘못된 결과를 초래 합니다.
Arnauld

1
BigInt 접미사가 매개 변수와 같은 문자라는 사실은 매우 혼란 스럽습니다 ...
Neil

1
@Neil PPCG에서 읽을 수없는 코드 ?? 이럴 수 없습니다! 결정된! : p
Arnauld





4

05AB1E , 10 9 바이트

·bg65αsd*

I / O는 모두 정수입니다

온라인으로 시도 하거나 모든 테스트 사례를 확인하십시오 .

설명:

·         # 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


3

파워 쉘, 51 바이트

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

테스트 스크립트 :

$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"
}

산출:

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

자바 8, 38 바이트

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

같은 입력 long(64 비트 정수) 등의 출력 int(32 비트 정수).

@ l4m2 의 C (gcc) 답변 포트 .

온라인으로 사용해보십시오.

설명:

 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

편집 : @lukeg 의 Java 8 answer에 표시된대로 내장을 사용하여 26 바이트 가 될 수 있습니다 .Long::numberOfLeadingZeros


3

APL + WIN, 34 바이트

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

설명:

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 # (Visual C # 대화식 컴파일러) , 42 바이트

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

온라인으로 사용해보십시오!

C # (Visual C # 대화식 컴파일러) , 31 바이트

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

@ l4m2의 C (gcc) 답변을 기반으로 더 짧습니다 . @Dana 덕분에 그런 함수를 선언 할 수 있다는 것을 결코 알지 못했습니다!

온라인으로 사용해보십시오!


1
이것이 유효하다고 생각합니까? tio.run/##ZZA/…
dana

3

젤리 ,  10  9 바이트

에릭 Outgolfer하여 깔끔한 트릭 -1 덕분에 (IS-음이 아닌 지금 단순히 )

ḤBL65_×AƑ

정수 (범위 내)를 허용하는 정수 링크는 정수를 생성합니다.

온라인으로 사용해보십시오! 또는 테스트 스위트를 참조하십시오.


10은 ḤBL65_ɓ>-×

여기에 또 다른 10 바이트 솔루션이 있는데, 이것이 "BOSS"라고 말했기 때문에 좋아합니다 ...

BoṠS»-~%65

시험 스위트 여기

... BoṠS63r0¤i, BoṠS63ŻṚ¤i또는 BoṠS64ḶṚ¤i작동합니다.


(데니스)에서 또 다른 10 byter이다 æ»64ḶṚ¤Äċ0(다시 æ»63r0¤Äċ0æ»63ŻṚ¤Äċ0것 또한 일)



@EriktheOutgolfer 나는 나 자신에게 "isNonNegative를 곱하는 골퍼 방법이 있어야한다"고 생각 Ƒ했고, 아주 빠른 작업 은 전혀 생각하지 않았다 !
Jonathan Allan

1
사실, 나는 꽤 오랫동안 이론을 꾸 ve습니다 . 그것이 벡터화되지 않는다는 것을 경고하십시오! ;-) 실제로 "평평한 다음 모든 요소가 음수가 아닌지 확인"입니다.
Outgolfer Erik

2

펄 5 , 37 바이트

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

온라인으로 사용해보십시오!

또는 "stringification"이 허용되지 않는 경우이 46 바이트 : sub z

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

s/length$&/$+[0]/(-3 바이트);)
Dada

IMO에서는 subPerl 5 기능이 포함 된 답변 에서 키워드 를 제거 할 수 없습니다 .
nwellnhof

sub다른 언어, perl6, powershell 등의 답변 에서 제거하는 것과 비슷한 것이 나타났습니다 .
Kjetil S.

Perl6에서는 Perl6 sub{}답변에서 왜 생략되었는지 설명하는 (익명?) 하위를 만들 필요가 없다고 생각합니다 . @nwellnhof에 동의하지 않아야합니다 sub. (내가 1 년 전과 같이 여전히 활동적이었을 때, 그것이 규칙이었습니다)
Dada

지금 바뀌었다. 그리고 포함되어 있습니다 $+[0].
Kjetil S.

2

스위프트 (64 비트 플랫폼), 41 바이트

f을 수락하고 반환하는 클로저를 선언 합니다 Int. 이 솔루션은 제대로 64 비트 플랫폼, 작동 Int됩니다 typealias에 에드 Int64. 32 비트 플랫폼에서는 Int64클로저의 매개 변수 유형에 2 바이트를 추가하여 명시 적으로 사용할 수 있습니다.

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

Swift에서 기본 정수 유형조차 표준 라이브러리에 선언 된 일반 객체입니다. 즉 , 표준 라이브러리 프로토콜을 준수하는 모든 유형에 필요한 Int메소드 및 특성을 가질 수 있습니다 .leadingZeroBitCountFixedWidthInteger


흥미 롭군 녹을 생각 나게합니다. 나는 그것이 20 바이트로 계산되어야한다고 생각한다. .leadingZeroBitCount
밝게

2

하스켈 , 24 바이트

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

온라인으로 사용해보십시오!

이것은 기본적으로 Kevin Cruijssen의 Java 솔루션과 동일하지만 독립적으로 찾았습니다.

인수는 Int64 비트 빌드 또는 Int64기타 유형이어야합니다 .

설명

인수가 음수이면 결과는 즉시 0입니다. 그렇지 않으면 왼쪽으로 이동 하여 하나를 채 웁니다. 음수에 도달 할 때까지 합니다. 이 충전으로 0에 대한 특별한 경우를 피할 수 있습니다.

참고로 여기에 분명하고 효율적인 방법이 있습니다.

34 바이트

import Data.Bits
countLeadingZeros



1

펄 5 -p , 42 바이트

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

온라인으로 사용해보십시오!

비트 열 기반 솔루션보다 길지만 적절한 수학 기반 솔루션입니다.


내가 실수 하지 않으면 실제로 작동 하지 않습니다
Dada

@Dada 부동 소수점 나누기가 제대로 작동하지 않는 경우가 몇 가지 있습니다. int문제를 해결하기 위해 전화를 걸었 습니다 .
Xcali

죄송합니다. 복사 붙여 넣기에 실패한 것 같습니다. 이것은 내가 보내고 싶었던 것입니다;)
Dada

1

APL (NARS), 15 자, 30 바이트

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

사용 방법을 보려면 몇 가지 숫자를 테스트하십시오.

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




1

Wolfram Language (Mathematica) , 41 바이트

양수에 대한 공식은 단지 63-Floor@Log2@#&입니다. 교체 규칙은 특수 입력 0 및 음수 입력에 사용됩니다.

입력은 64 비트 부호있는 정수일 필요는 없습니다. 이것은 입력의 바닥을 효과적으로 정수로 바꿉니다. 64 비트 정수에 대해 정상 범위 밖의 숫자를 입력하면이 정수를 저장하는 데 필요한 비트 수를 나타내는 음수를 반환합니다.

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

온라인으로 사용해보십시오!

@ LegionMammal978의 솔루션은 28 바이트에서 약간 짧습니다. 입력은 정수 여야합니다. 문서에 따르면 : " BitLength[n]효과적으로 효율적인 버전입니다 Floor[Log[2,n]]+1."이 (가) 아닌 정확한보고 0가없는 경우를 자동으로 처리합니다 -∞.

Wolfram Language (Mathematica) , 28 바이트

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

온라인으로 사용해보십시오!


1
Boole[#>=0](64-BitLength@#)&28 바이트에서 조금 짧습니다. 그것은 당신과 같은 기본 개념을 사용하지만 BitLength및 적용됩니다 Boole.
LegionMammal978

나는 BitLength를 완전히 잊었다!
Kelly Lowder

1

bitNumber-math.ceil (math.log (number) / math.log (2))

예 : 64 비트 NUMBER : 9223372036854775807 math.ceil (math.log (9223372036854775807) / math.log (2)) ANS : 63


여기에 언어 이름을 추가 할 수 있다면 사람들은 언어 이름이 포함되지 않은 답변에 대한 투표를 거절 할 가능성이 높습니다.
Jono 2906
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.