Numeri di output fino a 2 ^ n-1, "ordinati"


38

Prendi un numero intero positivo n come input e genera (alcuni) numeri decimali che possono essere creati utilizzando n bit, ordinati nel modo seguente:

Prima elenca tutti i numeri che possono essere creati con solo uno 1, e il resto 0nella rappresentazione binaria (ordinata), quindi tutti i numeri che possono essere creati con due consecutivi 1 , il resto 0, quindi tre consecutivi 1 e così via.

Vediamo come appare per n = 4 :

0001  -  1
0010  -  2
0100  -  4
1000  -  8
0011  -  3
0110  -  6
1100  -  12
0111  -  7
1110  -  14
1111  -  15

Quindi, l'output per n = 4 è: 1, 2, 4, 8, 3, 6, 12, 7, 14, 15 (formato di output opzionale).

Casi test:

n = 1
1

n = 2
1 2 3

n = 3
1, 2, 4, 3, 6, 7

n = 8
1, 2, 4, 8, 16, 32, 64, 128, 3, 6, 12, 24, 48, 96, 192, 7, 14, 28, 56, 112, 224, 15, 30, 60, 120, 240, 31, 62, 124, 248, 63, 126, 252, 127, 254, 255

n = 17
1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 3, 6, 12, 24, 48, 96, 192, 384, 768, 1536, 3072, 6144, 12288, 24576, 49152, 98304, 7, 14, 28, 56, 112, 224, 448, 896, 1792, 3584, 7168, 14336, 28672, 57344, 114688, 15, 30, 60, 120, 240, 480, 960, 1920, 3840, 7680, 15360, 30720, 61440, 122880, 31, 62, 124, 248, 496, 992, 1984, 3968, 7936, 15872, 31744, 63488, 126976, 63, 126, 252, 504, 1008, 2016, 4032, 8064, 16128, 32256, 64512, 129024, 127, 254, 508, 1016, 2032, 4064, 8128, 16256, 32512, 65024, 130048, 255, 510, 1020, 2040, 4080, 8160, 16320, 32640, 65280, 130560, 511, 1022, 2044, 4088, 8176, 16352, 32704, 65408, 130816, 1023, 2046, 4092, 8184, 16368, 32736, 65472, 130944, 2047, 4094, 8188, 16376, 32752, 65504, 131008, 4095, 8190, 16380, 32760, 65520, 131040, 8191, 16382, 32764, 65528, 131056,16383, 32766, 65532, 131064, 32767, 65534, 131068, 65535, 131070, 131071

Questo è , quindi vince il codice più corto in ogni lingua !

Le buone spiegazioni sono fortemente incoraggiate , anche per soluzioni in "lingue normali"!



2
@zeppelin L'ho pensato anch'io all'inizio, ma questo è molto diverso.
ETHproductions

1
Relazionato. (Leggermente.)
Martin Ender,

6
Bonus immaginario se qualcuno lo fa senza alcuna forma di conversione di base (usando semplici vecchi calcoli matematici).
Stewie Griffin,

Ho scritto questo che è un mix tra i due immagino Provalo online!
PrincePolka

Risposte:


38

Python , 53 byte

f=lambda n,i=1:n*[f]and[i]+f(n-1,2*i)+i%2*f(n-1,i-~i)

Provalo online!

La funzione ricorsiva genera l'elenco ordinato come pre-ordine cammina lungo questo albero (esempio con n=4):

      1
     / \
    2   3
   /   / \
  4   6   7
 /   /   / \
8   12  14  15

1 2 4 8 3 6 12 7 14 15

I rami di sinistra raddoppiano il valore e i rami di destra i->i*2+1esistono ed esistono solo per dispari i. Quindi, la passeggiata pre-ordine per i non-foglie èT(i)=[i]+T(i*2)+i%2*T(i*2+1) .

L'albero termina in profondità n, dove si ntrova l'input. Ciò si ottiene diminuendon diminuendo con ogni passaggio verso il basso e arrestandosi quando è 0.

Una strategia alternativa sarebbe quella di terminare su valori che isuperano 2**n, piuttosto che approfondire la profondità. Ho trovato che questo è un byte più lungo:

f=lambda n,i=1:2**n/i*[f]and[i]+f(n,2*i)+i%2*f(n,i-~i)
f=lambda n,i=1:[f][i>>n:]and[i]+f(n,2*i)+i%2*f(n,i-~i)

4
Wow. Non solo è un trucco davvero interessante / intelligente, ma è estremamente efficace. +1, davvero bella risposta!
DJMcMayhem

2
Il [f]è un tocco divertente, non posso dire che ho visto prima.
FryAmTheEggman,

18

Gelatina , 6 byte

Ḷ2*ẆS€

Questo si qualifica per il bonus immaginario .

Provalo online!

Come funziona

Ḷ2*ẆS€  Main link. Argument: n

Ḷ       Unlength; yield [0, ..., n-1].
 2*     Yield [2**0, ..., 2**(n-1)].
   Ẇ    Sliding window; yield all subarrays of consecutive elements.
        The subarrays are sorted by length, then from left to right.
    S€  Map the sum atom over the substrings.

1
è l'ideale per questa sfida ed è implementato in modo che i risultati siano nell'ordine giusto per questa sfida. Ben fatto :-)
ETHproductions

Non sono 12 byte (almeno in UTF-8)?
Gareth,

1
@Gareth Sì, ma Jelly supporta anche un set di caratteri a byte singolo , che contiene gli unici 256 simboli che comprende.
Dennis,

9

Mathematica, 40 byte

Join@@Table[2^j(2^i-1),{i,#},{j,0,#-i}]&

Ogni numero nell'elenco desiderato è la differenza di due potenze di 2, quindi semplicemente li generiamo in ordine usando Table e quindi appiattiamo l'elenco. Penso che questo guadagni il bonus immaginario di Stewie Griffin :)

Mathematica, 35 byte

Tr/@Rest@Subsequences[2^Range@#/2]&

Un porto dell'algoritmo Jelly di Dennis . Non lo sapevo Subsequencesprima! (Inoltre non ho visto che miglia avevano pubblicato questa risposta esatta ... vai a votarla!)


1
Nota: questa soluzione è identica al codice Mathematica di @mile , pubblicato 5 ore prima della modifica di @GregMartin. Tuttavia, per meta consenso , questa risposta è ancora valida.
JungHwan Min

Ugh, non l'ho visto, grazie per averlo sottolineato.
Greg Martin,

8

JavaScript (ES6), 59 58 55 byte

for(q=prompt(n=1);p=q--;n-=~n)for(m=n;p--;m*=2)alert(m)

Un programma completo che accetta input tramite un prompt e avvisa ogni numero in successione. Questo si qualifica anche per il bonus immaginario .

Test snippet

(Nota: utilizza console.loginvece di alert)


Suggerimento (dopo aver selezionato "Non mostrare più popup"): passa a console.log per lo snippet di prova.
Tejas Kale,

@TejasKale Buona idea, grazie!
ETHproductions

7

JavaScript (ES6), 55 51 byte

Restituisce un elenco di numeri interi separati da spazio.

n=>(F=k=>k>>n?--j?F(k>>j|1):'':k+' '+F(k*2))(1,j=n)

Bonus immaginario amichevole.

Formattato e commentato

n => (                    // main function, takes n as input
  F = k =>                // recursive function, takes k as input
    k >> n ?              // if k is greater or equal to 1 << n:
      --j ?               //   decrement j ; if j is > 0:
        F(k >> j | 1)     //     do a recursive call with an additional bit set
      :                   //   else
        ''                //     stop recursion
    :                     // else
      k + ' ' + F(k * 2)  //   append k to output and do a recursive call with k * 2
  )(1, j = n)             // start the recursion with k = 1 and j = n

Casi test



6

Mathematica, 35 byte

Tr/@Rest@Subsequences[2^Range@#/2]&

5

Python 2 , 65 63 58 byte

lambda n:[(2<<k/n)-1<<k%n for k in range(n*n)if k/n+k%n<n]

Provalo online!


1
Ho appena trascorso un'ora a trovare quella formula (2<<i)-1<<j... e tu l'hai già capito. Ottimo lavoro! Inoltre, buon lavoro per sbarazzarsi delle doppie gamme
TheNumberOne


4

Haskell, 47 byte

f n=[1..n]>>= \b->take(n-b+1)$iterate(2*)$2^b-1

Esempio di utilizzo: f 4-> [1,2,4,8,3,6,12,7,14,15]. Provalo online! .

Come funziona: per ogni numero bin [1..n], inizia con 2^b-1e raddoppia ripetutamente il valore e prendi n-b+1elementi da questo elenco.



4

Groovy, 90 89 byte

{(0..<2**it).collect{0.toBinaryString(it)}.sort{it.count("1")}.collect{0.parseInt(it,2)}}

La conversione binaria è così stupida in groovy.

-1 grazie a Gurupad Mamadapur


3
Caldaia a conversione binaria da 28 byte, così dolorosa.
Magic Octopus Urn

1
{(1..<2**it)...salva un byte.
Gurupad Mamadapur,


3

Utilità Bash + Unix, 51 byte

dc<<<2i`seq -f%.f $[10**$1-1]|grep ^1*0*$|sort -r`f

Provalo online!

L'ingresso n viene passato in un argomento.

Utilizzare seq per stampare tutti i numeri con n o meno cifre. (Questi sono numeri di base 10, quindi ci sono molti altri numeri qui. È dispendioso e richiede molto tempo, ma questo è il golf del codice!)

La chiamata a grep mantiene solo quei numeri che consistono esattamente di 1 seguito da 0.

Quindi utilizzare sort -r per ordinare questi in ordine lessicografico inverso.

Infine, dc è impostato sull'input di base 2: inserisce i numeri ordinati in una pila e quindi stampa la pila dall'alto verso il basso. (Questo stampa l'ultimo elemento spinto per primo, ecc., Motivo per cui sto usando sort -r anziché solo sort.)

Corretto un bug: avevo omesso l'opzione -f% .f su seq, che è richiesta per i conteggi interi da 1000000 in poi. (Grazie a @TobySpeight per aver sottolineato che si è verificato un problema.)


" Sprecato e che richiede tempo " ... e intelligente ! Grazie per questo - è un buon promemoria per ignorare intenzionalmente l'efficienza computazionale quando si gioca a golf. È davvero difficile quando passi il resto dei tuoi giorni a scrivere codice veloce e chiaro ...
Toby Speight,

Alcuni valori mancanti: dc<<<2i`seq $[10**7-1]|grep ^1*0*$|sort -r`f | wc -riporta solo 12 valori. Penso che tu voglia grep ^1[01]*$invece.
Toby Speight,

@TobySpeight Grazie - c'era un bug che ho corretto. Il problema non era con la regex; il problema era che seq richiedeva un'opzione. (Non sono sicuro del motivo per cui stavi ottenendo solo 12 valori di output - anche la versione errata ha prodotto 21 valori di output anziché i 28 corretti. Se lo avessi eseguito su TIO, potrebbe aver superato il limite di 1 minuto di TIO .) Ora ho provato questo su Linux e OS X.
Mitchell Spector,

1
In realtà, ho frainteso la domanda: l'importante parola "consecutiva" lì in qualche modo è passata subito davanti a me!
Toby Speight,


2

Perl 6 , 38 byte

->\n{map {|(2**$_-1 X+<0..n-$_)},1..n}

Come funziona

->\n{                                }  # A lambda with argument n.
                                 1..n   # Numbers from 1 to n.
     map {                     },       # Replace each one with a list:
            2**$_-1                     #   2 to that power minus 1,
                    X+<                 #   bit-shifted to the left by each element of
                       0..n-$_          #   the range from 0 to n minus the number.
          |(                  )         #   Slip the list into the outer list.

Cioè costruisce i numeri in questo modo:

1 2 4 8 = (2^1)-1 bit-shifted to the left by 0 1 2 3 places
3 6 12  = (2^2)-1 bit-shifted to the left by 0 1 2   places
7 14    = (2^3)-1 bit-shifted to the left by 0 1     places
15      = (2^4)-1 bit-shifted to the left by 0       places      n rows
                                                  
             n                                     n-1

Il codice:


Perl 6 , 44 byte

->\n{map {|(2**$_-1,* *2...^*>2**n-1)},1..n}

Questo è stato il mio primo approccio prima di pensare alla soluzione (in realtà più semplice) di spostamento dei bit sopra.

Come funziona

->\n{                                      }  # A lambda with argument n.
                                       1..n   # Numbers from 1 to n.
     map {                           }        # Replace each one with:
            2**$_-1                              # 2 to that power minus 1,
                   ,* *2                         # followed by the result of doubling it,
                        ...^                     # repeated until (but not including)
                            *>2**n-1             # it's larger than 2^n-1.
          |(                        )            # Slip the list into the outer list.

Cioè costruisce i numeri in questo modo:

1 2 4 8 = (2^1)-1, times 2, times 2, times 2
3 6 12  = (2^2)-1, times 2, times 2
7 14    = (2^3)-1, times 2
15      = (2^4)-1                                 n rows
                                    
             n                       as many columns as possible in
                                     each row without exceeding (2^n)-1

2

Haskell 59 46 byte

Ho iniziato con f n=[0..n]>>= \b->take(n-b).iterate(*2).sum.map(2^)$[0..b]

dalla risposta di nimi sopra ha acquisito l'intuizione che sum.map(2^)$[0..x]può essere ridotta a2^x-1

Finendo con

e n=[1..n]>>= \x->map(\y->2^y*(2^x-1))[0..n-x]

[1..n] - elenca con il numero di bit consecutivi che vogliamo scorrere`

>> = - tradotto per ogni elemento nell'elenco a sinistra, passalo nella funzione a destra e concatena tutti i risultati

\ x -> - dichiarazione della funzione lambda con un argomento

mappa xy : applica la funzione x a tutti i membri dell'elenco y

Nel nostro caso x = (\ y-> 2 ^ y * (2 ^ x-1)) - un'altra funzione lambda 2 ^ y * (2 ^ x-1)). Questa formula deriva dalla moltiplicazione per due aggiungendo uno zero a destra in binario (esempio da 0001 a 0010). 2 ^ x - 1 è il numero di bit con cui stiamo lavorando. quindi per 11 abbiamo 2 ^ 0 * 3 (cioè non spostare affatto) == 0011, quindi 2 ^ 1 * 3 = 0110 quindi 2 ^ 2 * 3 - 1100.

[0..nx] Crea l'elenco di quante volte possiamo spostare i bit. Se stiamo lavorando con un singolo 1, guardando 0001 vogliamo spostare 3 volte (4-1). Se stiamo lavorando con due 11, vogliamo 4-2 e così via.


2

Python 3, 59 byte

Nota: questo è stato realizzato indipendentemente dalle soluzioni di ovs e Dennis , anche se è molto simile a entrambi.

lambda n:[(2<<i)-1<<j for i in range(n)for j in range(n-i)]

Come funziona:

for i in range(n)for j in range(n-i)  # Iterate over number of ones, then number of places
                                      # shifted over. i = ones, j = shifts

(2<<i)                                # Create a one followed by i zeroes
      -1                              # Subtract one from above to get i ones.
        <<j                           # Shift j places.

Provalo online!

Suggerimenti (sia in codice che in contanti) sono sempre i benvenuti!


2

Japt , 11 byte

o@o!²ãXÄ mx

Provalo online!

Spiegazione

Questo praticamente utilizza l'approccio di @Dennis:

o@ o!²  ãXÄ  mx
oX{o!p2 ãX+1 mx}
                  // Implicit: U = input integer
oX{            }  // Create the range [0...U) and map each item X by this function:
   o              //   Create the range [0...U)
    !p2           //     and map each item Z to 2.p(Z); that is, 2**Z.
                  //     (p2 would map each item Z to Z.p(2); ! reverses the arguments.)
        ãX+1      //   Get all overlapping slices of length X + 1.
             mx   //   Map each of these slices Z through Z.x(); that is, sum each slice.
                  // Implicit: output result of last expression


2

PHP, 59 56 53 byte

for(;$p>($k*=2)?:($p=1<<$argn)>$k=$i+=$i+1;)echo$k,_;

accetta input da STDIN; corri con -R.

abbattersi

for(;$p>($k*=2)         // 3. inner loop: shift-0 $k while $k<$p (false in first iteration)
    ?:
    ($p=1<<$argvn)      // 1. init $p=2^N, outer loop:
    >$k=$i+=$i+1        // 2. shift-1 $i while $i<$p, init $k to new $i
;)
    echo$k,_;           // 4. print $k

Puoi usare $argnun'ottima idea. Dopo aver letto la domanda ho in testa una soluzione con oltre 200 byte
Jörg Hülsermann

@ JörgHülsermann Grazie per avermi ricordato di STDIN. Adoro unire i loop.
Tito,

1

J , 19 byte

(0-.~&,>:+/\2&^)@i.

Questo utilizza lo stesso metodo nella soluzione di @Dennis .

Provalo online!

Spiegazione

(0-.~&,>:+/\2&^)@i.  Input: integer n
                 i.  Range [0, 1, ..., n-1]
(              )@    Operate on that range
            2&^        Compute 2^x for each x in that range
       >:              Increment each in that range
           \           For each overlapping sublist of size (previous) in powers of 2
         +/              Reduce by addition
 0                     The constant 0
     &,                Flatten each
  -.~                  Remove zeroes

1

Python 3, 91 byte

a=int(input())
print(*[int('1'*-~b,2)<<c for b in range(a)for c in range(a-b)],sep=', ')

Programma completo, con virgola + spazio separato, come specificato.

Spiegazione:

La notazione a stella disimballa gli elenchi. Quindi print(*[1,2,3])è lo stesso di print(1,2,3). Passa al int()costruttore una stringa di '1' consecutivi.

-~b valuta b+1 , ma non è necessario racchiuderlo tra parentesi quando si moltiplica una stringa.

Sposta il numero intero prodotto un numero crescente di volte. print()ha l'argomento sep opzionale, che specifica la stringa da inserire tra ciascun elemento in un elenco decompresso.


2
Puoi semplicemente stampare l'elenco. Il formato di output non è così rigoroso.
mbomb007,

1

Java 7, 108 byte

static void x(int i){int a=0,t=1<<i,b;while((a=(a<<1)+1)<t){b=a;do System.out.println(b);while((b<<=1)<t);}}

Raddoppia il valore iniziale purché il risultato sia inferiore a 2^n. Successivamente, aggiorna il valore iniziale (initial_value * 2) + 1e ricomincia da lì fino a quando non raggiunge(2^n)-1 .

ad es. per n=4:

0001 -> init
0010
0100
1000
return, double init and add one
0011 -> init
0110
1100
return, double init and add one
0111 -> init
1110
return, double init and add one
1111 -> init
done

Provalo online!


1

Rubino, 50 byte

->r{1.upto(r){|x|p a=2**x-1;p a while(a*=2)<2**r}}

Ho provato alcuni approcci "intelligenti", ma questo sembra essere il più breve (seguire letteralmente le istruzioni)

Spiegazione:

Ogni iterazione inizia con 2 ^ n-1 e si moltiplica per 2 fino a raggiungere il limite superiore. Niente di speciale, solo matematica di base.


1

QBIC , 37 byte - bonus immaginario = ancora 37 byte ...

:[a|e=2^b-1┘while e<2^a┘?e┘e=e*2┘wend

Peccato che non ho ancora integrato while-wendin QBIC ... Spiegazione:

:       Get N from the command line
[a|     For b = 1 to N; The sequence is reset N times
e=2^b-1 Set the first number of this sub-sequence (yields 1, 3, 7, 15 ...)
┘       Line-break - syntactic separation of commands because there's no command for WHILE yet.
while   Pure QBasic code - lower-case is not (really) interpreted by QBIC
e<2^a   Continue as long as we don't exceed the maximum value
┘?e     Print the number in the sequence
┘e=e*2  Double the number
┘wend   And loop as long as we're not exceeding maximum, reset the sequence otherwise.
        FOR loop auto-closed by QBIC

EDIT: QBIC ora ha il supporto per WHILE:

:[a|e=2^b-1≈e<2^a|?e┘e=e*2

Questo è solo 26 byte! Ecco il WHILE:

≈e<2^a|          ≈ = WHILE, and the TRUE condition is everything up to the |
       ...       Loop code goes here
          ]      Close construct: adds a WEND instruction
                 In the program above, this is done implicitly because of EOF.


1

R , 69 48 46 byte

n=scan();for(i in 1:n)print((2^i-1)*2^(i:n-i))

Ogni numero decimale corrispondente a i in 1..nquelli nel sistema binario viene moltiplicato per 2^(0..n-i), cioè prime n-i+1potenze di due (1, 2, 4, ...).

Provalo online!


1

Stax , 9 byte

übg▓}╥é►╪

Esegui ed esegui il debug online!

Spiegazione

Bonus immaginario se qualcuno lo fa senza alcuna forma di conversione di base (usando semplici vecchi calcoli matematici).

Bene, non ci sono conversioni di base qui.

Utilizza la versione decompressa (10 byte) per spiegare.

m|2vx_-DQH
m             For input=`n`, loop over `1..n`
 |2v          Power of two minus one
    x_-D      Do `n-j` times, where `j` is the current 1-based loop index
        Q     Output the current value
         H    And double it

0

Lotto, 92-0 = 92 byte

@for /l %%i in (1,1,%1)do @for /l %%j in (%%i,1,%1)do @cmd/cset/a"(1<<%%i)-1<<%%j-%%i"&echo(

Sottraendo 0 per il bonus immaginario di @ StewieGriffin.

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.