การเปลี่ยนสับเปลี่ยนบิตกลับ


28

เป้าหมายของคุณคือการสร้างฟังก์ชั่นหรือโปรแกรมที่จะย้อนกลับบิตในช่วงของจำนวนเต็มให้จำนวนเต็มn กล่าวอีกนัยหนึ่งคุณต้องการค้นหาการเปลี่ยนรูปบิตกลับรายการช่วง 2 nรายการซึ่งไม่มีดัชนี และนี่ก็เป็นลำดับ OEIS A030109 กระบวนการนี้มักใช้ในการคำนวณ Fast Fourier Transforms เช่นอัลกอริทึม Cooley-Tukey ในสถานที่สำหรับ FFT นอกจากนี้ยังมีความท้าทายสำหรับการคำนวณ FFT สำหรับลำดับที่ความยาวคือพลังของ 2

กระบวนการนี้กำหนดให้คุณทำซ้ำในช่วง [0, 2 n -1] และแปลงแต่ละค่าเป็นไบนารีและแปลงบิตในค่านั้น คุณจะได้รับการรักษาแต่ละค่าเป็นnจำนวน -digit ในฐาน 2 ซึ่งหมายถึงการกลับรายการจะเกิดขึ้นในหมู่สุดท้าย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

ที่แต่ละดัชนีฉันถูกแปลงเป็นดัชนีjโดยใช้การกลับรายการบิต [0, 4, 2, 6, 1, 5, 3, 7]ซึ่งหมายความว่าการส่งออกเป็น

เอาต์พุตสำหรับnจาก 0 ถึง 4 คือ

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]

ซึ่งแสดงถึงการต่อกัน

คุณสามารถใช้วิธีใดวิธีหนึ่งจากสองวิธีด้านบนเพื่อสร้างโซลูชันของคุณ หากคุณรู้วิธีที่ดีกว่าคุณมีอิสระที่จะใช้เช่นกัน วิธีการใด ๆ ก็ใช้ได้ตราบใดที่มันออกผลลัพธ์ที่ถูกต้อง

กฎระเบียบ

  • นี่คือเพื่อให้ทางออกที่สั้นที่สุดชนะ
  • บิลด์อินที่แก้ปัญหาความท้าทายนี้โดยรวมและบิลด์อินที่คำนวณการพลิกกลับบิตของค่าไม่ได้รับอนุญาต สิ่งนี้ไม่รวม builtins ซึ่งดำเนินการแปลงแบบไบนารีหรือการดำเนินการระดับบิตอื่น ๆ
  • อย่างน้อยที่สุดโซลูชันของคุณจะต้องใช้ได้สำหรับnจาก 0 ถึง 31

3
"บิลด์อินที่แก้ปัญหาความท้าทายนี้โดยรวมและบิลด์อินที่คำนวณการพลิกกลับบิตของค่าไม่ได้รับอนุญาต" IntegerReverse[Range[2^#]-1,2,#]&awww, (ฉันไม่รู้ว่าทำไม Mathematica จึงต้องการบิวท์อิน แต่ฉันเดาว่ามันไม่แปลกกว่าSunset... )
Martin Ender

@ มาร์ตินเข้าดี สักวันหนึ่งอาจเป็นไปได้ว่าจะมีสิ่งก่อสร้างภายในสำหรับทุกสิ่งใน Mathematica รวมถึงการสร้างความท้าทายของโค้ดกอล์ฟ
ไมล์

เราสามารถพิมพ์0แทนที่จะ[0]ต้องเป็นรายการหรือไม่?
Dennis

@Dennis จุดดี ฉันจะอนุญาตเนื่องจากเป็นสิ่งสำคัญเท่านั้นที่ผลลัพธ์แสดงถึงการเปลี่ยนแปลงที่ถูกต้องโดยไม่คำนึงถึงรูปแบบ
ไมล์

จะกลับมาเป็นเท็จแทน0เป็นที่ยอมรับ?
Dennis

คำตอบ:


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

@ Emigna ขอบคุณ! รุ่นของคุณเป็นอย่างไร
Adnan

0)ïsF·D>«อยู่ใกล้แม้ว่า พบปัญหาบางอย่างกับ '0'
Emigna

1
¾การใช้งานที่ดีของ จะต้องจำเคล็ดลับนั้น
Emigna

1
@KevinCruijssen สำหรับอินพุต0ดูเหมือนว่าน่าจะมีการเป็นตัวแทนของ 0 ไม่ใช่การแทนสตริง :) นอกจากนั้นไม่มีความแตกต่าง
Adnan

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

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 ได้

ลองออนไลน์! (Ideone)


คุณสามารถบันทึกไม่กี่ไบต์แยกวิเคราะห์ int จาก args แทนที่จะอ่านจาก StdIn
Pavel

3

Mathematica, 56 33 ไบต์

จำนวนไบต์ถือว่าแหล่งที่เข้ารหัส ISO 8859-1

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

นี้ใช้คำนิยาม recursive ±เพื่อกำหนดผู้ประกอบการเอก




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ขอบคุณ
Dendrobium

2
ฉันคิดว่าฉันจัดการเพื่อโกน 2 ไบต์โดยการย้ายคูณสอง:f=(n,m=1)=>n?[...n=f(n-1,m+m),...n.map(i=>i+m)]:[0]
นีล

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 ผกผันของจาก - ฐาน -2 ของ

จำนวนเต็มnแรกโดยที่nคือ

2* 2 ถึงพลังของ

ใส่ตัวเลข

ลองใช้ออนไลน์!


สำหรับการเปรียบเทียบนี่คือวิธีอื่น ๆ :

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

( รถไฟฟังก์ชั่น ...

2∘× สองครั้ง (อาร์กิวเมนต์)

, ตัดแบ่งเป็น

1+ หนึ่งบวก

2∘× สองครั้ง (อาร์กิวเมนต์)

)⍣ ใช้หลายครั้งตามที่ระบุโดย

ใส่ตัวเลข

บน

0 ศูนย์


(⍋,⍨)⍣⎕⊢0( ⎕io←0)
ก.ย.

@ngn มันไม่มีส่วนเกี่ยวข้องกับอัลกอริทึมของฉัน
อดัม

ฉันคิดว่ามันคล้ายกับ "วิธีการอื่น" ของคุณ แต่โอเคฉันจะเขียนคำตอบแยกต่างหาก
27.00 น

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

&เป็นคำกริยาสุดท้ายในการจัดองค์ประกอบดังนั้นเราจำเป็นต้องมี:เพื่อบังคับให้เป็น monadic




1

Clojure, 78 ไบต์

เพียงทำตามข้อกำหนด ...

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


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ดังนั้นดัชนีย้อนกลับบิตถัดไปสามารถหาได้จากดัชนีก่อนหน้าโดยการพลิกลำดับของบิตที่สำคัญที่สุด หน้ากากแฮคเกอร์สามารถคำนวณได้ด้วยm - (m >> (ctz(i) + 1))สำหรับหรือm = 2**nm = 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]

โซลูชัน Python 2 ของพอร์ตของ @ Dennis ♦


ReferenceError: f ไม่ได้ถูกกำหนด
l4m2

1

Japt , 14 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

1

APL (Dyalog Classic)ขนาด 9 ไบต์

(⍋,⍨)⍣⎕⊢0

ลองออนไลน์!

การประเมินการป้อนข้อมูล

( )⍣⎕⊢0 ใช้สิ่งนี้ใน ( )หลาย ๆ ครั้งเริ่มต้นด้วย0

,⍨ ต่อผลลัพธ์ปัจจุบันเข้ากับตัวเอง

ดัชนีการเรียงลำดับจากน้อยไปมาก


0

x86, 31 ไบต์

ใช้เวลามากพอint[] bufferในeaxและnในและผลตอบแทนในบัฟเฟอร์ecxeax

ใช้อัลกอริทึมการต่อข้อมูลที่กำหนดในคำสั่งการท้าทาย อาจเป็นไปได้ที่จะบันทึกไบต์โดยการเพิ่มพอยน์เตอร์ด้วย 4 แทนที่จะใช้การเข้าถึงอาร์เรย์โดยตรง แต่lea/ / movก็ค่อนข้างสั้น (3 ไบต์สำหรับ 3 regs และตัวคูณ)

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