İkinci Sıfırı Bul


10

Meydan okuma

32 bit ikisinin tamamlayıcı biçiminde bir tamsayı verildiğinde , ikili gösterimde ikinci en az anlamlı sıfır basamağının dizinini döndürün; burada bir indeksi 0en az anlamlı biti ve en önemli biti temsil eden bir indeksi döndürür 31.

İkinci sıfır yoksa, 0'ı, herhangi bir negatif sayıyı, herhangi bir yanlış değeri döndürebilir veya bir hatayı kendi dilinizde anlamlı olacak şekilde bildirebilirsiniz.

İsterseniz 1-endeksleme kullanabilirsiniz, ancak aşağıdaki test senaryoları 0-endeksleme kullanacaktır.

İsterseniz işaretsiz tamsayılar kullanabilirsiniz; bunu yaparsanız, aralıktaki tamsayıları işlemeniz gerekir [0, 2^32). İşaretli tamsayılar kullanırsanız, aralıktaki tamsayıları işlemeniz gerekir [-2^31, 2^31). Buradaki test senaryolarında imzalı tamsayılar kullanılır, ancak -x(imzalı) 2^32 - x(imzasız) olduğuna dikkat edin .

Test Durumları

0 (0b00) -> 1
1 (0b001) -> 2
10 (0b1010) -> 2
11 (0b01011) -> 4
12 (0b1100) -> 1
23 (0b010111) -> 5
-1 (0b11..11) -> Yok
-2 (0b11..10) -> Yok
-4 (0b11..00) -> 1
-5 (0b11..1011) -> Yok
-9 (0b11..10111) -> Yok
2 ^ 31-2 (0b0111..1110) -> 31

puanlama

Bu , bu yüzden her dilde en kısa cevap kazanır!


Bunun yerine işaretsiz bir tam sayı kullanabilir miyiz?
Sızan Rahibe

Evet, aralıktaki tamsayıları işlediğiniz sürece yapabilirsiniz [0, 2^32).
musicman523

1
Tamsayıyı mı yoksa dizeyi 0b...girdi olarak mı alıyoruz ?
TheLethalCoder

1
@JonathanAllan Sanırım değil, çünkü Jelly cevabımda düzeltildi 2^32-1çünkü geri dönmemem gerekiyordu 33.
Outgolfer Erik

1
@JonathanAllan Erik'in cevabı doğru. 32-bit tamsayıları imzalı veya imzasız olarak almayı seçip seçmemenizi yansıtmak için meydan okuma özelliğini güncelledim
musicman523

Yanıtlar:


16

Python 2 , 45 bayt

lambda n:[i for i in range(32)if n|1<<i>n][1]

Çevrimiçi deneyin!

0 indeksleme, işaretsiz sayılar kullanır ve ikinci sıfıra bir hata atar.

En küçükten en yükseğe doğru ayarlanmamış bit indekslerinin bir listesini oluşturur ve ikinci girişi döndürür.


5
PPCG'ye Hoşgeldiniz! Güzel ilk gönderi!
Outgolfer Erik

Teşekkürler! Ben hala Python golf hile için gerçekten yeni, bu yüzden bu kod hemen aşağı golf alamadım sevindim.
Arnold Palmer

Harika :) n = 2147483647 hakkında?
mdahmoune

@mdahmoune 2 ** 31-1 32 bitlik ikili gösterimi 0b01111111111111111111111111111111 olduğundan ikinci bir 0'a sahip olmadığı için hata yapmalıdır ...
Arnold Palmer

6

JavaScript (ES6), 34 bayt

0 tabanlı bir dizin veya -1ikinci bir sıfır bulunmazsa döndürür .

n=>31-Math.clz32((n=~n^~n&-~n)&-n)

Test senaryoları

Alternatif ifade

n=>31-Math.clz32((n=~n^++n&-n)&-n)

Özyinelemeli sürüm, 42 bayt

0 tabanlı bir dizin veya falseikinci bir sıfır bulunmazsa döndürür .

f=(n,p=k=0)=>n&1||!k++?p<32&&f(n>>1,p+1):p

Nasıl?

f=(n,p=k=0)=>                               // given n, p, k
             n&1||                          // if the least significant bit of n is set
                  !k++?                     // or this is the 1st zero (k was not set):
                       p<31&&               //   return false if p is >= 31
                             f(n>>1,p+1)    //   or do a recursive call with n>>1 / p+1
                                        :p  // else: return p

Test senaryoları

Neil tarafından önerilen alternatif versiyon, 41 bytes

0 tabanlı bir dizin döndürür veya ikinci bir sıfır bulunmazsa çok fazla özyineleme hatası atar .

f=(n,c=1)=>n%2?1+f(~-n/2,c):c&&1+f(n/2,0)

41 bayt özyinelemeli sürüm:f=(n,c=1)=>n%2?1+f(~-n/2,c):c&&1+f(n/2,0)
Neil

5

Jöle , 7 bayt

|‘‘&~l2

Çevrimiçi deneyin!

İkinci sıfır yoksa, [1,31] aralığında olmayan bir çıktı verir. Buna 32 33ve içerir (-inf+nanj). Sanırım bu biraz mantıklı.

Hesaplar log(((x|(x+1))+1)&~x)/log(2).


1
-inf+nanjBunun var olabileceğini bile düşünmedim
Luis Mendo

İkili gösterimi 31 1s olan (-inf+nanj)bir giriş için çıktı vermez 2147483647, bu nedenle 32 bit imzalı notasyonda ikinci sıfır yoktur (bu yüzden benimkinden ve Erik'in cevaplarından çok daha kısadır).
Jonathan Allan

Aslında, ne zaman geliyor üretmesi (-inf+nanj)?
Jonathan Allan

... ah bence işe yaradı, imzalı seçeneği mi kullanıyorsun?
Jonathan Allan

4

Java, ... 194191 186 Bayt

static int f(int n){char[] c=Integer.toBinaryString(n).toCharArray();int j=0,o=2^32-2,i=c.length,l=i-1;if(n<0|n>o)return 0;for(;j<2&i>0;j+=c[--i]==48?1:0);if(j==2)return l-i;return 0;}

-159 Bayt küçük değişken adları kullanarak ve boşluk kaldırmak için
@KevinCruijssen ipuçları da kısa değişkenleri ve teşekkür aldıktan sonra, -25 Bytes
-18 Byte, daha boşlukların, işlev adı
kısaltarak -3 Byte, @KevinCruijssen sayesinde koşul ise
-5 Bayt , @Arnold Palmer, @KevinCruijssen, kısaltma döngüsü sayesinde

Ungolfed

public static int getPosSecondZero2(int number){
    int overflow = 2^32-2;
    if(number < 0 || number > overflow){
        return 0;
    }    
    String binaryString = Integer.toBinaryString(number);   
    char[] binaryCharArray = binaryString.toCharArray();    
    int count = 0;
    int idx = binaryCharArray.length;
    int length = binaryCharArray.length -1;
    while(count < 2 && idx>0){
        idx--;
        if(binaryCharArray[idx] == '0'){
            count++;
        }   
    }
    if(count == 2)
        return length-idx;
    return 0;
}

PPCG'ye Hoşgeldiniz! Golf yapabileceğiniz birkaç şey var: static kaldırılabilir; if(n<0||n>o){return 0;}olabilir if(n<0|n>o)return 0;( |yerine|| parantez ve parantezsiz); bs,, bsavb. tek karakter olabilir (kod-golf'de asla çok baytlı değişken / yöntem adları kullanmayın); Birleştirebilirsiniz intbu gibi s: int o=2^32-2,c=0,i=x.length,l=i-1;. Ve golf yapmak için birkaç şey daha var. Java golf için ipuçları ve tüm dillerde golf için ipuçları okumak ilginç olabilir. Yine hoş geldiniz ve kaldınız! :)
Kevin Cruijssen

Değişken beyanlarınızda kaldırabileceğiniz birkaç alan olduğunu düşünüyorum. Hoşgeldiniz! :)
musicman523

@ musicman523 Teşekkürler, evet düzelttim. Şimdilik 194 :)
0x45

1
if(c[i]=='0'){j++;}if(c[i]==48)j++;-3 bayt için hala golf olabilir :) EDIT: Veya daha iyisi: -8 bayt için while(j<2&&i>0){i--;if(c[i]=='0'){j++;}}olabilir for(;j<2&i>0;j+=c[i--]==48?1:0);.
Kevin Cruijssen

1
@ 0x45 @ KevinCruijssen'in kodunu değiştirirseniz for(;j<2&i>0;j+=c[--i]==48?1:0);işe yarayacağına inanıyorum . Hata, idizenin uzunluğu olmaktan geliyor , bu nedenle başlangıçta dizinin sınırlarını geçmeye çalışıyorsunuz. Bir ön azaltma yaparsanız (güncellenmiş snippet'te gösterildiği gibi), ilk kez kullandığınızda c[c.length-1]orijinal kodunuzdaki gibi erişir .
Arnold Palmer


3

IA-32 makine kodu, 14 13 bayt

HexDump:

F7 D1 0F BC C1 0F B3 C1 0F BC C9 91 C3

Sökme listesi:

0:  f7 d1                   not    ecx
2:  0f bc c1                bsf    eax,ecx
5:  0f b3 c1                btr    ecx,eax
8:  0f bc c1                bsf    ecx,ecx
b:  91                      xchg   eax, ecx
c:  c3                      ret

Girişi alır ecx ; çıktı çıktı al. Hata durumunda 0 döndürür.

Her şeyden önce, girişi tersine çevirir, böylece ayarlanmış bitleri aramak için bit tarama talimatlarını kullanabilir. En az anlamlı set bitini arar, sıfırlar, en az önemli set bitini tekrar arar ve sonucu döndürür.

Bit tarama talimatı ayarlanmış bir bit bulamazsa, Intel belgeleri çıktının tanımsız olduğunu söyler. Bununla birlikte, uygulamada tüm işlemciler bu durumda hedef kaydını değiştirmeden bırakır (Cody Gray tarafından belirtildiği gibi AMD belgeleri bu davranışı zorunlu olarak tanımlar).

Yani, aşağıdaki durumlar vardır:

  1. Sıfır bit yok (ikili 111 ... 1): ecx, 0'a ayarlanır ve 0 olarak notkalır
  2. Bir sıfır bit: ecx 0 ile ayarlanır btrve sonra 0 kalırbsf
  3. İki sıfır bit: ecx doğru değere bsf

0'da bit taramalarının tanımsız olduğunu söyleyen yalnızca Intel'in belgelerindendir. AMD belgeleri, hedefin değişmediğini açıkça belgelemektedir. Bu davranışı önlemek istiyorsanız, normalde LZCNT veya TZCNT almak için REP önekini eklersiniz, ancak bu, kod golfü için doğal olarak istenmeyen bayt sayısını artırır.
Cody Gray

1
Aslında burada çok fazla iş yapıyorsunuz. Zorluk, sıfır bitin bulunmadığı durum ile yalnızca 1 sıfır bitin bulunduğu durum arasında ayrım yapmanızı gerektirmez. Her iki durumda da 0 (veya herhangi bir negatif değer) döndürmenizi sağlar. 1 bayt So rağmen SALC+ DEColan son derece zeki, sadece ne varsa kullanarak bir bayt kapalı tıraş edebilirsiniz ECXikinci itibariyle BSFtalimatı. İhtiyacı olan tek şey XCHGsonucu almak için 1 bayttır , EAXböylece geri döndürülebilir. Başka bir deyişle,not ecx; bsf eax, ecx; btr ecx, eax; bsf ecx, ecx; xchg eax, ecx; ret
Cody Gray

1
İşte yukarıdakiler için "çevrimiçi deneyin" bağlantısı . Kullandığınız yana ECXgiriş kaydı olarak biz fastcall çağırma kuralını kullanmak GCC söylemek gerekir.
Cody Gray

2

Dyalog APL, 20 bayt

{2⊃(⍳32)/⍨~⌽⍵⊤⍨32⍴2}

1 endeksleme kullanır, INDEX ERRORikinci sıfır olmaması durumunda atar .

Nasıl?

⍵⊤⍨- kodlamak a olarak

32⍴2 - 32 uzunluğunda ikili dize

- tersine çevirmek

~ - olumsuzluk (0 → 1, 1 → 0)

(⍳32)/⍨ - 1-32 aralığıyla sıkıştırın (sıfır indekslerini bırakarak)

2⊃ - ikinci elemanı seç


Where ( )
TwiNight

@TwiNight Ben dyalog 14 kullanıyorum
Uriel

Gerekirse TIO Dyalog 16'ya sahiptir
TwiNight


1

Jöle , 12 bayt

,4BUFḣ32¬TḊḢ

Bir tamsayı alan, imzasız seçeneği kullanarak ve 1 dizinli sonucu döndüren bir monadik bağlantı (yok olduğunda 0 döndürür).

Çevrimiçi deneyin!

veya

32Ḷ2*|€n⁸TḊḢ

Bunu dene

Nasıl?

1.

,4BUFḣ32¬TḊḢ - Link: number, n   e.g. 14
,4           - pair with 4            [14,4]
  B          - to binary              [[1,1,1,0],[1,0,0]]
   U         - upend                  [[0,1,1,1],[0,0,1]]
    F        - flatten                [0,1,1,1,0,0,1]
     ḣ32     - head to 32             [0,1,1,1,0,0,1] (truncates the right if need be)
        ¬    - not (vectorises)       [1,0,0,0,1,1,0]
         T   - truthy indexes         [1,5,6]
          Ḋ  - dequeue                [5,6]
           Ḣ - head                   5
             -   if the dequeued list is empty the head yields 0

2.

32Ḷ2*|€n⁸TḊḢ - Link: number, n   e.g. 14
32Ḷ          - lowered range of 32    [ 0, 1, 2, 3, 4, 5, ...,31]
   2*        - 2 exponentiated        [ 1, 2, 4, 8,16,32, ...,2147483648]
     |€      - bitwise or for €ach    [15,14,14,14,30,46, ...,2147483662]
        ⁸    - chain's right argument 14
       n     - not equal?             [ 1, 0, 0, 0, 1, 1, ..., 1]
         T   - truthy indexes         [ 1, 5, 6, ..., 32]
          Ḋ  - dequeue                [ 5, 6, ..., 32]
           Ḣ - head                   5
             -   if the dequeued list is empty the head yields 0

1

x86_64 makine kodu, 34 32 bayt

Bunun doğru yaklaşım olup olmadığından emin değilim, oldukça fazla bayt (öyle değil ):

31 c0 83 c9 ff 89 fa 83 e2 01 83 f2 01 01 d1 7f 09 ff c0 d1 ef eb ee 83 c8 ff 83 f8 1f 7f f8 c3

Çevrimiçi deneyin!

second_zero:
  # Set eax = 0
  xor  %eax, %eax
  # Set ecx = -1
  xor %ecx,%ecx
  not %ecx

  # Loop over all bits
Loop:
  # Get current bit
  mov %edi, %edx
  and $0x1, %edx
  # Check if it's zero and possibly increment ecx
  xor $0x1, %edx
  add %edx, %ecx
  # If ecx > 0: we found the position & return
  jg Return
  # Increment the position
  inc %eax
  # Shift the input and loop
  shr %edi
  jmp Loop

Fix:
  # If there's not two 0, set value to -1
  xor %eax,%eax
  not %eax

Return:
  # Nasty fix: if position > 31 (e.g for -1 == 0b11..11)
  cmp $31, %eax
  jg  Fix

  ret

@CodyGray -2byte için teşekkürler .


1
Tüm kodların içinden geçmek, kod golfü veya gerçek dünya için muhtemelen doğru bir yaklaşım değildir. Gerçek atılım tek seferde 32 (veya 64) bit işlemek için izin talimatlar birini kullanarak olacak gibi BSF, BSR, POPCNT, BT, vb Anatolyg gelmiştir bu satırlar boyunca bir çözüm sundu . Henüz yenilebileceğine henüz karar vermedim. :-p
Cody Gray

1
Bu arada, -1'e bir kayıt ayarlamak için potansiyel olarak yararlı bir kod golf hilesi -1 ile VEYA. Örneğin or ecx, -1,. Bu 3 bayt, XOR + NEG'den 1 bayt daha kısa. Bu, golf yaparken iyi bir hile değildir çünkü hedef kayıt defterine yanlış bir okuma bağımlılığı getirir, ancak orada sadece mov ecx, -15 bayt kullanır ve harcarsınız.
Cody Gray

1

8 , 149 bayt

2 base swap >s nip decimal s:len 32 swap n:- ( "0" s:<+ ) swap times s:rev null s:/ a:new swap ( "0" s:= if a:push else drop then ) a:each swap 1 a:@

Yorumlanan kod

: f \ n -- a1 a2 n 

  \ decimal to binary conversion
  2 base swap >s nip decimal     

  \ 32bit formatting (padding with 0)            
  s:len 32 swap n:- ( "0" s:<+ ) swap times  

  \ put reversed binary number into an array 
  s:rev null s:/

  \ build a new array with position of each zero 
  a:new swap ( "0" s:= if a:push else drop then ) a:each

  \ put on TOS the position of the 2nd least least-significant zero digit
  swap 1 a:@
;

Kullanım ve çıktı

ok> : f 2 base swap >s nip decimal s:len 32 swap n:- ( "0" s:<+ ) swap times s:rev null s:/ a:new swap ( "0" s:= if a:push else drop then ) a:each swap 1 a:@ ;

ok> [0, 1, 10, 11, 12, 23, -1, -2, -4, -5, -9, 2147483646]

ok> ( dup . " -> " .  f . 2drop cr ) a:each
0 -> 1
1 -> 2
10 -> 2
11 -> 4
12 -> 1
23 -> 5
-1 -> null
-2 -> null
-4 -> 1
-5 -> null
-9 -> null
2147483646 -> 31

0

R , 66 bayt

w=which.min
x=strtoi(intToBits(scan()));w(x[-w(x)])*any(!x[-w(x)])

stdin'den okur; İadeler0ikinci sıfır olmadan ve aksi halde yer.

Çevrimiçi deneyin!

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.