隣人とビットを交換する


26

タスクの説明

整数が与えられた場合、すべての整数k> 0の(2k–1)番目と2k番目の最下位ビットを交換します。これは、OEISのシーケンスA057300です。

(数値には、「無限に多くの」先行ゼロがあると想定されます。実際には、これは単に、単一の0ビットを奇数長の数値の前に追加することを意味します。)

ここに画像の説明を入力してください

これはなので、最短のコード(バイト単位)が優先されます。

テストケース

0 -> 0
1 -> 2
9 -> 6
85 -> 170
220 -> 236
1827 -> 2835
47525 -> 30298

5
ビットシフトのようなものの整数として数値が適合すると仮定できますか?
xnor

1
@xnor:それがデフォルト/コミュニティのコンセンサスだと思います(そうでなければ、Cなどでの答えは常に間違っているでしょう)?確かに!:)
リン

@Lynn:Cはunsigned char array_of_bytes[1024]期待どおりに機能する必要があります(つまり、1024 * CHAR_BITエントリのビットフィールド)。CHAR_BITしかし、バイト間でビットをシフトするのは面倒なので、任意の長さの入力をサポートするほとんどの答えは均等であると仮定します。したがってk、256やAESにとって妥当なものなど、一定のサイズまでサポートする必要が絶対にあり、256ビット整数型のない言語ではループを使用する必要があります。P:それは、x86のasm答えを考慮SIMDベクトルの価値になるかもしれない
ピーター・コルド

2
@GeobitsとMinibitsを入れ替える
オプティマイザー

回答:



20

Python 2、26バイト

lambda n:2*n-3*(4**n/3&n/2)

ちょっとしたトリック!

セイはn、フォームを持っている...ghfedcbaバイナリに。次に、次のように他のすべてのビットに分割できます

n   = o + 2*e
n   = ...hgfedcba
o   = ...0g0e0c0a
2*e = ...h0f0d0b0

次に、ビット交換の結果sはとして表現できますs=2*o+e

s   = 2*o + e
s   = ...ghefcdab
2*o = ...g0e0c0a0
e   = ...0h0f0d0b

私たちは、むしろ一つだけの計算をしたいeo、私たちは、表現o=n-2*eと代替

s=2*(n-2*e)+e = 2*n-3*e

ですから、今ではeに関して表現することが残っていnます。数値M=4**n/3...101010101012進数形式で、奇数桁のマスクとして機能します。指数nは、それMが十分に長いことを保証します。のビット単位andを取り、n/2この値はe必要に応じて与えます。

n/2     = ...hgfedcb
M       = ...1010101
n/2 & M = ...h0f0d0b = e

代わりに、で表現eすることができますo e=(n-o)/2。これはs=(n+o*3)/2、xsotからの最適化のおかげでバイトを節約します。

lambda n:n+(n&4**n/3)*3>>1

優れた説明、およびから減算してマスクを1回だけ使用するための素敵なトリックn。ただし、私は反対の「奇数」対「偶数」ビット命名規則を好みます。LSBはビット0で、偶数です(最初のビットであっても)。シャッフルがインデックスを持つ要素を選択することが多いSIMDプログラミングでは、インデックスは0からカウントされるため、低要素を偶数要素と見なすのが普通です。例[ 3 2 1 0 ]
ピーターコーデス

式を使用してCの回答を追加しました。バイトの節約とDigital TraumaのCの答えのすべての功績は、これによるものです。
ピーターコーデス

2
26:lambda n:n+(n&4**n/3)*3>>1
xsot

@PeterCordesあなたのCコードはgcc 4.8.3とデフォルト設定で動作します。入力2に対して1f(x){return x+((x&~0U/3)*3)>>1;}返します。
デニス

@Dennis:ええ、Cで私のために働いています。calc実際にはCではなく(別名apcalc)で式をテストしていました。32ビットまたは2の補数への切り捨ては必要ないので、大丈夫だと思いました。表現が正しいとは思わなかったので、間違ったテストを信じて喜んでいた。しかし、とにかく、私はビットハックを開発するためにより良いREPLを必要としています。助言がありますか?(理想的には、bc -lまたはのようなLinuxコマンドラインですcalcが、実際にはint32_t/ uint32_tまたは何かを公開しますが、拡張精度ではありません。)
ピーターコーデス

10

C関数、38

ビット調整:

f(x){return(x&~0U/3*2)/2+(x&~0U/3)*2;}

イデオン。


またはそれの楽しみのために:

C再帰関数、43

OEISの式に従って、a(4n+k) = 4a(n) + a(k), 0 <= k <= 3

f(x){return x>3?4*f(x/4)+f(x%4):x%3?3-x:x;}

または

f(x){return x>3?4*f(x/4)+f(x%4):x%2*2+x/2;}

イデオン。


1
xnorの式の巧妙な変換により、これがCで32バイトになります。これは、別個の回答として投稿しました。これは、かなり異なるアプローチだからです。
ピーターコーデス

8

CJam、16 14 13バイト

ri4b4e!2=f=4b

ここでテストしてください。

説明

ri  e# Read input and convert to integer.
4b  e# Get base-4 digits.
4e! e# Push all permutations of [0 1 2 3].
2=  e# Select the third one which happens to be [0 2 1 3].
f=  e# For each base-4 digit select the value at that position in the previous
    e# list, which swaps 1s and 2s.
4b  e# Convert back from base 4.

順列を使ったそのトリックはとても良いです!
ルイスメンドー

7

Pyth、9バイト

iXjQ4S2)4

で試してみてください Pyth Compiler

使い方

  jQ4      Convert the input (Q) to base 4.
 X   S2)   Translate [1, 2] to [2, 1].
i       4  COnvert from base 4 to integer.

5

JavaScript(ES6)、32 30バイト

(n,m=0x55555555)=>n*2&~m|n/2&m

JavaScriptの整数の制限により、最大1073741823までしか機能しません。38 36バイトは4294967295まで機能します。

(n,m=0x55555555)=>(n*2&~m|n/2&m)>>>0

編集:@ user81655のおかげで2バイトを保存しました。

51バイトは最大4503599627370495まで機能します。

n=>parseInt(n.toString(4).replace(/1|2/g,n=>3-n),4)

でしたn<<1ことn*2
user81655

@ user81655そして、私も使用n/2できます!なぜこれらのことを考えなかったのか分かりません。
ニール

私は見たことがない>>>...それは何ですか?
タイタス

@Titus似て>>>いますが、符号なしシフトを行います。>>>0基本的に32ビットの符号なし整数に変換します。
ニール

5

x86 asm関数:14バイトのマシンコード

uint64_tバージョン:24バイト

x86-64 SysV呼び出し規約(xin edi)ですが、これと同じマシンコードは32ビットモードでも機能します。(ここleaとしてデコードしlea eax, [edi + eax*2]同一の結果を与えます)。

0000000000000040 <onemask_even>:
  40:   89 f8                   mov    eax,edi
  42:   25 55 55 55 55          and    eax,0x55555555
  47:   29 c7                   sub    edi,eax
  49:   d1 ef                   shr    edi,1
  4b:   8d 04 47                lea    eax,[rdi+rax*2]
  4e:   c3                      ret    
4f: <end>

0x4f - 0x40 = 14バイト

これは、xnorの優れたマスクワンスアイデアを逆の方法で使用した場合のコンパイラ出力です。(および反対の用語:下位ビットはビット0であり、奇数ではなく偶数です。)

unsigned onemask_even(unsigned x) {
  unsigned emask = ~0U/3;
  unsigned e = (x & emask);
  return e*2 + ((x - e) >> 1);
}

コンパイラーの機能に関して改善点は見当たりません。mov eax, 0x555.../ and eax, ediと書いたかもしれませんが、それは同じ長さです。


64ビット整数の同じ関数は24バイトかかります(godboltリンクを参照)。movabs rax, 0x55...レジスタにマスクを生成するための10バイトより短い方法は見当たりません。(x86のdiv命令は不格好であるため、3によるオールワンの符号なし除算は役に立たない。)

raxでマスクを生成するループを考え出しましたが、10バイトです(正確にの長さと同じですmov imm64)。

# since 0x55 has its low bit set, shifting it out the top of RAX will set CF
0000000000000000 <swap_bitpairs64>:
   0:   31 c0                   xor    eax,eax      ; old garbage in rax could end the loop early
0000000000000002 <swap_bitpairs64.loop>:
   2:   48 c1 e0 08             shl    rax,0x8
   6:   b0 55                   mov    al,0x55      ; set the low byte
   8:   73 f8                   jnc    2 <swap_bitpairs64.loop>  ; loop until CF is set
000000000000000a <swap_bitpairs64.rest_of_function_as_normal>:
 # 10 bytes, same as   mov  rax, 0x5555555555555555
 # rax = 0x5555...
   a:   48 21 f8                and    rax,rdi
   ...

の既存のバイトにrax低ビットが設定されていないことがわかっている場合、をスキップできxor、これは8バイト長になります。

この回答の以前のバージョンには、loopinsn を使用した10バイトのループがありましたが、を0xFFFFFFFFFFFFFF08設定しclただけなので、最悪の場合の反復の実行時間がありました。


5

Oasis、17バイト(非競合)

n4÷axxn4÷xxe+3120

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

Oasisは、シーケンスに特化したAdnanによって設計された言語です。

現在、この言語は再帰と閉じた形式を実行できます。

次の式を使用します。 a(4n+k) = 4a(n) + a(k), 0 <= k <= 3

基本ケースを指定するのは簡単です:3120末尾にあるということは単にを意味しa(0)=0, a(1)=2, a(2)=1, a(3)=3ます。

n4÷axxn4÷xxe+3120
                0  a(0) = 0
               2   a(1) = 2
              1    a(2) = 1
             3     a(3) = 3

n                  push n (input)
 4÷                integer-divide by 4
   a               a(n/4)
    xx             double twice; multiply by 4
                   now we have 4a(n/4)
      n            push n (input)
       4÷xx        integer-divide by 4 and then multiply by 4
                   since there is no modulo currently, n%4
                   is built as n-(n/4*4)
           e       we should have done a(n-(n/4*4)), but this
                   is a shortcut for a(n-x) where x is the top
                   of stack. Therefore, we now have a(n-n/4*4)
                   which is a(n%4).
            +      add.

4

MATL、10バイト

BP2eP1ePXB

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

シーケンスの最初の項を生成するように修正されたバージョンOEIS A057300)。

説明

B     % Take input implicitly. Convert to binary array
P     % Flip
2e    % Convert to two-row 2D array, padding with a trailing zero if needed. 
      % Because of the previous flip, this really corresponds to a leading zero
P     % Flip each column. This corresponds to swapping the bits
1e    % Reshape into a row
P     % Flip, to undo the initial flipping
XB    % Convert from binary array to number. Display implicitly

3

zsh、28バイト

<<<$[`tr 12 21<<<$[[#4]$1]`]

入力をコマンドライン引数として受け取り、STDOUTに出力します。

zsh固有のベース変換構文を使用するため、Bash互換ではありません。

                       $1     input (first command line argument)
                 $[      ]    arithmetic expansion
                   [#4]       output in base 4
              <<<             pass the result of this to...
      tr                      the `tr' command
         12 21                and replace 1s with 2s, 2s with 1s
     `                    `   evaluate the result...
   $[                      ]  in another arithmetic expansion, to convert back
                                to base 10
<<<                           output the result on STDOUT

3

網膜、70バイト

。+
$ *
+ `(1 +)\ 1
$ 1x
x1
1
^
バツ
r`(。)(。)
$ 2 $ 1
1
バツ@
+ `@ x
バツ@@
バツ*(@*)
$ .1
0 $

テストスイート。(少し変更されています。)

まあ、楽しみのために:7バイト

T`12`21

入力としてbase-4を取り、base-4として出力します。

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


4
私は対立しています。私はあなたの答えの下半分に賛成票を投じたいが、上半分には反対票を投じたい。
デニス

1
@Dennis今、これらのビットを交換しました。
リーキー修道女

3

05AB1E、8バイト

4B12‡4ö

-5バイトの@Adnanに感謝します!

CP-1252エンコードを使用します。

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

説明:

4B       - Take input and convert to base 4.
  12Â    - Push 12 bifurcated.
     ‡   - Transliterate [1, 2] to [2, 1].
      4ö - Convert to base 10.

2
ニース、しかし、あなたは置き換えることができる1 2‚2 1‚12Â8バイトのために。
アドナン

いい答えだ!ここでは8バイトの代替:4в2‰íJJC
ケビンCruijssen

3

C、32 30 29バイト

f(x){return(x&~0U/3)*3+x>>1;}                // 30 bit version, see below

// less golfed:
f(x){return ((x & 0x55555555)*3 + x) >>1;}   //  >> is lower precedence than +

xnorのPython answerに対するxsotのコメントからコピーされたアルゴリズム。両方の方法をマスクする代わりに、一方の方法をマスクして結合します。

これは、私がテストした最後のバージョンと同じasmにコンパイルされ、動作します(0x3FFFFFFFビット30が設定されていない限り、x からxまで、およびxについては以下を参照)。マシンコードでは、既存のasmの回答と同じ長さです。


上記のバージョンは常に結果の上位ビットをクリアします。最も安全なバージョンは32バイトです。

g(x){return 2*x-3*(x/2U&~0U/3);}   // safe 32bit version, works for all x

Pythonバージョンには、この問題はありません。Pythonは、必要に応じて、固定の上限に切り捨てるのではなく、任意精度の整数型を使用するためです。


@デニス:アー、はい、ありがとう。テスト後にその最後の変更行い、asm出力の違いを見逃しました。それが間違っているように思えたのも不思議ではありません。そんなに>>低い優先順位であることを忘れていました。危険な場合に括弧を示唆するコンパイラの警告が実際のコードで私を救うので、私は規則が何であるかを正確に覚えているほど頻繁にゴルフをしません。:P
ピーターコーデス

2
式内の用語を並べ替えることで、そのスペースを削除できます。
xsot

2

Javascript(ES6)、113 109バイト

Upgoatのおかげで4バイト節約

n=>+('0b'+/(..)+$/.exec('0'+n.toString`2`)[0].split``.reduce((p,c)=>p.length-1?[p.join(c)]:[p[0],c],[''])[0],2)

使い方

n=>+('0b'+                              //parse as binary literal
    /(..)+$/.exec('0'+n.toString`2`)[0] //convert to binary string with an even number of digits
        .split``                        //convert to array
        .reduce((p,c)=>p.length-1?[p.join(c)]:[p[0],c],[''])
                                        //swap all numbers
)

+('0b"+binary_string_here)`parseInt(...、2)の代わりに使用
-Downgoat

1

J、20バイト

4#.0 2 1 3{~4#.^:_1]

使用法

>> f =: 4#.0 2 1 3{~4#.^:_1]
>> f 85
<< 170

>>STDINと<<STDOUT はどこにあります。

非ゴルフ

to_base   =: 4 #.^:_1 ]
transpose =: 0 2 1 3 {~ to_base
from_base =: 4 #. transpose

3つのフォーク。

サイドノート

公式の通訳で^:_1は、に置き換えることができinv、1バイトを節約します。

ただし、これを実装するオンライン通訳者はいません。



1

INTERCAL、60バイト

DOWRITEIN.1PLEASE.1<-!1~#21845'$.1~#43690DOREADOUT.1DOGIVEUP

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

16ビット整数で動作し、I / OはINTERCALの最も自然な形式で行われます。入力は、いくつかの自然言語または構築言語の1つで記述された一連の10進数であり、出力は「ブッチャーローマ数字」です。

これは、INTERCALの2項演算子を実際に直感的に使用できるまれな課題の1つです。ビットの再配置がすべてであるためです。Select(~)は、2番目の引数の1に対応する最初の引数からビットを取得し、ゼロで右にパディングし、mingle($)は、最初の引数からのビットがより重要になるように、引数からビットをインターリーブします。したがって、簡単な解決策は、重要度の低い交互ビット(.1~#21845)を選択し、重要度の高い交互ビット(.1~#43690)、それらを逆の順序でインターリーブします。幸い、バイト数については、INTERCALの演算子には定義済みの優先順位はありませんが(言語の目的は先例がないため)、TIOのC-INTERCALはこの特定の式に対して多くのグループ化を必要とせず、1バイトしかかかりません'.短縮できます!

32ビット整数のサポート:

INTERCAL、67バイト

DOWRITEIN:1PLEASE:1<-':1~#0$#65535'$:1~#65535$#0DOREADOUT:1DOGIVEUP

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

INTERCALは32ビットリテラルを許可しないため、実際にはこれが少し簡単になります読みします。これは、交互ビットを選択するためのマジック定数は、2つの16ビットリテラルを組み合わせて構築する必要があるためです。すべてのもの。(実際には、32ビットリテラルがあったとしても、これはさらに短くなります#0$#65535。2バイトオフ#1431655765で、もう1つは同じです。)これは、INTERCALのプロセス全体を不自然にうまく伝えます。

の不器用な使用による代替アプローチ オペランドのオーバーロード

INTERCAL、71バイト

DO:1<-:1/.2$.3PLEASEWRITEIN:2DO:1<-:2PLEASE:2<-.3$.2DOREADOUT:2DOGIVEUP

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

これは、:1.2混ざり合っていることを宣言して、入力を.3設定:1し、を.3混ざり合って出力することで、完全に選択することを排除します.2。以来:1としてオーバーロードされた.2$.3DO :1 <- :2に割り当てる値.2.3、その結果:1の値を取得し:2、中結果.2からより上位の交番ビットを含む:2.3下位交番ビットを含有します。これは、PLEASE WRITE IN :1こと場合、2つの32ビットソリューションのうち4バイト短いものになりますPLEASE WRITE IN :2 DO :1 <- :2、オーバーロード:1にが、CALCULATINGオーバーロードを使用するために必要であることが判明しました。また、でプログラムを起動するよりも、オーバーロードを実行する方法が少し短いかもしれないと感じていますDO:1<-:1/.2$.3が、これはINTERCALなので、できないこともあります。


0

Mathematica、44バイト

Fold[3#+##&,#~IntegerDigits~4/.{1->2,2->1}]&

私のCJamの答えと同じアプローチ:base-4に変換し、1と2を交換し、元に戻します。また、alephalphaのトリックを使用FromDigitsして、Fold1バイトを節約する操作に置き換えます。



0

J、22バイト

([:,_2|.\,&0)&.(|.@#:)

ベース4のトリックではなく、配列操作に基づく代替アプローチ。

使用法

   f =: ([:,_2|.\,&0)&.(|.@#:)
   (,.f"0) 0 1 9 85 220 1827 47525
    0     0
    1     2
    9     6
   85   170
  220   236
 1827  2835
47525 30298

説明

([:,_2|.\,&0)&.(|.@#:)  Input: n
                   #:   Get the value as a list of base 2 digits
                |.@     Reverse it
(           )&.         Apply to the list of base 2 digits
         ,&0            Append a zero to the end of the list
    _2  \               Split the list into nonoverlapping sublists of size 2
      |.                Reverse each sublist
 [:,                    Flatten the list of sublists into a list
             &.(    )   Apply the inverse of (reversed base 2 digits)
                        to convert back to a number and return it

0

REXX、88バイト

n=x2b(d2x(arg(1)))
o=0
do while n>''
  parse var n a+1 b+1 n
  o=o||b||a
  end
say x2d(b2x(o))
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.