位反转排列


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 的先前序列取为两倍。然后将那个双精度列表连接到相同的双精度列表,但是增加一个。显示,

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

其中表示串联。

您可以使用上述两种方法中的任何一种来形成您的解决方案。如果您知道更好的方法,则也可以自由使用。只要能输出正确的结果,任何方法都可以。

规则

  • 这是因此最短的解决方案是成功的。
  • 不允许从整体上解决此难题的内建函数和用于计算值的位反转的内建函数。这不包括执行二进制转换或其他按位运算的内置函数。
  • 您的解决方案必须至少对0到31之间的n有效。

3
“不允许整体解决这一难题的构建程序以及计算值的位反转的内置函数。” Awww ,IntegerReverse[Range[2^#]-1,2,#]&。(我不知道为什么 Mathematica需要内置的功能,但我想这并不奇怪Sunset……)
Martin Ender

@MartinEnder很好找到。总有一天,Mathematica中可能会内置所有功能,包括生成随机的代码高尔夫挑战。
英里

我们可以打印0而不是[0]列表吗?
丹尼斯

@丹尼斯好点。我会允许的,因为不管格式如何,输出都代表有效的排列是非常重要的。
英里

返回false而不是0是否可以接受?
丹尼斯

Answers:


2

果冻7 6 字节

Ḥ;‘$$¡

感谢@EriktheOutgolfer打高尔夫球1个字节!

在线尝试!

怎么运行的

Ḥ;‘$$¡  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 '16

@Emigna谢谢!那你是什么版本?
阿德南(Adnan)

0)ïsF·D>«虽然很近。“ 0”存在一些问题。
Emigna '16

1
很好的用法¾。必须记住那个把戏。
Emigna '16

1
@KevinCruijssen对于输入0,它看起来更漂亮,其int表示形式为0而不是字符串表示形式:)。除此之外,没有任何区别。
阿德南'18

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

八度,37字节

@(n)bin2dec(fliplr(dec2bin(0:2^n-1)))

创建一个名为的匿名函数ans,该函数可以简单地通过调用ans(n)

在线演示


3

Python 2,56 55 54字节

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

Ideone上进行测试

感谢@xnor打高尔夫球1个字节!


你可以的[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())));}}

好吧,我终于学习了第二种编程语言的Java,所以我想用我的新技能来完成一个简单的挑战,尽管结果长,但我并不失望。我很高兴能够用Java完成一个简单的挑战。

在线尝试!(爱迪生)


您可以保存一些字节来从args解析一个int,而不是从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]

使用递归double-increment-concat算法。

示例运行:

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,谢谢。
Dendrobium

2
我想我通过将乘数移动两个来设法减少了2个字节:f=(n,m=1)=>n?[...n=f(n-1,m+m),...n.map(i=>i+m)]:[0]
尼尔(Neil)

2

Python 3,67 59字节

感谢@Dennis提供-8个字节

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的移植。–
Dennis

2

Dyalog APL,12 个字节

要求⎕IO←0在许多系统上是默认设置。

2⊥⊖2⊥⍣¯12*⎕

2⊥ 从2开始

翻转

2⊥⍣¯1 的from-base-2的倒数

n个整数,其中n

2* 2的力量

数字输入

在线尝试APL!


为了进行比较,这是另一种方法:

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

( 功能训练...

2∘× 两次(争论)

, 串联到

1+ 一加

2∘× 两次(争论)

)⍣ 按规定多次使用

数字输入

0


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

@ngn与我的算法无关。
亚当

我以为它与您的“其他方法”类似,但是好吧,我将写一个单独的答案
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

&是构词中的最后一个动词,因此我们需要a :使其强制为单音



1

Pyth,8个字节

iR2_M^U2

在线尝试:演示测试套件

说明:

iR2_M^U2Q   implicit Q (=input number) at the end
     ^U2Q   generate all lists of zeros and ones of length Q in order
   _M       reverse each list
iR2         convert each list to a number

1

Clojure,78个字节

只是遵循规范...

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

1

Ruby,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

在线尝试!

递增整数仅会翻转最低有效位的序列,例如从xxxx0111xxxx1000。因此,可以通过翻转最高有效位序列来从上一个索引中获取下一个反转索引。可以使用m - (m >> (ctz(i) + 1))for m = 2**n或来计算XOR掩码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Í
Oliver


0

x86,31字节

取足够大的int[] bufferin eaxn in ecx,并返回中的缓冲区eax

实现质询语句中给出的连接算法。可以通过将指针增加4而不是直接使用数组访问来保存字节,但是lea/ mov已经很短了(3个寄存器和一个乘数为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

十六进制转储:

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......|
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.