64 bit tam sayıdaki baştaki sıfır sayısını bulun


18

Sorun:

64 bit işaretli tamsayıda önde gelen sıfır sayısını bulun

Kurallar:

  • Giriş dize olarak ele alınamaz; matematik ve bitsel işlemlerin algoritmayı tahrik ettiği herhangi bir şey olabilir
  • Çıktı dilden bağımsız olarak sayının 64 bit imzalı tamsayı gösterimine göre doğrulanmalıdır.
  • Varsayılan kod golf kuralları geçerlidir
  • Bayt cinsinden en kısa kod kazanır

Test senaryoları:

Bu testler ikinin tamamlayıcı imzalı tam sayılarını varsayar. Dilinizde / çözümünüzde imzalı tamsayıların farklı bir temsili yoksa veya kullanılıyorsa, lütfen bunu arayın ve alakalı olabilecek ek test durumları sağlayın. Çift kesinlik ile ilgili bazı test senaryoları ekledim, ancak lütfen listelenmesi gereken başkalarını önermekten çekinmeyin.

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'ye Hoşgeldiniz! "Girdi dize olarak değerlendirilemez" in arkasındaki neden nedir ? Bu, 64 bit tamsayıları işleyemeyen ve tamsayı alan daha fazla yanıta yol açması olası olmayan tüm dilleri diskalifiye eder , çünkü zaten mevcut olduğunda bu basit bir yoldur.
Arnauld

1
FalseBunun yerine geri dönebilir miyiz 0?
Jo King

4
@Arnauld Burada ve özellikle dize tabanlı çözümler gerektiren diğer sitelerde benzer sorular var, ancak soruyu matematik ve mantıksal işlemlere açan hiçbir şey yok. Umudum, bu soruna başka bir yerde henüz cevaplanmayan bir dizi farklı yaklaşım görmek. Bu, her şey dahil olmak üzere dize çözümlerine de açılmalı mıdır?
Dave,

4
X86 ve ARM dahil olmak üzere birçok CPU'nun bunun için belirli talimatları vardır (x86'nın aslında birkaç tane vardır). Programlama dillerinin neden bu özelliği göstermediğini merak ettim, çünkü bugün çoğu programlama dilinde montaj talimatlarını çağıramazsınız.
slebetman

1
@ user202729 Sanırım bu kötü ifade: Ben çıktı dili ne olursa olsun, sayının 64 bit imzalı tamsayı temsil karşı doğrulanmalıdır 'Bununla ne demek istediğim bu soru sıfır sayısını sıfır sayısı olarak tanımlamaktadır 64 bit işaretli bir tamsayı. Sanırım imzalı ve imzasız tamsayıları ortadan kaldırmak için bu kısıtlamayı yaptım.
Dave

Yanıtlar:


41

Linux'ta x86_64 makine dili, 6 bayt

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

Haswell veya K10 veya üstü bir işlemci gerektirir lzcnt.

Çevrimiçi deneyin!


20

1
Kullanılan arama kuralını belirtmenizi öneririm (Linux'ta
söylediniz

@qwr Parametre% rdi içinde iletildiği ve% rax içinde döndürüldüğü için SysV çağrı kuralı gibi görünüyor.
Logern

24

Altıgen , 78 70 bayt

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

Çevrimiçi deneyin!

Bu zorluk pratik bir dil için fazla önemsiz değil mi? ;)

yan uzunluk 6. 5 altıgen yan uzunluğa sığamıyorum.

açıklama


3
"Açıklama" da gerçekten çok güldüm. : D
Eric Duminil

1
Negatif sayıları / sıfırı ele almakta aşırı karmaşık olabileceğinizi düşünüyorum. Ben o ağır 2 ^ 64 hesaplama yapmadan yan uzunluk 5 içine benzer bir program sığdırmayı başardı . Yine de, açıkça iyi golf değil!
FryAmTheEggman

@fry Ah doğru, negatif sayılar her zaman 0 önde gelen sıfıra sahiptir ... bu da kesinlikle daha kısa bir programa yol açar çünkü 2 ^ 64 üretir uzun.
user202729

12

Python , 31 bayt

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

Çevrimiçi deneyin!

Ekspres &iki bölümün bitselidir :

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

67-len(bin(-n))Negatif olmayan girişleri için doğru cevabı verir. Bit uzunluğunu alır ve -0bönekini telafi etmek için 64'ten 3 olan 67'den çıkarır . Olumsuzluk, n==0bunu reddetmenin -önünde bir işaret üretmediği için ayarlama hilesidir .

Bunun & ~n>>64cevabı, bunun 0olumsuz olmasını sağlar n. Ne zaman n<0, ~n>>640'a eşittir (64 bit tamsayılarda), ve bununla birlikte verir 0. Zaman n>=0, ~n>>64değerlendirir için-1 ve yapmanın bir &-1etkisi yoktur.


Python 2 , 36 bayt

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

Çevrimiçi deneyin!

Aritmetik alternatif.


9

Java 8, 32 26 bayt.

Long::numberOfLeadingZeros

FTW inşa eder.

Kevin Cruijssen sayesinde -6 bayt

Çevrimiçi deneyin!


Ah, tamamen unuttum numberOfLeadingZeros.. 28 baytlık btw golf:n->n.numberOfLeadingZeros(n)
Kevin Cruijssen

2
Aslında, Long::numberOfLeadingZerosdaha da kısadır (26 bayt).
Kevin Cruijssen

6
Vay canına, Java'nın Python'u yenmesi çok sık gerçekleşmez. Tebrikler!
Eric Duminil

9

C (gcc) , 14 bayt

__builtin_clzl

Tio'da iyi çalışıyor

C (gcc) , 35 29 bayt

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

Çevrimiçi deneyin!

6 bayt için Dennis'den

C (gcc) derleyici bayrakları, 29 byte David Foerster

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

Çevrimiçi deneyin!


3
Sadece 64 bit makineler (veya LP64 / ILP64 / vb. ABI'li diğerleri) için kayda değer
Ruslan

1
Herhangi bir kullanımı daha da kısa olduğunu Tanrım, GCC yerleşik__builtin_clzl hangi ile ben yapabilirsiniz gelip .
David Foerster

@Ruslan: iyi bir nokta, long32 bit (Windows x64 dahil) olan sistemlerde ihtiyacınız var __builtin_clzll(uzun süre imzasız). godbolt.org/z/MACCKf . (Intel intrinsics aksine, GNU C builtins bakılmaksızın bir makine talimat ile yapılabilir olmanın operasyonun desteklenir 32 bit x86 yandan, bir dal veya cmov için clzll derler yapmak. lzcnt(low half)+32Ya lzcnt(high half)Or. bsrEğer lzcntkullanılamaz.
Peter Cordes

Test senaryoları "0" içerir, ancak __builtin_clz(l)(l)sıfır için tanımlanmamış bir davranıştır: "x 0 ise, sonuç tanımsızdır."
MCCCS

1
@MCCCS Çalışırsa önemlidir. Bu yüzden de son cevabı
saklıyorum

6

Perl 6 , 35 28 26 bayt

Nwellnhof sayesinde -2 bayt

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

Çevrimiçi deneyin!

Bir sayı alan ve bir sayı döndüren anonim kod bloğu. Bu, sayıyı bir ikili dizeye dönüştürür ve baştaki sıfırları sayar. Negatif sayılar için çalışır çünkü ilk karakter -örn.-00000101 , bu nedenle önde gelen sıfır yoktur.

Açıklama:

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

Girişi BigInt değişmezi olarak alır.

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

Çevrimiçi deneyin!

0


n=>n<1?0:n.toString(2)-64Aynı şeyi yapmaz mıydınız?
Ismael Miguel

Sanırım demek istediğim n=>n<1?0:n.toString(2).length-64, ama bu yine de işe yaramaz. Bence bu olur .
Arnauld

1
@IsmaelMiguel Endişelenme. :) .toString()Yaklaşımın işe yaraması gerçekten mümkün , ancak yine de girdi olarak bir BigInt hazır bilgisine ihtiyacımız var. Aksi takdirde, sadece 52 bit mantis var, bu da hassasiyet kaybolduğunda geçersiz sonuçlara yol açar .
Arnauld

1
BigInt sonekinin parametrenizle aynı karakter olması çok kafa karıştırıcı ...
Neil

1
@Neil PPCG'de okunamayan kod ?? Bu olamaz! Sabit! : p
Arnauld





4

05AB1E , 10 9 bayt

·bg65αsd*

G / Ç her ikisi de tamsayıdır

Çevrimiçi deneyin veya tüm test senaryolarını doğrulayın .

Açıklama:

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

Bir hata tespit ettiğiniz için teşekkürler xnor !

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

Oldukça fazla bellek ayırabilir, çevrimiçi deneyin!

Belki daha küçük bir sabitle test etmek istersiniz: 8 bit deneyin!

açıklama

mapM(pure[0,1])[1..64]Girdiyi ikiliye dönüştürmek için kullanmak yerine, mapM(pure[1,0])[1..64]aslında ters çevrilmiş dizeleri oluşturan{0,1}64sözlükbilimsel sırayla. Böylece,1kullanarak s-öneki sum.fst.span(>0).


3

Powershell, 51 bayt

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

Test komut dosyası:

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

Çıktı:

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 bayt

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

Gibi giriş long(64-bit tamsayı) olarak çıkış int(32 bit tamsayı).

Bağlantı noktası @ l4m2 'nin C (gcc) cevabı .

Çevrimiçi deneyin.

Açıklama:

 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: @lukeg Java 8 yanıt görüntülendiği gibi yerleşik kullanarak 26 bayt olabilir .Long::numberOfLeadingZeros


3

APL + WIN, 34 bayt

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

Açıklama:

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

Jöle ,  10  9 bayt

-1 Outgolfer Erik'in düzgün bir hilesi sayesinde (negatif olmayan şimdi basitçe )

ḤBL65_×AƑ

Bir tamsayı veren bir tamsayıyı (aralık dahilinde) kabul eden monadik bir Bağlantı.

Çevrimiçi deneyin! Veya test takımına bakın .


10 kişi ḤBL65_ɓ>-×

İşte "BOSS" dediği için sevdiğim 10 baytlık bir çözüm daha ...

BoṠS»-~%65

Test paketi burada

... BoṠS63r0¤i, BoṠS63ŻṚ¤iveya BoṠS64ḶṚ¤içalışır.


Başka bir 10 byter (Dennis'den) æ»64ḶṚ¤Äċ0(tekrar æ»63r0¤Äċ0ve æ»63ŻṚ¤Äċ0aynı zamanda çalışacak)



@EriktheOutgolfer Kendi kendime "isNonNegative ile çarpmak için daha golfçü bir yol olmalı" düşündüm ve Ƒhızlı, hiç de çok güzel bir iş düşünmüyordu !
Jonathan Allan

1
Aslında, bir süredir teorik davranıyorum . Vektörleşmediği konusunda uyarılmalıdır! ;-) Aslında "düzleştirin ve sonra tüm öğelerin negatif olup olmadığını kontrol edin".
Outgolfer Erik

2

Perl 5 , 37 bayt

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

Çevrimiçi deneyin!

Veya "dizgileştirmeye" izin verilmiyorsa bu 46 bayt: sub z

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

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

IMO, subanahtar kelimeyi Perl 5 işlevleri içeren yanıtlardan kaldırmanıza izin verilmez .
nwellnhof

subDiğer diller, perl6, powershell ve daha fazlası için cevapları kaldırmaya benzer şeyler gördüm .
Kjetil

Perl6'da, sub{}neden Perl6 cevaplarından çıkarıldığını açıklayan (anonim?) Bir alt yapmanız gerekmediğini düşünüyorum . @Nwellnhof ile kaldırmanıza izin verilmemesi gerektiğini kabul ediyorum sub. (hala aktifken, bir yıl kadar önce, bu kural
Dada

şimdi değişti. Ve dahil $+[0].
Kjetil S.

2

Swift (64 bit platformda), 41 bayt

Adlı bir kapatma bildirir f eden ve döndüren birInt . Bu çözüm sadece doğru 64 bit platformları, işler Intolduğu typealiasiçin ed Int64. (32 bit bir platformda, Int642 bayt ekleyerek kapağın parametre türü için açıkça kullanılabilir.)

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

Swift'te, temel tamsayı türü bile standart kütüphanede bildirilen sıradan bir nesnedir. Bu, Intaşağıdaki gibi yöntem ve özelliklere sahip olabileceği anlamına gelirleadingZeroBitCount (standart kütüphanenin FixedWidthIntegerprotokolüne uygun tüm tiplerde gerekli olan) .


ilginç. Bana Rust'u hatırlatıyor. Ben 20 bayt, .leadingZeroBitCount olarak saymak gerektiğini düşünüyorum
don parlak

2

Haskell , 24 bayt

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

Çevrimiçi deneyin!

Bu temelde Kevin Cruijssen'in Java çözümü ile aynı, ancak bağımsız olarak buldum.

Bağımsız değişken, Int64 bit derleme için türe sahip olmalıdır veyaInt64 herhangi bir şey için .

açıklama

Argüman negatifse, sonuç biz sola kaydırmaya, Aksi hemen 0'dır olanlarla doldurarak negatif bir sayı ulaşana kadar. Bu dolgu 0 için özel bir durumdan kaçınmamızı sağlar.

Sadece referans olarak, işte bariz / verimli yol:

34 bayt

import Data.Bits
countLeadingZeros



1

Perl 5 -p , 42 bayt

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

Çevrimiçi deneyin!

Bit dizisi tabanlı bir çözümden daha uzun, ama iyi bir matematik tabanlı çözüm.



@Dada Kayan nokta bölümünün düzgün çalışmadığı birkaç durum olduğunu görüyorum. intSorunu çözmesi gereken bir arama yaptım .
Xcali

Üzgünüm, görünüşe göre kopya geçmişimi geçemedim. Bu ben göndermek istedim budur;)
Dada

1

APL (NARS), 15 karakter, 30 bayt

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

nasıl kullanılacağını görmek için birkaç sayıyı test edin:

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


1

K (ngn / k) , 6 bayt

64-#2\

Çevrimiçi deneyin!

2\ argümanı ikili olarak kodlamak

# uzunluk

64- 64'ten çıkart


# = length... dize tabanlı görünüyor
Titus

2
@Titus 2\ tamsayıların bir listesini verir #ve uzunluğunu bulur. burada herhangi bir dizge yer almıyor.
ngn

1

PHP, 50 46 bayt

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

Pipo ile çalıştırın -Rveya çevrimiçi deneyin ,

<?=$argn<0?0:0|64-log($argn+1,2);yuvarlama sorunları var; bu yüzden çok yol aldım.


1

Wolfram Dili (Mathematica) , 41 bayt

Pozitif sayılar için formül sadece 63-Floor@Log2@#& . Özel sıfır ve negatif giriş durumları için değiştirme kuralları kullanılır.

Girişin 64 bit işaretli bir tam sayı olması gerekmez. Bu, girdiyi tamsayı haline getirmek için etkili bir şekilde katlanır. 64 bit tam sayı için normal sınırların dışında bir sayı girerseniz, bu tamsayıyı saklamak için daha fazla bitin gerekli olacağını belirten bir negatif sayı döndürür.

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

Çevrimiçi deneyin!

@ LegionMammal978'in çözümü 28 baytta oldukça kısadır. Giriş bir tamsayı olmalıdır. Belgelere göre: " BitLength[n]etkin bir şekilde verimli bir sürümüdür Floor[Log[2,n]]+1." Sıfır raporlama durumunu otomatik olarak doğru 0yerine ele alır-∞ .

Wolfram Dili (Mathematica) , 28 bayt

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

Çevrimiçi deneyin!


1
Boole[#>=0](64-BitLength@#)&28 baytta biraz daha kısadır. Sizinkiyle aynı temel kavramı kullanır, ancak geçerlidir BitLengthve Boole.
LegionMammal978

BitLength'yu tamamen unuttum!
Kelly Lowder

1

bitNumber - math.ceil (math.log (sayı) / math.log (2))

64 bit NUMBER: 9223372036854775807 math.ceil (math.log (9223372036854775807) / math.log (2)) ANS: 63


Buna dil adını ekleyebiliyorsanız, bu harika olurdu, çünkü insanlar dil adı dahil olmayan cevapları aşağıya indirebilirler
Jono 2906
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.