Número diferente, mismo peso

22

Fondo

El peso de Hamming de un entero es el número de unos en su representación binaria. Para este desafío, los enteros se representan con 32 bits y no están firmados.

Reto

Dado un número entero entre 0 y 2 ^ 32-1 (no incluido), genera un número entero diferente dentro del mismo rango y también con el mismo peso de Hamming.

Ejemplos

Input (Decimal) | Input (Binary) | Hamming weight | Possible output (Decimal)
       46       |   0b0010 1110  |       4        |      15
       12       |   0b0000 1100  |       2        |      3
        1       |   0b0000 0001  |       1        |      2
        3       |   0b0000 0011  |       2        |      6
      2^31      |   0b1000....0  |       1        |      1
      2^31+2    |   0b1000...10  |       2        |      3
      2^32-5    |   0b1111..011  |       31       |      2^31-1
      2^32-2    |   0b1111....0  |       31       |      2^31-1
        0       |   0b0000 0000  |       0        | None (This case need not be handled)
      2^32-1    |   0b1111....1  |       32       | None (This case need not be handled)

Tanteo

Este es el , por lo que gana la solución en la menor cantidad de bytes en cada idioma.

musicman523
fuente
2
Sugeriría agregar un número impar entre 2 ^ 31 + 1 y 2 ^ 32-3, ya que algunas respuestas fallan en eso.
Ørjan Johansen
Relacionado.
Martin Ender
Como acabas de agregar 2^31+2, repetiré que dije un número impar . Las respuestas en cuestión solo fallaron cuando tanto el bit más alto como el más bajo son 1.
Ørjan Johansen
Soy un tonto. Gracias. Lo arreglará
musicman523
1
@ musicman523 Simplemente estaba buscando preguntas activas y vi esta. Y notó que aún no ha agregado los casos de prueba solicitados.
Draco18s

Respuestas:

29

Ensamblado x86-64, 5 4 bytes

   0:   97                      xchg   %eax,%edi
   1:   d1 c0                   rol    %eax
   3:   c3                      retq   

Una función que utiliza la convención de llamada C que gira a nivel de bits su argumento a la izquierda en 1 bit.

Anders Kaseorg
fuente
Maldición - Estaba a punto de publicar exactamente esto - bien hecho :)
Digital Trauma
12
asamblea vence a Jelly: o
Uriel
¿No es esto multiplicar por 2? Si es así, entonces mi 2 bytes Pyth respuesta probablemente gana
NoOneIsHere
@NoOneIsHere No, esto no multiplicación por 2. La multiplicación por 2 envía la mitad de las entradas fuera del rango requerido, y si se ignora el bit de desbordamiento de la izquierda, que ha disminuido el peso de Hamming es por 1. Este es un bit a bit rotación , que devuelve el bit de desbordamiento desde la derecha.
Anders Kaseorg
1
@DigitalTrauma GCC 4.9.0 y posterior son lo suficientemente inteligentes como para compilar n << 1 | n >> 31en rollugar de ror(guardar un byte).
Anders Kaseorg
8

Python, 20 bytes

lambda x:x*2%~-2**32

Rotación bit a la izquierda por 1 bit.

Anders Kaseorg
fuente
6

MATL , 9 bytes

32&B1YSXB

Desplaza circularmente la representación binaria de 32 dígitos un paso hacia la derecha.

Pruébalo en línea!

Luis Mendo
fuente
6

Jalea , 10 8 bytes

‘&~^^N&$

Intercambia el bit menos definido y menos definido.

Pruébalo en línea!

Cómo funciona

‘&~^^N&$  Main link. Argument: n

‘         Increment; yield n+1, toggling all trailing set bits and the rightmost
          unset bit.
  ~       Bitwise NOT; yield ~n, toggling ALL bits of n.
 &        Bitwise AND; yield (n+1)&~n, keeping the only bit that differs in n+1 and
          ~n, i.e., the rightmost unset bit.
   ^      Perform bitwise XOR with n, toggling the rightmost unset bit.
       $  Combine the two links to the left into a monadic chain.
     N        Negate; yield -n. Since ~n = -(n+1) in 2's complement, -n = ~n+1.
      &       Take the bitwise AND of n and -n. Since -n = ~n + 1 and n = ~~n, the
              same reasoning that applied for (n+1)&~n applies to -n&n; it yields
              the rightmost unset bit of ~n, i.e., the rightmost set bit of n.
    ^      XOR the result to the left with the result to the right, toggling the
           rightmost set bit of the left one.
Dennis
fuente
5

JavaScript (ES6), 35 31 bytes

Busca la transición del primer bit (0 → 1 o 1 → 0) y la invierte.

f=(n,k=3)=>(n&k)%k?n^k:f(n,k*2)

Manifestación

Rotación de bits, 14 bytes.

Mucho más corto pero menos divertido.

n=>n>>>31|n<<1

Manifestación

Arnauld
fuente
Los operadores de bits de JavaScript proporcionan enteros con signo de 32 bits en lugar de sin signo. Por ejemplo, f(2147483647)es -1073741825y (n=>n>>>31|n<<1)(2147483647)es -2.
Anders Kaseorg
2
Está bien siempre que no haya más de 32 bits.
musicman523
¿Puedes agregar una explicación para la primera? Estoy tratando de aprender Javascript, y estoy un poco perdido en cuanto a cómo se llama f con k indefinido y aún así obtengo una respuesta razonable.
musicman523
2
@ musicman523 Aquí está el consejo correspondiente. Básicamente, kse establece inicialmente en undefinedy aprovechamos el hecho de que ~undefinedes igual -1.
Arnauld
@ musicman523 (ya no uso este consejo en la versión actualizada. Pero no dude en preguntar si tiene otras preguntas sobre la respuesta original).
Arnauld
4

Brain-Flak , 78 bytes

(([()()])[[]()]){((){}<({({})({}())}{})>)}{}([(({}(({}){})())<>)]){({}())<>}{}

Pruébalo en línea!

Devuelve 2n si n <2 ^ 31, y 2n + 1-2 ^ 32 de lo contrario. Desafortunadamente, debido a que Brain-Flak no tiene una forma rápida de determinar el signo de un número, el programa agota el tiempo de espera en TIO si la entrada difiere de 2 ^ 31 en más de aproximadamente 500000.

Explicación

Primero, empuja -2 ^ 32 en la pila:

(([()()])[[]()])                               push (initial value) -2 and (iterator) -5
                {((){}<                >)}     do 5 times:
                       ({({})({}())}{})        replace the current (negative) value with the negation of its square
                                            {}   pop the (now zero) iterator

Luego, calcule la salida deseada:

      (({}){})                        replace n by 2n on left stack
   ({}        ())                     push 2n+1-2^32 on left stack
  (              <>)                  push again on right stack
([                  ])                push its negation on right stack
                      {({}())<>}      add 1 to the top value of each stack until one of them reaches zero
                                {}    pop this zero, and implicitly print the number below it on the stack
Nitrodon
fuente
3

dc, 10

?2~z31^*+p

Pruébalo en línea .

Esta es una implementación aritmética de un giro a la derecha de 32 bits:

?           # input
 2~         # divmod by 2 - quotient pushed first, then the remainder
   z        # z pushes the size of the stack which will be 2 (quotient and remainder) ...
    31^     #  ... and take that 2 to the 31st power
       *    # multiply the remainder by 2^31
        +   # add
         p  # output
Trauma digital
fuente
3

Java 8, 117 17 29 bytes

n->n*2%~-(long)Math.pow(2,32)

+12 bytes cambiando inta long, porque intel tamaño máximo es2³¹-1

100 89 bytes guardados al crear un puerto de la sorprendente respuesta Python de @AndersKaseorg .

Pruébalo aquí

Salidas:

46 (101110):                                     92 (1011100)
12 (1100):                                       24 (11000)
1 (1):                                           2 (10)
3 (11):                                          6 (110)
10000 (10011100010000):                          20000 (100111000100000)
987654 (11110001001000000110):                   1975308 (111100010010000001100)
2147483648 (10000000000000000000000000000000):   1 (1)
4294967294 (11111111111111111111111111111110):   4294967293 (11111111111111111111111111111101)

Respuesta anterior ( 117 118 bytes):

n->{long r=0;for(;!n.toBinaryString(++r).replace("0","").equals(n.toBinaryString(n).replace("0",""))|r==n;);return r;}

+1 byte cambiando inta long, porque intel tamaño máximo es2³¹-1

Pruébalo aquí

Salidas:

46 (101110):                                     15 (1111)
12 (1100):                                       3 (11)
1 (1):                                           2 (10)
3 (11):                                          5 (101)
10000 (10011100010000):                          31 (11111)
987654 (11110001001000000110):                   255 (11111111)
2147483648 (10000000000000000000000000000000):   1 (1)
Kevin Cruijssen
fuente
2

Mathematica, 29 bytes

Mod@##+Quotient@##&[2#,2^32]&

Pruébalo en el sandbox de Wolfram

Rota a la izquierda aritméticamente: primero multiplique por 2, lo que posiblemente desplace el número fuera del rango, luego corte el dígito fuera del rango con Mod[...,2^32]y agréguelo nuevamente a la derecha con +Quotient[...,2^32].

(Mathematica tiene una sola construcción que da el módulo y el cociente de una vez, pero es QuotientRemainder, que es un poco una desventaja para el golf ...)

No un arbol
fuente
Mod 2 ^ 32-1? (4 más para ir)
usuario202729
2

APL, 12 bytes

(2⊥32⍴1)|2×⊢

¿Cómo?

           ⊢  ⍝ monadic argument
         2×   ⍝ shift left (×2)
(2⊥32⍴1)|     ⍝ modulo 2^32 - 1
Uriel
fuente
1

R, 42 63 bytes

function(x){s=x;while(s==x){sample(binaryLogic::as.binary(x))}}

Mezcla los bits aleatoriamente, pero se asegura de que no haya devuelto el mismo número por casualidad.

BLT
fuente
1

Espacios en blanco , 81 80 bytes

(1 byte guardado gracias a @ Ørjan Johansen que me recuerda que dup es más corto que push 0)

   
 
 	
					 
    	 
	 		
	 
   	        
 
 	  
 
 	  
	   
  
   	 
	 	 	
 	

Pruébalo en línea!

Básicamente implementa un desplazamiento de bits a la derecha cíclico utilizando aritmética de enteros. Empujar una constante grande es costoso en espacios en blanco, por lo que ahorramos algunos bytes presionando 2 ^ 8 y cuadrándolo dos veces. (Ahorra 1 byte sobre (2 ^ 16) ^ 2 y 10 bytes sobre empujando 2 ^ 32 directamente.)

Explicación

sssn  ; push 0
sns   ; dup
tntt  ; getnum from stdio
ttt   ; retrieve n from heap and put it on the stack
sns   ; dup
ssstsn ; push 2
tstt  ; mod - check if divisible by 2 (i.e. even)
ntsn  ; jez "even"
ssstssssssssn ; push 2^8
sns   ; dup
tssn  ; mul - square it to get 2^16
sns   ; dup
tssn  ; mul - square it to get 2^32
tsss  ; add 2^32 so MSB ends up set after the divide
nssn  ; even:
ssstsn ; push 2
tsts  ; divide by 2, aka shift right
tnst  ; putnum - display result
Ephphatha
fuente
1
Creo que puedes reemplazar el segundo push 0con un dupcomando anterior.
Ørjan Johansen
Tienes razón, acabo de terminar de agregar la sintaxis de acceso directo a mi transpiler, así que lo he estado usando demasiado ...
Ephphatha
0

Python 2.7, 89 bytes

Programa completo:

from random import*;a=list(bin(input())[2:].zfill(32));shuffle(a);print int(''.join(a),2)

Pruébalo en línea!

Sugerencias bienvenidas! :)

Koishore Roy
fuente
Eso no es válido porque por casualidad puede devolver el mismo número nuevamente.
Ørjan Johansen
0

Japt , 5 bytes

Ñ%3pH

Rotación bit a bit, como la mayoría de las respuestas aquí.

Intentalo

Encarnación de la ignorancia
fuente