Hoán đổi bit-đảo ngược


28

Mục tiêu của bạn là tạo ra một hàm hoặc một chương trình để đảo ngược các bit trong một phạm vi số nguyên cho một số nguyên n . Nói cách khác, bạn muốn tìm hoán vị bit đảo ngược của một phạm vi gồm 2 n mục, không có chỉ mục. Đây cũng là chuỗi OEIS A030109 . Quá trình này thường được sử dụng trong tính toán Biến đổi Fourier nhanh, chẳng hạn như thuật toán Cooley-Tukey tại chỗ cho FFT. Ngoài ra còn có một thách thức cho việc tính toán FFT cho các chuỗi trong đó độ dài là 2.

Quá trình này yêu cầu bạn lặp lại trong phạm vi [0, 2 n -1] và để chuyển đổi từng giá trị thành nhị phân và đảo ngược các bit trong giá trị đó. Bạn sẽ coi mỗi giá trị là một số n chữ số trong cơ sở 2, điều đó có nghĩa là sự đảo ngược sẽ chỉ xảy ra trong số n bit cuối cùng .

Ví dụ: nếu n = 3, phạm vi số nguyên là [0, 1, 2, 3, 4, 5, 6, 7]. đó là

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

trong đó mỗi chỉ số i được chuyển đổi thành chỉ mục j bằng cách sử dụng đảo ngược bit. Điều này có nghĩa là đầu ra là [0, 4, 2, 6, 1, 5, 3, 7].

Đầu ra cho n từ 0 đến 4 là

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

Bạn có thể đã nhận thấy một mô hình hình thành. Cho n , bạn có thể lấy chuỗi trước cho n -1 và nhân đôi nó. Sau đó nối danh sách nhân đôi đó vào cùng một danh sách kép nhưng tăng thêm một. Để hiển thị,

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

trong đó đại diện cho sự kết hợp.

Bạn có thể sử dụng một trong hai phương pháp trên để hình thành giải pháp của mình. Nếu bạn biết một cách tốt hơn, bạn cũng có thể sử dụng nó. Bất kỳ phương pháp nào cũng được miễn là nó cho kết quả chính xác.

Quy tắc

  • Đây là nên giải pháp ngắn nhất sẽ thắng.
  • Các công cụ xây dựng giải quyết thách thức này nói chung và các công cụ tính toán đảo ngược bit của một giá trị không được phép. Điều này không bao gồm các nội dung thực hiện chuyển đổi nhị phân hoặc các hoạt động bitwise khác.
  • Giải pháp của bạn ít nhất phải có giá trị cho n từ 0 đến 31.

3
"Các công cụ giải quyết toàn bộ thách thức này và các công cụ tính toán tính toán đảo ngược bit của một giá trị không được phép." Awww, IntegerReverse[Range[2^#]-1,2,#]&. (Tôi không biết tại sao Mathicala cần tích hợp sẵn nhưng tôi đoán nó không lạ hơn Sunset...)
Martin Ender

@MartinEnder Đẹp tìm. Một ngày nào đó, có thể sẽ có một bản dựng cho tất cả mọi thứ trong Mathematica, bao gồm cả việc tạo ra các thử thách golf-code ngẫu nhiên.
dặm

Chúng tôi có thể in 0thay vì [0]hoặc nó phải là một danh sách?
Dennis

@Dennis Điểm tốt. Tôi sẽ cho phép nó, vì điều quan trọng là đầu ra đại diện cho một hoán vị hợp lệ bất kể định dạng.
dặm

Sẽ trả về false thay vì 0 được chấp nhận?
Dennis

Câu trả lời:


2

Thạch , 7 6 byte

Ḥ;‘$$¡

Cảm ơn @EriktheOutgolfer vì đã chơi golf 1 byte!

Hãy thử trực tuyến!

Làm thế nào nó hoạt động

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

Mã số:

¾)IF·D>«

Giải trình:

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

Sử dụng mã hóa CP-1252 . Hãy thử trực tuyến! .


Đẹp quá
Đánh bại

@Emigna Cảm ơn! Phiên bản của bạn là gì?
Ad Nam

0)ïsF·D>«đã gần Có một số vấn đề với '0'.
Emigna

1
Sử dụng tốt đẹp của ¾. Gonna phải nhớ thủ thuật đó.
Emigna

1
@KevinCruijssen Đối với đầu vào 0 , có vẻ đẹp hơn khi có biểu diễn int là 0 và không phải là biểu diễn chuỗi :). Khác hơn thế, không có sự khác biệt.
Ad Nam

4

MATL, 13 12 10 9 8 byte

0i:"EtQh

Dùng thử trực tuyến

Giải trình

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

Để hoàn thiện, đây là câu trả lời cũ của tôi bằng cách sử dụng phương pháp không đệ quy (9 byte).

W:qB2&PXB

Dùng thử trực tuyến

Giải trình

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 byte

2&(*,1+*)0:

Có một sự thay thế cho 15 byte sử dụng chuyển đổi và đảo ngược nhị phân thẳng.

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

Sử dụng

   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

Giải trình

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

Octave, 37 byte

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

Tạo một hàm ẩn danh có tên ansđơn giản có thể được gọi với ans(n).

Demo trực tuyến


3

Python 2, 56 55 54 byte

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

Kiểm tra nó trên Ideone .

Cảm ơn @xnor vì đã chơi golf 1 byte!


Bạn có thể làm [0][n:]or.
xnor

3

Java, 422 419 byte:

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

Chà, cuối cùng tôi đã học Java cho ngôn ngữ lập trình thứ hai của mình, vì vậy tôi muốn sử dụng các kỹ năng mới của mình để hoàn thành một thử thách đơn giản, và mặc dù nó đã diễn ra rất lâu, tôi không thất vọng. Tôi chỉ vui mừng vì tôi đã có thể hoàn thành một thử thách đơn giản trong Java.

Dùng thử trực tuyến! (Ý)


Bạn có thể lưu một vài byte phân tích cú pháp int từ args thay vì đọc từ StdIn
Pavel

3

Toán học, 56 33 byte

Số lượng byte giả định nguồn được mã hóa ISO 8859-1.

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

Điều này sử dụng định nghĩa đệ quy để định nghĩa một toán tử đơn nguyên ±.


3

Perl, 46 45 byte

Bao gồm +1 cho -p

Cung cấp số đầu vào trên STDIN

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


2

Javascript ES6, 65 53 51 byte

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

Sử dụng thuật toán đệ quy tăng gấp đôi đệ quy.

Ví dụ chạy:

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]

Thế còn f=n=>n>0?(r=f(n-1).map(i=>i*2)).concat(r.map(i=>i+1)):[0]?
dặm

@miles Rất tiếc, không nhận ra tôi không cần một trường hợp cơ bản cho n==1, cảm ơn.
Dendrobium

2
Tôi nghĩ rằng tôi đã xoay sở để loại bỏ 2 byte bằng cách di chuyển phép nhân lên hai:f=(n,m=1)=>n?[...n=f(n-1,m+m),...n.map(i=>i+m)]:[0]
Neil

2

Python 3, 67 59 byte

Cảm ơn @Dennis cho -8 byte

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

Chúng tôi cũng có thể có một triển khai (sửa đổi) đơn giản trong Python, ngay cả khi điều này khá dài.

Một hàm ẩn danh nhận đầu vào theo đối số và trả về hoán vị đảo ngược bit dưới dạng danh sách.

Làm thế nào nó hoạt động

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

Hãy thử nó trên Ideone


2
Mối quan hệ này với cách tiếp cận của tôi, nhưng tính golf không tồn tại trên cổng của Python 3.
Dennis

2

APL Dyalog , 12 byte

Yêu cầu ⎕IO←0mặc định trên nhiều hệ thống.

2⊥⊖2⊥⍣¯12*⎕

2⊥ từ cơ sở-2 của

lật

2⊥⍣¯1 nghịch đảo từ-cơ sở-2 của

số nguyên n đầu tiên , trong đó n

2* 2 đến sức mạnh của

đầu vào số

Dùng thử trực tuyến!


Để so sánh, đây là phương pháp khác:

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

( tàu chức năng ...

2∘× hai lần (đối số)

, nối với

1+ một cộng

2∘× hai lần (đối số)

)⍣ áp dụng nhiều lần theo quy định của

đầu vào số

trên

0 số không


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

@ngn Điều đó không liên quan gì đến thuật toán của tôi.
Adám

Tôi nghĩ nó giống với "phương pháp khác" của bạn nhưng ok, tôi sẽ viết một câu trả lời riêng
ngn

2

K (ngn / k) , 11 8 byte

2/|!2|&:

Hãy thử trực tuyến!

 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

&là động từ cuối cùng trong thành phần vì vậy chúng ta cần phải :buộc nó phải đơn điệu



1

Bình thường, 8 byte

iR2_M^U2

Dùng thử trực tuyến: Trình diễn hoặc Test Suite

Giải trình:

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 byte

Chỉ cần làm theo thông số ...

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

1

Ruby, 57 byte:

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

1

PHP, 57 byte

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

lấy đầu vào từ tham số dòng lệnh, in các giá trị được phân cách dưới. Chạy với -nr.

giải pháp đệ quy, 72 byte

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

Hàm lấy số nguyên, trả về mảng



1

Perl 6 , 42 byte

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

Hãy thử trực tuyến!

Tăng một số nguyên chỉ đơn giản là lật một chuỗi các bit có ý nghĩa nhỏ nhất, ví dụ từ xxxx0111đến xxxx1000. Vì vậy, chỉ số đảo ngược bit tiếp theo có thể được lấy từ chỉ số trước bằng cách lật một chuỗi các bit có ý nghĩa nhất. Mặt nạ XOR có thể được tính toán m - (m >> (ctz(i) + 1))cho m = 2**nhoặc m = 2**n-1.

Perl 6 , 30 byte

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

Hãy thử trực tuyến!

Phương pháp đệ quy.


1

JavaScript (Firefox 30-57), 48 byte

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

Giải pháp Python 2 của @ Dennis ♦.


Tham
khảoError

1

Japt , 14 13 byte

2pU Ǥw ú0U Í

Hãy thử trực tuyến!

Giải nén & Cách thức hoạt động

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

Thực hiện đơn giản.


Thực sự có một lối tắt không có giấy tờ cho n2:Í
Oliver

1

APL (Dyalog Classic) , 9 byte

(⍋,⍨)⍣⎕⊢0

Hãy thử trực tuyến!

đánh giá đầu vào

( )⍣⎕⊢0áp dụng điều đó trong ( )nhiều lần, bắt đầu với0

,⍨ nối kết quả hiện tại với chính nó

chỉ số của một hoán vị tăng dần


0

x86, 31 byte

Đưa một số lượng đủ lớn int[] buffervào eaxn trong ecx, và trả về bộ đệm vào eax.

Triển khai thuật toán nối được đưa ra trong tuyên bố thách thức. Có thể lưu byte bằng cách tăng con trỏ lên 4 thay vì sử dụng truy cập mảng trực tiếp, nhưng lea/ movđã khá ngắn (3 byte cho 3 regs và số nhân).

.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......|
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.