Permutazioni di inversione di bit


28

Il tuo obiettivo è creare una funzione o un programma per invertire i bit in un intervallo di numeri interi dato un numero intero n . In altre parole, si desidera trovare la permutazione di inversione di bit di un intervallo di 2 n elementi, con indice zero. Questa è anche la sequenza OEIS A030109 . Questo processo viene spesso utilizzato nel calcolo delle trasformazioni di Fourier veloci, come l'algoritmo Cooley-Tukey sul posto per FFT. Esiste anche una sfida per il calcolo della FFT per sequenze in cui la lunghezza è una potenza di 2.

Questo processo richiede di scorrere nell'intervallo [0, 2 n -1] e di convertire ciascun valore in binario e invertire i bit in quel valore. Tratterai ciascun valore come un numero n -digit nella base 2, il che significa che l'inversione avverrà solo tra gli ultimi n bit.

Ad esempio, se n = 3, l'intervallo di numeri interi è [0, 1, 2, 3, 4, 5, 6, 7]. Questi sono

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

dove ogni indice i viene convertito in un indice j usando l'inversione dei bit. Ciò significa che l'output è [0, 4, 2, 6, 1, 5, 3, 7].

Le uscite per n da 0 a 4 sono

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

Potresti aver notato che si sta formando un motivo. Dato n , puoi prendere la sequenza precedente per n -1 e raddoppiarla. Quindi concatena quell'elenco raddoppiato con lo stesso doppio elenco ma incrementato di uno. Mostrare,

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

dove rappresenta la concatenazione.

È possibile utilizzare uno dei due metodi sopra per formare la soluzione. Se conosci un modo migliore, sei libero di usarlo anche tu. Qualsiasi metodo va bene purché produca i risultati corretti.

Regole

  • Questo è quindi vince la soluzione più breve.
  • Non sono consentiti i builtin che risolvono questa sfida nel suo insieme e quelli che calcolano l'inversione dei bit di un valore. Questo non include i builtin che eseguono la conversione binaria o altre operazioni bit a bit.
  • La soluzione deve essere almeno valida per n da 0 a 31.

3
"Non sono consentiti i builtin che risolvono questa sfida nel suo insieme e quelli che calcolano l'inversione dei bit di un valore." Awww, IntegerReverse[Range[2^#]-1,2,#]&. (Non so perché Mathematica abbia bisogno di questo integrato ma immagino che non sia molto più strano di Sunset...)
Martin Ender,

@MartinEnder Nice find. Un giorno, potrebbe essere che ci sarà un elemento integrato per tutto in Mathematica, compresa la generazione di sfide casuali di code-golf.
miglia

Possiamo stampare 0invece [0]o deve essere un elenco?
Dennis,

@Dennis Un buon punto. Lo permetterò, poiché è importante solo che l'output rappresenti una permutazione valida indipendentemente dal formato.
miglia

Restituire falso invece di 0 sarebbe accettabile?
Dennis,

Risposte:


2

Gelatina , 7 6 byte

Ḥ;‘$$¡

Grazie a @EriktheOutgolfer per giocare a golf a 1 byte!

Provalo online!

Come funziona

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

Codice:

¾)IF·D>«

Spiegazione:

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

Utilizza la codifica CP-1252 . Provalo online! .


Ben fatto! Batte quello che avevo :)
Emigna il

@Emigna Grazie! Qual era la tua versione allora?
Adnan,

0)ïsF·D>«era vicino però. Ho avuto dei problemi con lo '0'.
Emigna,

1
Buon uso di ¾. Devo ricordare quel trucco.
Emigna,

1
@KevinCruijssen Per l'ingresso 0 , sembra più bello avere la rappresentazione int di 0 e non la rappresentazione di stringa :). A parte questo, non ci sono differenze.
Adnan,

4

MATL, 13 12 10 9 8 byte

0i:"EtQh

Provalo online

Spiegazione

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

Per completezza, ecco la mia vecchia risposta usando l'approccio non ricorsivo (9 byte).

W:qB2&PXB

Provalo online

Spiegazione

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:

Esiste un'alternativa per 15 byte che utilizza la conversione binaria diretta e l'inversione.

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

uso

   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

Spiegazione

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

Ottava, 37 byte

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

Crea una funzione anonima denominata ansche può essere semplicemente chiamata con ans(n).

Demo online


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

Provalo su Ideone .

Grazie a @xnor per giocare a golf a 1 byte!


Si può fare [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())));}}

Bene, ho finalmente imparato Java per il mio secondo linguaggio di programmazione, quindi volevo usare le mie nuove abilità per completare una semplice sfida, e anche se si è rivelato molto lungo, non sono deluso. Sono contento di essere riuscito a completare una semplice sfida in Java.

Provalo online! (Ideone)


È possibile salvare alcuni byte analizzando un int da args anziché leggere da StdIn
Pavel

3

Mathematica, 56 33 byte

Il conteggio dei byte presuppone una sorgente codificata ISO 8859-1.

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

Questo utilizza la definizione ricorsiva per definire un operatore unario ±.


3

Perl, 46 45 byte

Include +1 per -p

Fornire il numero di input su 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]

Utilizza l'algoritmo ricorsivo a doppio incremento incrementale.

Esempi di esecuzione:

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]

Che ne dici f=n=>n>0?(r=f(n-1).map(i=>i*2)).concat(r.map(i=>i+1)):[0]?
miglia

@miles Whoops, non ho realizzato che non ho bisogno di un caso base n==1, grazie.
Dendrobium,

2
Penso di essere riuscito a radere 2 byte spostando la moltiplicazione per due:f=(n,m=1)=>n?[...n=f(n-1,m+m),...n.map(i=>i+m)]:[0]
Neil

2

Python 3, 67 59 byte

Grazie a @Dennis per -8 byte

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

Potremmo anche avere un'implementazione (modificata) semplice in Python, anche se è piuttosto lunga.

Una funzione anonima che accetta input per argomento e restituisce la permutazione a bit invertiti come elenco.

Come funziona

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

Provalo su Ideone


2
Ciò è in linea con il mio approccio, ma il golfismo non sopravviverà a un porto per Python 3.
Dennis,

2

Dyalog APL , 12 byte

Richiede il ⎕IO←0valore predefinito su molti sistemi.

2⊥⊖2⊥⍣¯12*⎕

2⊥ da-base-2 di

capovolto

2⊥⍣¯1 inverso di da-base-2 di

i primi n numeri interi, dove n è

2* 2 alla potenza di

input numerico

ProvaAPL online!


Per confronto, ecco l'altro metodo:

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

( il treno di funzioni ...

2∘× due volte (l'argomento)

, concatenato a

1+ uno più

2∘× due volte (l'argomento)

)⍣ applicato quante volte specificato da

input numerico

su

0 zero


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

@ngn Non ha nulla a che fare con il mio algoritmo.
Adám,

ho pensato che fosse simile al tuo "altro metodo" ma ok, scriverò una risposta separata
ngn

2

K (ngn / k) , 11 8 byte

2/|!2|&:

Provalo online!

 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'ultimo verbo nella composizione, quindi abbiamo bisogno di un :per forzarlo ad essere monadico


1

Julia, 23 22 byte

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

Piuttosto semplice implementazione del processo descritto nelle specifiche della sfida.

Provalo online!


1

Pyth, 8 byte

iR2_M^U2

Provalo online: dimostrazione o suite di test

Spiegazione:

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

Solo seguendo le specifiche ...

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

1

Rubino, 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++))),_;

accetta l'input dal parametro della riga di comando, stampa i valori delimitati da trattino basso. Corri con-nr .

soluzione ricorsiva, 72 byte

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

la funzione accetta numeri interi, restituisce array



1

Perl 6 , 42 byte

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

Provalo online!

L'incremento di un numero intero lancia semplicemente una sequenza di bit meno significativi, ad esempio da xxxx0111a xxxx1000. Quindi il prossimo indice con inversione di bit può essere ottenuto dal precedente lanciando una sequenza di bit più significativi. La maschera XOR può essere calcolata con m - (m >> (ctz(i) + 1))per m = 2**no m = 2**n-1.

Perl 6 , 30 byte

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

Provalo online!

Approccio ricorsivo


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]

La soluzione Python 2 di Port of @ Dennis ♦.



1

Japt , 14 13 byte

2pU Ǥw ú0U Í

Provalo online!

Disimballato e come funziona

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

Implementazione semplice.


In realtà c'è una scorciatoia non documentata per n2:Í
Oliver,

1

APL (Dyalog Classic) , 9 byte

(⍋,⍨)⍣⎕⊢0

Provalo online!

input valutato

( )⍣⎕⊢0 applica la cosa dentro ( ) così tante volte, a partire da0

,⍨ concatena il risultato corrente con se stesso

indici di una permutazione ascendente


0

x86, 31 byte

Accetta int[] bufferin eaxe n in sufficientemente ampi ecxe restituisce il buffer ineax .

Implementa l'algoritmo di concatenazione fornito nella dichiarazione di verifica. Potrebbe essere possibile salvare byte incrementando i puntatori di 4 invece di utilizzare direttamente gli accessi agli array, ma lea/ movè già piuttosto breve (3 byte per 3 reg e un moltiplicatore).

.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......|
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.