異なる数、同じ重量


22

バックグラウンド

整数のハミング重みは、バイナリ表現の1の数です。このチャレンジでは、整数は32ビットで表され、符号なしです。

チャレンジ

0から2 ^ 32-1までの整数(非包括的)が与えられた場合、同じ範囲内で同じハミング重みを持つ異なる整数を出力します。

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)

得点

これはであるため、各言語の最小バイトでのソリューションが優先されます。


2
2 ^ 31 + 1から2 ^ 32-3の間に奇数を追加することをお勧めします。いくつかの答えが失敗しています。
Ørjanヨハンセン


追加したばかりなので2^31+2奇数を言ったことを繰り返します。問題の答えは場合にのみ、失敗の両方の最上位と最下位ビットです1
Ørjanヨハンセン

私はバカです。ありがとうございました。それを修正します
musicman523

1
@ musicman523私はたまたま活発な質問を閲覧していて、これを見ました。そして、リクエストされたテストケースをまだ追加していないことに気付きました。
Draco18s

回答:


29

x86-64アセンブリ、5 4バイト

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

ビットごとに引数を1ビット左に回転させるC呼び出し規約を使用する関数。


Dammit-まさにこれを投稿しようとしていた-よくやった:)
デジタルトラウマ

12
アセンブリーがゼリーを破る:o
ウリエル

これは2倍ではありませんか?もしそうなら、私の2バイトPythの答えは、おそらく勝利
NoOneIsHere

これは2の乗算2の乗算ではありません@NoOneIsHereませんが、必要な範囲の入力外の半分を送信し、あなたが左側のオーバーフロービットを無視した場合、あなたは1でハミング重みを減少させてきたこれは、ビット単位rotationは、右からオーバーフロービットを戻します。
アンダースカセオルグ

1
@DigitalTrauma GCC 4.9.0以降は、(バイトを節約する)代わりにコンパイルn << 1 | n >> 31するのrolに十分スマートrorです。
アンダースカセオルグ



6

ゼリー10 8バイト

‘&~^^N&$

最下位のセットビットとアンセットビットを交換します。

オンラインでお試しください!

使い方

‘&~^^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バイト

最初のビット遷移(0→1または1→0)を探し、それを反転します。

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

デモ

ビットローテーション、14バイト

はるかに短いが、あまり面白くない。

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

デモ


JavaScriptのビット演算子は、符号なしではなく32ビットの符号付き整数を提供します。たとえば、f(2147483647)is -1073741825および(n=>n>>>31|n<<1)(2147483647)is -2です。
アンデルスカセオルグ

2
32ビット以下であれば問題ありません。
musicman523

最初の説明を追加できますか?私はJavascriptを学ぼうとしていますが、未定義のkでfを呼び出す方法については少し迷っていますが、それでも妥当な答えが得られます!
musicman523

2
@ musicman523 ここでは、対応するチップです。基本的に、kはに初期設定されundefined、と~undefined等しいという事実を利用し-1ます。
アーナルド

@ musicman523(更新版ではもうこのヒントを使用していません。ただし、元の答えについて他に質問があるかどうかお気軽に。)
Arnauld

4

Brain-Flak、78バイト

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

オンラインでお試しください!

n <2 ^ 31の場合は2nを返し、そうでない場合は2n + 1-2 ^ 32を返します。残念ながら、Brain-Flakには数値の符号を決定する高速な方法がないため、入力が2 ^ 31から約500000以上異なる場合、プログラムはTIOでタイムアウトします。

説明

まず、-2 ^ 32をスタックにプッシュします。

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

次に、目的の出力を計算します。

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

オンラインでお試しください

これは、32ビットの右回転の算術実装です。

?           # 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バイト

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

変更することによって、12バイトintlong、ためintの最大サイズがあります2³¹-1

@AndersKaseorgのすばらしいPython回答のポートを作成することで100 89バイトを節約

ここで試してみてください。

出力:

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)

古い回答(117 118バイト):

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

変更することにより、1バイトintlongするので、intの最大サイズがあります2³¹-1

ここで試してみてください。

出力:

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バイト

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

Wolframサンドボックスで試してみてください

回転は、算術左:最初の乗算おそらく範囲外の数をシフト2で、次いで、範囲外の数字をカットMod[...,2^32]し、右側に戻ってそれを追加します+Quotient[...,2^32]

(Mathematicaにはモジュラスと商を一度に与える単一のビルトインがありますがQuotientRemainder、それはであり、これはちょっとしたゴルフのハンディキャップです…)


Mod 2 ^ 32-1?(あと4つ)
-user202729

2

APL、12バイト

(2⊥32⍴1)|2×⊢

どうやって?

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


1

R、42 63バイト

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

ランダムにビットをシャッフルしますが、偶然同じ番号を返さないことを確認します。


1

空白81 80バイト

(@ØrjanJohansenのおかげで、dupは0を押すより短いことを思い出させて、1バイトを節約しました)

   
 
 	
					 
    	 
	 		
	 
   	        
 
 	  
 
 	  
	   
  
   	 
	 	 	
 	

オンラインでお試しください!

基本的に、整数演算を使用して循環右ビットシフトを実装します。ホワイトスペースでは大きな定数をプッシュするとコストがかかるため、2 ^ 8をプッシュして2回二乗することでバイトを節約します。((2 ^ 16)^ 2で1バイト、2 ^ 32を直接プッシュして10バイト節約します。)

説明

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
私は、あなたが第二を交換することができると思うpush 0dup一つのコマンド早いです。
Ørjanヨハンセン

そうです、私はトランスパイラーにショートカット構文を追加し終えたので、使いすぎていました
...-Ephphatha






弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.