ビット反転順列


28

目標は、整数nが与えられた整数の範囲のビットを反転する関数またはプログラムを作成することです。言い換えると、インデックスがゼロの2 n個のアイテムの範囲のビット反転順列を検索する必要があります。これは、OEISシーケンスA030109でもあります。このプロセスは、FFTのインプレースCooley-Tukeyアルゴリズムなど、高速フーリエ変換の計算でよく使用されます。また、長さが2の累乗であるシーケンスのFFTの計算にも課題があります。

このプロセスでは、範囲[0、2 n -1] を反復処理し、各値をバイナリに変換し、その値のビットを反転する必要があります。各値を基数2のn桁の数値として処理します。つまり、反転は最後のnビットの間でのみ発生します。

たとえば、n = 3の場合、整数の範囲はです[0, 1, 2, 3, 4, 5, 6, 7]。これらは

i  Regular  Bit-Reversed  j
0    000        000       0
1    001        100       4
2    010        010       2
3    011        110       6
4    100        001       1
5    101        101       5
6    110        011       3
7    111        111       7

ここで、各インデックスiはビット反転を使用してインデックスjに変換されます。これは、出力がであることを意味します[0, 4, 2, 6, 1, 5, 3, 7]

0から4までのnの出力は次のとおりです。

n    Bit-Reversed Permutation
0    [0]
1    [0, 1]
2    [0, 2, 1, 3]
3    [0, 4, 2, 6, 1, 5, 3, 7]

パターンの形成に気づいたかもしれません。与えられたnは、あなたがのために前のシーケンスを取ることができ、N -1とそれを倍増します。次に、その二重リストを同じ二重リストに連結しますが、1ずつ増加します。示すために、

[0, 2, 1, 3] * 2 = [0, 4, 2, 6]
[0, 4, 2, 6] + 1 = [1, 5, 3, 7]
[0, 4, 2, 6] ⊕ [1, 5, 3, 7] = [0, 4, 2, 6, 1, 5, 3, 7]

ここで連結を表します。

ソリューションを形成するには、上記の2つの方法のいずれかを使用できます。より良い方法を知っていれば、それも自由に使用できます。正しい結果を出力する限り、どの方法でも問題ありません。

ルール

  • これはので、最短のソリューションが勝ちます。
  • この課題を全体として解決する組み込み関数と、値のビット反転を計算する組み込み関数は許可されていません。これには、バイナリ変換またはその他のビット演算を実行する組み込み関数は含まれません。
  • ソリューションは、少なくとも0〜31のnに対して有効でなければなりません。

3
「この課題を全体として解決するビルチンと、値のビット反転を計算するビルトインは許可されていません。」Awww 、IntegerReverse[Range[2^#]-1,2,#]&。(なぜ Mathematicaにその組み込みが必要なのかわかりませんがそれはそれほど奇妙ではないと思いSunsetます...)
Martin Ender

@MartinEnder素敵な発見。いつか、ランダムなコードとゴルフのチャレンジを生成するなど、Mathematicaのすべての機能が組み込まれることがあります。
マイル

リストの0代わりに印刷できますか、[0]それともリストにする必要がありますか?
デニス

@デニス良い点。出力が形式に関係なく有効な順列を表すことだけが重要であるため、許可します。
マイル

0ではなくfalse返すことは受け入れられますか?
デニス

回答:


2

ゼリー7 6 バイト

Ḥ;‘$$¡

1バイトのゴルフをしてくれた@EriktheOutgolferに感謝します!

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

使い方

Ḥ;‘$$¡  Main link. No arguments.
        Implicit argument / initial return value: 0

     ¡  Read an integer n from STDIN and call the link to the left n times.
    $   Combine the two links to the left into a monadic chain, to be called
        with argument A (initially 0, later an array).
Ḥ         Unhalve; yield 2A.
   $      Combine the two links to the left into a monadic chain, to be called
          with argument 2A.
  ‘         Increment; yield 2A + 1
 ;          Concatenate 2A and 2A + 1.

4

05AB1E、8バイト

コード:

¾)IF·D>«

説明:

¾         # Constant for 0.
 )        # Wrap it up into an array.
  IF      # Do the following input times.
    ·     # Double every element.
     D    # Duplicate it.
      >   # Increment by 1.
       «  # Concatenate the first array.

CP-1252エンコードを使用します。オンラインでお試しください!


良いですね!私が持っていたものを
打ちます

@Emignaありがとう!あなたのバージョンは何でしたか?
アドナン

0)ïsF·D>«でも近かった。「0」に問題がありました。
エミグナ

1
のいい使い方¾。そのトリックを覚えておく必要があります。
エミグナ

1
@KevinCruijssen入力0の場合、文字列表現ではなく0のint表現を持つ方がきれいに見えます:)。それ以外は、違いはありません。
アドナン

4

MATL、13 12 10 9 8バイト

0i:"EtQh

オンラインで試す

説明

0       % Push number literal 0 to the stack
i:"     % Loop n times
    E   % Multiply by two
    t   % Duplicate
    Q   % Add one
    h   % Horizontally concatenate the result
        % Implicit end of loop, and implicitly display the result

完全を期すために、ここに非再帰的アプローチ(9バイト)を使用した古い回答があります。

W:qB2&PXB

オンラインで試す

説明

W       % Compute 2 to the power% ofImplicitly thegrab input (n) and compute 2^n
:       % Create an array from [1...2^n]
q       % Subtract 1 to get [0...(2^n - 1)]
B       % Convert to binary where each row is the binary representation of a number
2&P     % Flip this 2D array of binary numbers along the second dimension
XB      % Convert binary back to decimal
        % Implicitly display the result

4

J、15 11バイト

2&(*,1+*)0:

単純なバイナリ変換と反転を使用する15バイトの代替があります

2|."1&.#:@i.@^]

使用法

   f =: 2&(*,1+*)0:
   f 0
0
   f 1
0 1
   f 2
0 2 1 3
   f 3
0 4 2 6 1 5 3 7
   f 4
0 8 4 12 2 10 6 14 1 9 5 13 3 11 7 15

説明

2&(*,1+*)0:  Input: n
         0:  The constant 0
2&(     )    Repeat n times starting with x = [0]
2      *       Multiply each in x by 2
     1+        Add 1 to each
    ,          Append that to
2  *           The list formed by multiplying each in x by 2
               Return that as the next value of x
             Return the final value of x




3

パイソン2、56の 55 54バイト

f=lambda n:[0][n:]or[i+j*2for i in 0,1for j in f(n-1)]

Ideoneでテストします。

1バイトのゴルフを楽しんでくれた@xnorに感謝します!


できます[0][n:]or
-xnor

3

Java、422 419バイト:

import java.util.*;class A{static int[]P(int n){int[]U=new int[(int)Math.pow(2,n)];for(int i=0;i<U.length;i++){String Q=new String(Integer.toBinaryString(i));if(Q.length()<n){Q=new String(new char[n-Q.length()]).replace("\0","0")+Q;}U[i]=Integer.parseInt(new StringBuilder(Q).reverse().toString(),2);}return U;}public static void main(String[]a){System.out.print(Arrays.toString(P(new Scanner(System.in).nextInt())));}}

さて私は、単純なチャレンジを完了するために、私の新しいスキルを使用したかったので、私は最終的に、私の第2のプログラミング言語のJavaを学び、そしてそれが判明したものの、非常に長い、私は失望していないです。Javaで簡単なチャレンジを完了できたことを嬉しく思います。

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


StdIn
Pavel

3

Mathematica、56 33バイト

バイトカウントは、ISO 8859-1でエンコードされたソースを想定しています。

±0={0};±x_:=Join[y=±(x-1)2,y+1]

これは、再帰的な定義を使用して単項演算子を定義します±


3

Perl、46 45バイト

+1を含む -p

STDINに入力番号を与える

#!/usr/bin/perl -p
map$F[@F]=($_*=2)+1,@F for(@F=0)..$_;$_="@F"


2

JavascriptをES6、65の 53 51バイト

f=(n,m=1)=>n?[...n=f(n-1,m+m),...n.map(i=>i+m)]:[0]

再帰的な二重増分連結アルゴリズムを使用します。

実行例:

f(0) => [0]
f(1) => [0, 1]
f(2) => [0, 2, 1, 3]
f(4) => [0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15]

どうf=n=>n>0?(r=f(n-1).map(i=>i*2)).concat(r.map(i=>i+1)):[0]
マイル

@milesおっと、ベースケースが必要ないことに気づかなかったn==1、ありがとう。
デンドロビウム

2
私は、私は2つの乗算を移動することによって、2バイト剃り落とすに管理すると思う:f=(n,m=1)=>n?[...n=f(n-1,m+m),...n.map(i=>i+m)]:[0]
ニール

2

Python 3、67 59バイト

-8バイトの@Dennisに感謝

lambda n:[int(bin(i+2**n)[:1:-1],2)//2for i in range(2**n)]

Pythonでの(修正された)簡単な実装も、これが非常に長い場合でも可能です。

引数によって入力を受け取り、ビット反転順列をリストとして返す匿名関数。

使い方

lambda n                 Anonymous function with input n
...for i in range(2**n)  Range from 0 to 2**n-1
bin(i+2**n)[:1:-1]       Convert i+2**n to binary string, giving 1 more digit than needed,
                         remove '0b' from start, and reverse
int(...,2)               Convert back to decimal
...//2                   The binary representation of the decimal value has one trailing
                         bit that is not required. This is removed by integer division by 2
:[...]                   Return as list

Ideoneでお試しください


2
これは私のアプローチと結びついていますが、ゴルフィネスはPython 3への移植には耐えられません。-
デニス

2

Dyalog APL、12 バイト

⎕IO←0多くのシステムでデフォルトである必要があります。

2⊥⊖2⊥⍣¯12*⎕

2⊥ from-base-2 of

反転

2⊥⍣¯1 from-base-2の逆

最初のn個の整数。n

2* 2の累乗

数値入力

TryAPLオンライン!


比較のために、他の方法を次に示します。

(2∘×,1+2∘×)⍣⎕⊢0

( 関数トレイン...

2∘× 2回(引数)

, に連結

1+ ワンプラス

2∘× 2回(引数)

)⍣ で指定された回数だけ適用されます

数値入力

0 ゼロ


(⍋,⍨)⍣⎕⊢0⎕io←0
ngn

@ngnそれは私のアルゴリズムとは関係ありません。
アダム

私はそれはあなたの「他の方法」と同様だと思ったが、[OK]を、私は別の答え書きます
NGN

2

K(ngn / k)11 8バイト

2/|!2|&:

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

 x:3  / just for testing
 &x   / that many zeroes
0 0 0
 2|&x / max with 2
2 2 2
 !x#2 / binary words of length x, as a transposed matrix
(0 0 0 0 1 1 1 1
 0 0 1 1 0 0 1 1
 0 1 0 1 0 1 0 1)
 |!x#2 / reverse
(0 1 0 1 0 1 0 1
 0 0 1 1 0 0 1 1
 0 0 0 0 1 1 1 1)
 2/|!x#2 / base-2 decode the columns
0 4 2 6 1 5 3 7

&構成の最後の動詞なので、:強制的に単項式にする必要があります




1

Clojure、78バイト

ただ仕様に従って...

(defn f[n](if(= n 0)[0](let[F(map #(* 2 %)(f(dec n)))](concat F(map inc F)))))

1

ルビー、57バイト:

->n{(0...a=2**n).map{|x|("%b"%x+=a).reverse[0,n].to_i 2}}

1

PHP、57バイト

while($i<1<<$argv[1])echo bindec(strrev(decbin($i++))),_;

コマンドラインパラメータから入力を受け取り、アンダースコアで区切られた値を出力します。で実行し-nrます。

再帰的ソリューション、72バイト

function p($n){$r=[$n];if($n)foreach($r=p($n-1)as$q)$r[]=$q+1;return$r;}

関数は整数を取り、配列を返します



1

Perl 6、42バイト

{0,{$^p+^($_-$_/2+>lsb ++$)}...$_}o 1+<*-1

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

整数をインクリメントすると、例えばからのxxxx0111ように、最下位ビットのシーケンスが単純に反転しxxxx1000ます。したがって、最上位ビットのシーケンスを反転させることにより、次のビット反転インデックスを前のインデックスから取得できます。XORマスクはm - (m >> (ctz(i) + 1))for m = 2**nまたはで計算できますm = 2**n-1

Perl 6、30バイト

my&f={$_&&(^2 X+(f($_-1)X*2))}

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

再帰的アプローチ。


1

JavaScript(Firefox 30-57)、48バイト

f=n=>n?[for(x of[0,1])for(y of f(n-1))x+y+y]:[0]

@ Dennis♦のPython 2ソリューションのポート。


ReferenceError:fが定義されていません
l4m2

1

Japt14 13バイト

2pU Ǥw ú0U Í

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

開梱と仕組み

2pU o_s2 w ú0U n2

2pU    2**n
o_     range(2**n).map(...)
s2       convert to binary string
w        reverse
ú0U      right-pad to length n, filling with '0'
n2       convert binary string to number

簡単な実装。


実際には、文書化されていないショートカットがありn2ます:Í
オリバー


0

x86、31バイト

十分な大きさのint[] bufferin eaxn inを取りecx、バッファinを返しますeax

チャレンジステートメントで指定された連結アルゴリズムを実装します。配列アクセスを直接使用する代わりに、ポインターを4ずつ増やすことでバイトを節約できる場合がありますが、lea/ movは既にかなり短くなっています(3つのregと乗算器に対して3バイト)。

.section .text
.globl main
main:
        mov     $buf, %eax          # buf addr
        mov     $3, %ecx            # n 

start:
        xor     %ebx, %ebx
        mov     %ebx, (%eax)        # init buf[0] = 0 
        inc     %ebx                # x = 1

l1:
        mov     %ebx, %edi          
        dec     %edi                # i = x-1
        lea     (%eax,%ebx,4), %edx # buf+x 

l2:
        mov     (%eax,%edi,4), %esi # z = buf[i]
        sal     %esi                # z *= 2
        mov     %esi, (%eax,%edi,4) # buf[i] = z
        inc     %esi                # z += 1
        mov     %esi, (%edx,%edi,4) # buf[x+i] = z

        dec     %edi                # --i 
        jns     l2                  # do while (i >= 0)

        sal     %ebx                # x *= 2
        loop    l1                  # do while (--n)

        ret

.data
buf:    .space 256, -1

Hexdump:

00000507  31 db 89 18 43 89 df 4f  8d 14 98 8b 34 b8 d1 e6  |1...C..O....4...|
00000517  89 34 b8 46 89 34 ba 4f  79 f1 d1 e3 e2 e7 c3     |.4.F.4.Oy......|
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.