The Wayback Machine - https://web.archive.org/web/20160621211642/http://codegolf.stackexchange.com:80/questions/83373/bit-reversal-permutations
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Your goal is to create a function or a program to reverse the bits in a range of integers given an integer n. In other words, you want to find the bit-reversal permutation of a range of 2n items, zero-indexed. This is also the OEIS sequence A030109. This process is often used in computing Fast Fourier Transforms, such as the in-place Cooley-Tukey algorithm for FFT. There is also a challenge for computing the FFT for sequences where the length is a power of 2.

This process requires you to iterate over the range [0, 2n-1] and to convert each value to binary and reverse the bits in that value. You will be treating each value as a n-digit number in base 2 which means reversal will only occur among the last n bits.

For example, if n = 3, the range of integers is [0, 1, 2, 3, 4, 5, 6, 7]. These are

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 

where each index i is converted to an index j using bit-reversal. This means that the output is [0, 4, 2, 6, 1, 5, 3, 7].

The output for n from 0 thru 4 are

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

You may have noticed a pattern forming. Given n, you can take the previous sequence for n-1 and double it. Then concatenate that doubled list to the same double list but incremented by one. To show,

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

where represents concatenation.

You can use either of the two methods above in order to form your solution. If you know a better way, you are free to use that too. Any method is fine as long as it outputs the correct results.

Rules

  • This is so the shortest solution wins.
  • Builtins that solve this challenge as a whole and builtins that compute the bit-reversal of a value are not allowed. This does not include builtins which perform binary conversion or other bitwise operations.
  • Your solution must be, at the least, valid for n from 0 to 31.
share|improve this question
2  
"Builtins that solve this challenge as a whole and builtins that compute the bit-reversal of a value are not allowed." Awww, IntegerReverse[Range[2^#]-1,2,#]&. (I don't know why Mathematica needs that built-in but I guess it's not a lot weirder than Sunset...) – Martin Enderyesterday
    
@MartinEnder Nice find. Someday, it might be that there will be a builtin for everything in Mathematica, including generating random code-golf challenges. – milesyesterday
    
Can we print 0 instead of [0] or does it have to be a list? – Dennisyesterday
    
@Dennis Good point. I'll allow it, since it's only important that the output represents a valid permutation regardless of format. – milesyesterday
    
Would returning false instead of 0 be acceptable? – Dennis23 hours ago

14 Answers 14

05AB1E, 8 bytes

Code:

¾)IF·D>« 

Explanation:

¾ # 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. 

Uses the CP-1252 encoding. Try it online!.

share|improve this answer
    
Nice one! Beats the one I had :) – Emignayesterday
    
@Emigna Thanks! What was your version then? – Adnanyesterday
    
0)ïsF·D>« was close though. Had some issues with the '0'. – Emignayesterday
    
@Emigna Oh, I actually have that same issue now. Lemme fix that :p – Adnanyesterday
1  
Nice usage of ¾. Gonna have to remember that trick. – Emignayesterday

J, 15 bytes

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

Uses straight-forward binary conversion and reversal.

For 20 bytes,

([:(,>:)+:@$:@<:)^:* 

Uses the recursive, double and increment method.

Usage

 f =: 2|."1&.#:@i.@^] g =: ([:(,>:)+:@$:@<:)^:* (f,:g) 0 0 0 (f,:g) 2 0 2 1 3 0 2 1 3 (f,:g) 3 0 4 2 6 1 5 3 7 0 4 2 6 1 5 3 7 (f,:g) 4 0 8 4 12 2 10 6 14 1 9 5 13 3 11 7 15 0 8 4 12 2 10 6 14 1 9 5 13 3 11 7 15 

Explanation

2|."1&.#:@i.@^] Input: n ] Get n 2 ^ Find 2^n i.@ Get the range [0, 1, ..., 2^n-1] |."1&.#:@ Convert each value to binary using #: Then reverse each value using |."1 Then convert back to decimal from binary using the inverse of #: which is obtained from &. Return those values ([:(,>:)+:@$:@<:)^:* Input: n * Get the sign of n, either 0 if 0 or else 1 ( )^: Execute either 0 or 1 times When given 0, it executes 0 times on input 0 meaning that it returns a list [0] <: Decrement n to get n-1 $:@ Call recursively on n-1 +:@ Double each value in the recursive result [:( ) Modify the double result >: Increment each value in it , Join the doubled with the incremented result and return 
share|improve this answer

Octave, 37 bytes

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

Creates an anonymous function named ans that can simply be called with ans(n).

Online Demo

share|improve this answer

MATL, 1312109 8 bytes

0i:"EtQh 

Try it Online

Explanation

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 

For the sake of completeness, here was my old answer using the non-recursive approach (9 bytes).

W:qB2&PXB 

Try it Online

Explanation

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 
share|improve this answer

Pyth - 11 bytes

ushMByMGQ]0 

Test Suite.

share|improve this answer

Javascript ES6, 6553 51 bytes

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

Uses the recursive double-increment-concat algorithm.

Example runs:

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] 
share|improve this answer
    
How about f=n=>n>0?(r=f(n-1).map(i=>i*2)).concat(r.map(i=>i+1)):[0]? – milesyesterday
    
@miles Whoops, didn't realize I don't need a base case for n==1, thanks. – Dendrobiumyesterday
1  
I think I managed to shave off 2 bytes by moving the multiplication by two: f=(n,m=1)=>n?[...n=f(n-1,m+m),...n.map(i=>i+m)]:[0] – Neil21 hours ago

Python 2, 5655 54 bytes

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

Test it on Ideone.

Thanks to @xnor for golfing off 1 byte!

share|improve this answer
    
You can do [0][n:]or. – xnor19 hours ago
    
That's clever. Thanks! – Dennis19 hours ago

Java, 422 419 bytes:

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

Well, I finally learned Java for my second programming language, so I wanted to use my new skills to complete a simple challenge, and although it turned out very long, I am not disappointed. I am just glad I was able to complete a simple challenge in Java.

Try It Online! (Ideone)

share|improve this answer

Mathematica, 56 33 bytes

Byte count assumes an ISO 8859-1 encoded source.

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

This uses the recursive definition to define a unary operator ±.

share|improve this answer

Jelly, 7 bytes

Ḥµ;‘ Ç¡ 

Try it online!

How it works

Ḥµ;‘ Helper link. Argument: A (array) Ḥ Double; yield 2A. µ Begin a new, monadic chain. Argument: 2A ‘ Increment; yield 2A + 1. ; Concatenate the results to both sides. Ç¡ Main link. No arguments. Implicit argument / initial return value: 0 ¡ Read an integer n from STDIN and do the following n times. Ç Call the helper link with the previous return value as argument. 
share|improve this answer

Julia, 23 22 bytes

!n=n>0&&[t=2*!~-n;t+1] 

Rather straightforward implementation of the process described in the challenge spec.

Try it online!

share|improve this answer

Python 3, 67 59 bytes

Thanks to @Dennis for -8 bytes

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

We may as well have a (modified) straightforward implementation in Python, even if this is quite long.

An anonymous function that takes input by argument and returns the bit-reversed permutation as a list.

How it works

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 

Try it on Ideone

share|improve this answer
    
This ties with my approach, but it golfiness won't survive a port to Python 3. – Dennis21 hours ago

JavaScript (Firefox 30+), 46 bytes

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

Port of @Dennis♦'s Python 2 solution.

share|improve this answer

Pyth, 8 bytes

iR2_M^U2 

Try it online: Demonstration or Test Suite

Explanation:

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 
share|improve this answer

Not the answer you're looking for? Browse other questions tagged or ask your own question.

close