Numero diverso, stesso peso


22

sfondo

Il peso di Hamming di un numero intero è il numero di quelli nella sua rappresentazione binaria. Per questa sfida, i numeri interi sono rappresentati con 32 bit e sono senza segno.

Sfida

Dato un numero intero compreso tra 0 e 2 ^ 32-1 (non inclusivo), genera un numero intero diverso all'interno dello stesso intervallo e anche con lo stesso peso di Hamming.

Esempi

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)

punteggio

Questo è , quindi vince la soluzione nel minor numero di byte in ogni lingua.


2
Suggerirei di aggiungere un numero dispari tra 2 ^ 31 + 1 e 2 ^ 32-3, poiché alcune risposte non riescono.
Ørjan Johansen,


Da quando hai appena aggiunto 2^31+2, ripeterò che ho detto un numero dispari . Le risposte in questione sono fallite solo quando sono presenti sia il bit più alto che quello più basso 1.
Ørjan Johansen,

Sono un pazzo. Grazie. Risolverà questo problema
musicman523,

1
@ musicman523 Mi è capitato di sfogliare domande attive e ho visto questo. E ho notato che non hai ancora aggiunto i casi di test richiesti.
Draco18s

Risposte:


29

assembly x86-64, 5 4 byte

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

Una funzione che utilizza la convenzione di chiamata C che ruota a bit il suo argomento lasciato di 1 bit.


Dannazione - Stavo per pubblicare esattamente questo - ben fatto :)
Digital Trauma,

12
assemblaggio batte Jelly: o
Uriel

Questo non si moltiplica per 2? Se è così, allora la mia risposta
Pyth da

@NoOneIsHere No, questa non è una moltiplicazione per 2. La moltiplicazione per 2 invia metà degli input al di fuori dell'intervallo richiesto e se si ignora il bit di overflow a sinistra, il peso di Hamming è diminuito di 1. Questo è un bit rotazione , che riporta il bit di overflow da destra.
Anders Kaseorg,

1
@DigitalTrauma GCC 4.9.0 e successivamente sono abbastanza intelligente per compilare n << 1 | n >> 31in rol, invece di ror(salvataggio di un byte).
Anders Kaseorg,

8

Python, 20 byte

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

Rotazione bit per bit lasciata di 1 bit.



6

Gelatina , 10 8 byte

‘&~^^N&$

Scambia il bit meno significativo impostato e non impostato.

Provalo online!

Come funziona

‘&~^^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 byte

Cerca la prima transizione di bit (0 → 1 o 1 → 0) e la inverte.

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

dimostrazione

Rotazione bit, 14 byte

Molto più breve ma meno divertente.

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

dimostrazione


Gli operatori JavaScript bit a bit forniscono numeri interi con segno a 32 bit anziché non firmati. Ad esempio, f(2147483647)è -1073741825ed (n=>n>>>31|n<<1)(2147483647)è -2.
Anders Kaseorg,

2
Va bene purché non ci siano più di 32 bit.
musicman523

Puoi aggiungere una spiegazione per la prima? Sto cercando di imparare Javascript, e sono un po 'perplesso su come stai chiamando f con k indefinito e stai ancora ottenendo una risposta ragionevole!
musicman523

2
@ musicman523 Ecco il suggerimento corrispondente. Fondamentalmente, kè inizialmente impostato su undefinede sfruttiamo il fatto che sia ~undefineduguale -1.
Arnauld,

@ musicman523 (Non sto più usando questo suggerimento nella versione aggiornata. Ma non esitate a chiedere se avete altre domande sulla risposta originale.)
Arnauld

4

Brain-Flak , 78 byte

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

Provalo online!

Restituisce 2n se n <2 ^ 31 e 2n + 1-2 ^ 32 in caso contrario. Sfortunatamente, poiché Brain-Flak non ha alcun modo rapido per determinare il segno di un numero, il programma scade su TIO se l'ingresso differisce da 2 ^ 31 di oltre 500000 circa.

Spiegazione

Innanzitutto, premi -2 ^ 32 nello stack:

(([()()])[[]()])                               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

Quindi, calcola l'output desiderato:

      (({}){})                        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

Provalo online .

Questa è un'implementazione aritmetica di una rotazione a 32 bit a destra:

?           # 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 byte

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

+12 byte cambiando intin long, perché intla dimensione massima è2³¹-1

100 89 byte salvati creando una porta della sorprendente risposta Python di @AndersKaseorg .

Provalo qui.

Uscite:

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)

Vecchia risposta ( 117 118 byte):

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

+1 byte cambiando intin long, perché intla dimensione massima è2³¹-1

Provalo qui.

Uscite:

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 byte

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

Provalo nella sandbox Wolfram

Ruota a sinistra aritmeticamente: prima moltiplica per 2, il che sposta eventualmente il numero fuori intervallo, quindi taglia la cifra fuori intervallo con Mod[...,2^32]e aggiungila nuovamente a destra con +Quotient[...,2^32].

(Mathematica ha un solo built-in che fornisce il modulo e il quoziente in una volta, ma è QuotientRemainder, che è un po 'un handicap del golf ...)


Mod 2 ^ 32-1? (4 in più)
user202729

2

APL, 12 byte

(2⊥32⍴1)|2×⊢

Come?

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


1

R, 42 63 byte

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

Mescola i bit in modo casuale, ma controlla per assicurarsi che non abbia restituito lo stesso numero per caso.


1

Spazio bianco , 81 80 byte

(1 byte salvato grazie a @ Ørjan Johansen ricordandomi che dup è più breve di push 0)

   
 
 	
					 
    	 
	 		
	 
   	        
 
 	  
 
 	  
	   
  
   	 
	 	 	
 	

Provalo online!

Fondamentalmente implementa un bit-shift destro ciclico usando l'aritmetica intera. Spingere una grande costante è costoso in Whitespace, quindi salviamo alcuni byte premendo 2 ^ 8 e quadrandolo due volte. (Salva 1 byte su (2 ^ 16) ^ 2 e 10 byte spingendo direttamente 2 ^ 32).

Spiegazione

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
Penso che tu possa sostituire il secondo push 0con un dupcomando precedente.
Ørjan Johansen,

Hai ragione, ho appena finito di aggiungere la sintassi del collegamento al mio transpiler, quindi l'ho usato troppo ...
Ephphatha,

0

Python 2.7, 89 byte

Programma completo:

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

Provalo online!

Suggerimenti benvenuti! :)


Ciò non è valido perché può per caso restituire di nuovo lo stesso numero.
Ørjan Johansen,





Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.