「ビット借入」2つの数字


20

小さい数字が大きい数字からビットを借りることができることをご存知ですか?以下に例を示します。2つの数値5と14を考えてみましょう。最初に、それらをバイナリで書き出します。

5       14
000101  001110

最初に、大きい数値から最小のオンビットを取り、他の数値の最小のオフビットに与えます。そう

This bit turns off
            |
            v
000101  001110
    ^
    |
This bit turns on

今、私たちは持っています

000111  001100

数字は7と12です。最初の数字はまだ小さいので、続けます。

000111  001100
001111  001000

これで15と8になりましたので、停止できます。この一連の操作を「ビット借入」という2つの数字と呼びます。別の例を見てみましょう。20および61。

20        61
010100    111101
010101    111100
010111    111000
111111    100000
63        32

最終結果は32、63 です。もう1つやりましょう。31と12。31はすでに12よりも大きいため、何もする必要はありません。31と12をビット借用すると、31と12は変化しません。

チャレンジ

あなたの課題は、2つの数字を受け取り、それらをビット借用するプログラムまたは関数を作成することです。2つの数値は常に正の整数になります。入力と出力は、任意の合理的な形式にすることができます。

テストIO:

Input: 2, 3
Output: 3, 2

Input: 3, 2
Output: 3, 2

Input: 8, 23
Output: 31, 0

Input: 42, 81
Output: 63, 0

Input: 38, 41
Output: 47, 32

Input: 16, 73
Output: 23, 0

Input: 17, 17
Output: 17, 17

標準的な抜け穴が適用され、バイト単位の最短回答が勝ちます!

回答:


12

ゼリー、11 バイト

~1¦&N$^µ</¿

オンラインでお試しください!または、すべてのテストケースを確認します

バックグラウンド

次のように、整数nの最後のセットビットを抽出できます。

n + 1は、nのすべての後続設定ビットと隣接する未設定ビットを切り替えます。たとえば、10011 2 + 1 = 10100 2です。

以降〜N = - (N + 1)= -N - 1-N =〜N + 1、そう-N NOTのビット毎に上記適用N(トグル全てこうして最後の前にすべてのビットをトグル、ビット)1

例えば、-10100 2 =〜10100 2 + 1 = 01011 2 + 1 = 01100 2

撮影によって-n N&ビット単位のN-n(に等しくないので、最後に設定されたビットの前に全てのビットが無効化され、N及び-Nこうしての最後のセットビット得)nは

たとえば、10100 2&-10100 2 = 10100 2&01100 2 = 00100 2

したがって、XOR演算のnn個&-nの設定解除最後のセットビットのn

逆に、最後のセットビット設定解除するために、Nを、それが上に適用すればよいN〜我々は式を導き出すところから、N ^(〜N& - 〜N)

使い方

~1¦&N$^µ</¿  Main link. Argument: A (list of pairs)

          ¿  While loop:
        </     Condition: Reduce p by less-than. True iff x < y.
       µ       Body chain:
~1¦              Apply bitwise NOT to the x, first item of the pair.
     $           Convert the two links to the left into a monadic chain.
    N              Negate; multiply [~x, y] by -1, yielding [-~x, -y].
   &               Logical AND. Yields [-~x & ~x, -y & y].
      ^            Vectorized XOR with p. Yields [(-~x & ~x) ^ x, (-y & y) ^ y].

6

J、31 26バイト

,`(($:~(OR>:))~(AND<:))@.<

再帰とビット単位のトリックを使用した簡単なアプローチ。(に設定をオフにするために、0)、最も右(上の1値の)ビットは、N、あなたはビット単位-との間で行うことができ、NおよびN -1、および(に設定をオンにする1一番右)を値nに対してoff(0)ビットを使用すると、ビット単位で、またはnn +1の間で実行できます。

使用法

入力は2つの整数で構成され、1つはLHSに適用され、もう1つはRHSに適用され、出力はビット借用値のリストです。

   f =: ,`(($:~(OR>:))~(AND<:))@.<
   2 f 3
3 2
   3 f 2
3 2
   8 f 23
31 0
   42 f 81
63 0
   38 f 41
47 32
   16 f 73
23 0
   17 f 17
17 17

説明

,`(($:~(OR>:))~(AND<:))@.<  Input: x on LHS, y on RHS
                            If x < y,
,                             Form a 2-element array [x, y] and return
                            Else
                   <:         Decrement y
                AND           Perform bitwise-and on y and y-1, call it y'
          >:                  Increment x
        OR                    Perform bitwise-or on x and x+1, call it x'
    $:                        Call recursively on x' and y' and return

いい答えだ!回答を投稿した後、チャレンジを変更して申し訳ありませんが、チャレンジを少し簡略化しました。(リストを繰り返す必要はありません)。これにより、もう少し短くすることができます。
DJMcMayhem

@DrGreenEg​​gsandIronMan Jは、明示的なランク付けを行わずに、2つの配列間で実際に関数を要素ごとに適用しています。これは素晴らしいことです。別のトリックがない限り、おそらく同じままです。
マイル

4

Python、42バイト

f=lambda x,y:x<y and f(x|x+1,y&y-1)or(x,y)

4バイトのゴルフをしてくれた@ jimmy23013に感謝します! 2バイトのゴルフをしてくれた@LeakyNunに感謝します!

Ideoneでテストします。


3

Mathematica、46バイト

If[#<#2,BitOr[#,#+1]~#0~BitAnd[#2,#2-1],{##}]&

Jのソリューションで使用したものと同じ方法

@ Martinに1バイトの節約とinfixアプリケーションを思い出させてくれてありがとう~

使用法

入力は2つの整数引数で構成され、出力はビット借用値のリストです。

例


面白いことを試してみようと思ったが、残念ながら1バイト長くなっています:(#//.{x_,y_}/;x<y:>{BitOr[x,x+1],BitAnd[y,y-1]}&ただし、それを短くする方法を考えているかもしれません)
マーティンエンダー

それはきちんとしたルールですが、私はゴルフのルールにあまり詳しくありません。私は通常、代用/.と条件のみを使用します/;。希望するMathematicaは、引数の型&&などを検査することでブール型とビット単位を切り替えることができます。
マイル

3

Pyth、29 27 25 22 21 20 19 18 16バイト

MxG ^ 2x _ + \ 0.BG`HCm.W <FHgVZU2dC 
MxG ^ 2x_ + 0jG2HCm.W <FHgVZU2dC 
Cm.W <FH.bxN ^ 2x_ + 0jN2YZ2dC 
m.W <FH.bxN ^ 2x_ + 0j       - N2YZ形式
 mW <FH.exb ^ 2x_ + 0jb2kZ 
m.W <FH.U ,. | bhb。&ZtZZ 
.W <FH.U ,. | bhb。&ZtZZ          <-変更された入出力形式
 .W <FH.U ,. | bhb。&ZtZ
.W <FH.U ,. | bhb。&t

テストスイート。


回答を投稿した後、チャレンジを変更して申し訳ありませんが、チャレンジを少し簡略化しました。(リストを繰り返す必要はありません)。ありがたいことに、それを短くすることができます。
DJMcMayhem

@DrGreenEg​​gsandIronMan 1バイトしか保存されません。Pyth 効率的です。
リーキー修道女


2

ラビリンス37 34バイト

?"
}
|=:{:
)   }
: :;-{
=&( {!;\!@

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

説明

クイックラビリンスプライマー:

  • Labyrinthは、任意の精度の整数のメインスタックと補助スタックの2つのスタックで動作し、最初は(暗黙の)無限量のゼロで埋められます。
  • ソースコードは迷路に似ており、命令ポインター(IP)が廊下をたどっています。すべての興味深い制御フローはジャンクションで発生します。IPに複数のセルがある場合、メインスタックの最上部が検査されます。値が負の場合、IPは左に、正の場合はIPが右に、そうでない場合は直進します。選択した方向が壁(つまり、スペース)によってブロックされている場合、IPは代わりに反対方向に移動します。

プログラムは、他の回答と同じアルゴリズムを使用しています。私たちは代わる(a, b)(a | a+1, b & b-1)限りとしてa < b。ゴルフをもう少し試した後、完全な説明を追加します。

IPは左上隅から始まり、右に進みます。?整数を読み取りますa。その後"は何もしませんが、IPがすぐに下がらないようにする必要があります。これも行き止まりなので、IPは向きを変え?て読み取りを実行しますb}その後bmainからauxに移動するため、次のようになります。

Main [ ... 0 a | b 0 ...] Aux

|それはビット単位のORをとるので、その後、何もしませんaし、を0a常に正であることがわかっているため、IPは東に向けられます(西に向けられないため)。これにより、プログラムのメインループが開始されます。私たちは、比較するために、短い直線区間で始めるab

=   Swap tops of stacks, i.e. swap a and b.
:   Duplicate b.
{   Pull a over to main.
:   Duplicate a.
}   Push one copy back to aux.
-   Compute b-a.

IPは現在、別のジャンクションにあります。まず、結果が正の場合を考えてみましょう。つまりb > a、もう1回繰り返しを実行する必要があります。その反復も完全に線形です。スタックは現在次のとおりです。

Main [ ... 0 b (b-a) | a 0 ...] Aux

;   Discard b-a.
:   Duplicate b.
(   Decrement.
&   Bitwise AND with b, clearing the least-significant 1.
=   Swap new b with old a.
:   Duplicate a.
)   Increment.
|   Bitwise OR with a, setting the least-significant 0.

そして、ループの開始点に戻ります(a再び正の値になるため、IPは再び東に向きます)。

ある時点b-aで正ではなくなった場合、IPは他の2つのパスのいずれかを使用します。どちらの場合でも、フェッチaして{から、IPがベンドをたどるコーナーにヒットし、で印刷aすることに注意してください!。スタックの最上部が再び表示さb-aれます。つまり、どちらの場合もIPは最終的に東に移動します。残っているのは、短い線形ビットです。

;   Discard b-a.
\   Print a linefeed.
!   Print b.
@   Terminate the program.

1

Java 7、73バイト

void d(int x,int y){while(x<y){x|=x+1;y&=y-1;}System.out.print(x+","+y);}

未ゴルフ&テストケース:

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

public class Main{
  static void d(int x, int y){
    while(x < y){
      x |= x + 1;
      y &= y - 1;
    }
    System.out.print(x + "," + y);
  }

  public static void main(String[] a){
    print(2, 3);
    print(3, 2);
    print(8, 23);
    print(42, 81);
    print(38, 41);
    print(16, 73);
    print(17, 17);
  }

  public static void print(int a, int b){
    d(a, b);
    System.out.println();
  }
}

出力:

3,2
3,2
31,0
63,0
47,32
23,0
17,17

古いチャレンジルール[ 126 125 123バイト]:

注:古いチャレンジルールでは、2つの整数の代わりに、2つの整数配列を入力として使用していました。

void d(int[]a,int[]b){int i=-1,x,y;while(++i<a.length){x=a[i];y=b[i];for(;x<y;x|=x+1,y&=y-1);System.out.println(x+","+y);}}

回答を投稿した後、チャレンジを変更して申し訳ありませんが、チャレンジを少し簡略化しました。(リストを繰り返す必要はありません)。ありがたいことに、短縮することができます。
DJMcMayhem

@DrGreenEg​​gsandIronMan編集済み。ところで、人々が答えを投稿した後にルールを変更することは通常悪い習慣です。(PS:上記の全員の回答についてコメントしていません。)
ケビンクルーイッセン

1
このようにwhileループを書き換えることができますfor(;x<y;x|=x+1,y&=y-1);
-cliffroot

そうだね。-_-私は最初からそれをより良く書けたらよかったのに。ありがたいことに、それは不合理なまたは劇的な変化ではありません。また、はい、すべての回答にコメントしませんでしたが、すべてのユーザーに通知しました。同じユーザーに何度も通知する気はありませんでした。デニスの投稿にはコメントしませんでしたが、それは彼が最初にそれを変更することを勧めたユーザーの一人だったからです。
DJMcMayhem


1

ジュリア、27バイト

x<|y=x<y?x|-~x<|y&~-y:[x,y]

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

使い方

<|目的のために二項演算子を定義します。Juliaの最近のバージョンでは未定義ですが、パーサーによって演算子としてまだ認識されています。一方で\(明示的に整数に対して定義されていないが)1バイト短くなり、その高い優先順位は交換が必要となるx|-~x<|y&~-y(x|-~x)\(y&~-y)これバイト数を増やし、。

<|最初の引数が厳密に2番目の引数より小さいかどうかをチェックします。その場合、引数x |を使用して自分自身を再帰的に呼び出します-〜x = x | (x + 1)およびy&〜-y = y&(y-1)

xに1を追加すると、後続のすべての設定ビットと最下位の未設定ビットがトグルされるため、x | (x + 1)は、最も低い未設定ビットを切り替えます(他のビットは切り替えません)。同様に、yから1を引くと、後続のすべての未設定ビットと最下位セットビットがトグルされるため、y&(y + 1)は最下位セットビットをトグルします。

最後に、不等式x <yが成立しなくなると<|、ペア[x、y]を返します。


0

MATLAB、67 66バイト

ループ:

function[]=f(x,y)
while x<y
x=bitor(x,x+1);y=bitand(y,y-1);end
x,y

再帰的(67バイト):

function[]=f(x,y)
if x<y
f(bitor(x,x+1),bitand(y,y-1))
else
x,y
end

他の多くの回答と同じようにビットを変更するアプローチ。


0

Clojure、63バイト

#(if(< % %2)(recur(bit-or %(inc %))(bit-and %2(dec %2)))[% %2])

Jのソリューションで使用したものと同じ方法

使用法

=> (def f #(if(< % %2)(recur(bit-or %(inc %))(bit-and %2(dec %2)))[% %2]))
=> (f 38 41)
[47 32]
=> (map (partial apply f) [[2 3] [3 2] [8 23] [42 81] [38 41] [16 73] [17 17]])
([3 2] [3 2] [31 0] [63 0] [47 32] [23 0] [17 17])
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.