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.


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


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.


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



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.

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


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

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

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)

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 ...)


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


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.


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

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! :)


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





Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.