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.