Encontre o Segundo Zero


10

Desafio

Dado um número inteiro no formato de complemento de dois bits de 32 bits , retorne o índice do segundo dígito zero menos significativo na representação binária, em que um índice 0representa o bit menos significativo e um índice 31representa o bit mais significativo.

Se não houver um segundo zero, você pode retornar 0, qualquer número negativo, qualquer valor falso ou relatar um erro de uma maneira que faça sentido no seu idioma.

Você pode usar a indexação 1, se preferir, mas os casos de teste abaixo usarão a indexação 0.

Você pode usar números inteiros não assinados, se preferir; Se o fizer, você deve manipular números inteiros no intervalo [0, 2^32). Se você usar números inteiros assinados, deverá manipular números inteiros no intervalo [-2^31, 2^31). Os casos de teste aqui usarão números inteiros assinados, mas observe que -x(assinado) é 2^32 - x(não assinado).

Casos de teste

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

Pontuação

Isso é , então a resposta mais curta em cada idioma vence!


Podemos usar um número inteiro não assinado?
Leaky Nun

Sim, você pode, desde que lide com números inteiros no intervalo [0, 2^32).
musicman523

11
Estamos pegando o número inteiro ou a string 0b...como entrada?
TheLethalCoder

11
@ JonathanAllan Acho que não, já que fui corrigido na minha resposta da Jelly 2^32-1porque não deveria voltar 33.
Erik the Outgolfer

11
A resposta de @JonathanAllan Erik está correta. Eu atualizei a especificação desafio para refletir que você deve lidar com inteiros de 32 bits se você optar por tomá-los como sinal ou sem sinal
musicman523

Respostas:


16

Python 2 , 45 bytes

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

Experimente online!

Usa indexação 0, números não assinados e gera um erro no segundo zero.

Simplesmente cria uma lista de índices de bits não definidos, do menor para o maior, e retorna a segunda entrada.


5
Bem-vindo ao PPCG! Bom primeiro post!
Erik the Outgolfer

Obrigado! Ainda sou muito novo em truques de golfe em Python, por isso estou feliz que esse código não tenha sido jogado imediatamente.
9609 Arnold Palmer

Ótimo :) e quanto a n = 2147483647?
Mdahmoune 17/07/2017

@mdahmoune 2 ** 31-1 deve erro fora desde a sua representação binária em 32 bits é 0b01111111111111111111111111111111, que não tem uma segunda 0. A menos que eu estou faltando alguma coisa ...
Arnold Palmer

6

JavaScript (ES6), 34 bytes

Retorna um índice com base em 0 ou -1se nenhum segundo zero for encontrado.

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

Casos de teste

Expressão alternativa

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

Versão recursiva, 42 bytes

Retorna um índice com base em 0 ou falsese nenhum segundo zero for encontrado.

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

Como?

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

Casos de teste

Versão alternativa sugerida por Neil, 41 bytes

Retorna um índice baseado em 0 ou gera um erro de recursão em excesso se nenhum segundo zero for encontrado.

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

Versão recursiva de 41 bytes:f=(n,c=1)=>n%2?1+f(~-n/2,c):c&&1+f(n/2,0)
Neil

5

Geléia , 7 bytes

|‘‘&~l2

Experimente online!

Ele gera algo que não está no intervalo [1,31] se não houver o segundo zero. Isso inclui 32 33e (-inf+nanj). Eu acho que isso faz algum sentido.

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


11
-inf+nanjEu não acho que poderia mesmo existir
Luis Mendo

Ele não gera (-inf+nanj)uma entrada 2147483647com uma representação binária de 31 1s; portanto, não existe um segundo zero na notação assinada de 32 bits (é por isso que é muito mais curto do que o meu e as respostas de Erik).
Jonathan Allan

Na verdade, quando se ele produzir (-inf+nanj)?
Jonathan Allan

... ah eu acho que funcionou, você está usando a opção assinada?
Jonathan Allan

4

Java, ... 194191186 bytes

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 Bytes por usar nomes de variáveis ​​menores e remover espaços em branco
-25 Bytes, depois de pegar variáveis ​​ainda mais curtas e graças às dicas do @KevinCruijssen
-18 Bytes, mais espaços em branco, nome da função
-3 Bytes, graças ao @KevinCruijssen, reduzindo a condição
-5 Bytes , Graças a @Arnold Palmer, @KevinCruijssen, encurtando o loop

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;
}

Bem-vindo ao PPCG! Existem algumas coisas que você pode jogar golfe: static pode ser removido; if(n<0||n>o){return 0;}pode ser if(n<0|n>o)return 0;(em |vez de ||e sem colchetes); bs, bsaetc. podem ser caracteres únicos (nunca use nomes de variáveis ​​/ métodos de vários bytes no code-golf); Você pode combinar ints, como este: int o=2^32-2,c=0,i=x.length,l=i-1;. E há mais algumas coisas para jogar golfe. Dicas para jogar golfe em Java e Dicas para jogar golfe em todos os idiomas podem ser interessantes para ler. Mais uma vez bem-vindo, e aproveite a sua estadia! :)
Kevin Cruijssen

Eu acho que ainda existem alguns espaços que você pode remover nas suas declarações de variáveis. Bem-vinda! :)
musicman523

@ musicman523 Obrigado, sim, corrigi-lo. 194 por enquanto :)
0x45 18/07/2015

11
if(c[i]=='0'){j++;}ainda pode ser jogado if(c[i]==48)j++;para -3 bytes :) EDIT: Ou melhor ainda: while(j<2&&i>0){i--;if(c[i]=='0'){j++;}}pode ser for(;j<2&i>0;j+=c[i--]==48?1:0);para -8 bytes.
18717 Kevin Kevin Kurtijssen

11
@ 0x45 Eu acredito que se você alterar o código de @ KevinCruijssen for(;j<2&i>0;j+=c[--i]==48?1:0);, deve funcionar. O erro vem do icomprimento da string, então, inicialmente, você está tentando indexar além dos limites da matriz. Se você fizer um pré-decréscimo (conforme mostrado no snippet atualizado), na primeira vez em que o usar, ele será acessado c[c.length-1]como no seu código original.
Arnold Palmer


3

Código de máquina IA-32, 14 13 bytes

Hexdump:

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

Lista de desmontagem:

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

Recebe entrada ecx; saída é em al. Retorna 0 em erro.

Antes de tudo, inverte a entrada, para poder usar as instruções de verificação de bits para procurar por bits definidos. Ele procura o bit de conjunto menos significativo, redefine-o, procura o bit de conjunto menos significativo novamente e retorna o resultado.

Se a instrução bit-scan não encontrar nenhum bit definido, a documentação da Intel diz que a saída é indefinida. No entanto, na prática, todos os processadores deixam o registro de destino inalterado nesse caso (conforme observado por Cody Gray, a documentação da AMD descreve esse comportamento como obrigatório).

Portanto, existem os seguintes casos:

  1. Nenhum bit zero (binário 111 ... 1): ecx é definido como 0 por note permanece 0
  2. Um bit zero: ecx é definido como 0 por btre permanece 0 apósbsf
  3. Dois bits zero: ecx é definido no valor adequado por bsf

É apenas a documentação da Intel que diz que as varreduras de bits em 0 são indefinidas. A documentação da AMD documenta explicitamente que o destino é inalterado. Se você deseja evitar esse comportamento, normalmente adicionaria o prefixo REP para obter LZCNT ou TZCNT, mas isso aumenta a contagem de bytes, o que é naturalmente indesejável para o golfe de código.
Cody Grey

11
Você está realmente fazendo muito trabalho aqui. O desafio não exige que você discrimine entre o caso em que não há zero bits e o caso em que há apenas 1 bit. Permite retornar 0 (ou qualquer valor negativo) nos dois casos. Portanto, embora o 1 byte SALC+ DECseja extremamente inteligente, você pode cortar um byte usando apenas o que estiver na ECXsegunda BSFinstrução. A única coisa que requer é um byte XCHGpara obter o resultado, EAXpara que possa ser retornado. Em outras palavras,not ecx; bsf eax, ecx; btr ecx, eax; bsf ecx, ecx; xchg eax, ecx; ret
Cody Grey

11
Aqui está um link "experimente online" para os itens acima . Como você está usando ECXcomo registro de entrada, precisamos informar ao GCC para usar a convenção de chamada de chamada rápida.
Cody Grey

2

Dyalog APL, 20 bytes

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

Usa indexação 1, lança INDEX ERRORem caso de nenhum segundo zero.

Como?

⍵⊤⍨- codificar como

32⍴2 - sequência binária de comprimento 32

- marcha ré

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

(⍳32)/⍨ - comprimir com o intervalo de 1 a 32 (deixando índices de zeros)

2⊃ - escolha o segundo elemento


Você pode salvar muitos bytes usando Where ( )
TwiNight 17/07/17

@TwiNight eu uso o dyalog 14
Uriel

TIO tem Dyalog 16 se precisar
TwiNight


1

Gelatina , 12 bytes

,4BUFḣ32¬TḊḢ

Um link monádico, usando um número inteiro, usando a opção não assinada e retornando o resultado indexado em 1 (retorna 0 quando não existe).

Experimente online!

ou

32Ḷ2*|€n⁸TḊḢ

Tente isso

Como?

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

código de máquina x86_64, 34 32 bytes

Não tenho certeza se essa é a abordagem correta, muitos bytes (acontece que não é ):

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

Experimente online!

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

Obrigado @CodyGray pelos -2bytes.


11
Fazer um loop em todos os bits provavelmente não é a abordagem correta, seja para o golfe com código ou para o mundo real. O avanço real estará usando uma das instruções que lhe permitem manipular todos os 32 (ou 64) bits de uma vez, como BSF, BSR, POPCNT, BT, etc. Anatolyg tem apresentado uma solução ao longo destas linhas . Ainda não determinei se pode ser derrotado. :-p
Cody Gray

11
A propósito, um truque de código-golfe potencialmente útil para definir um registro como -1 é OU com -1. Por exemplo or ecx, -1,. São 3 bytes, 1 byte menor que XOR + NEG. Este não é um bom truque quando não está jogando golfe, pois introduz uma dependência de leitura falsa no registro de destino, mas você apenas usa mov ecx, -1e gasta os 5 bytes.
Cody Grey

1

8o , 149 bytes

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:@

Código comentado

: 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:@
;

Uso e saída

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 bytes

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

lê de stdin; retorna 0para nenhum segundo zero e o local, caso contrário.

Experimente online!

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.