Genera la sequenza Skyline del tempio


39

Considera il seguente processo:

  1. Prendi un numero intero non negativo N.

    es. N = 571

  2. Esprimilo in binario senza zero iniziali. (Zero stesso è l'unica eccezione, diventando 0.)

    ad esempio 571= 1000111011in binario

  3. Dividi le sequenze consecutive di uno e zero in questa rappresentazione binaria.

    ad esempio 10001110111, 000, 111, 0,11

  4. Ordina le piste dal più lungo al più corto.

    ad esempio 1, 000, 111, 0, 11000, 111, 11, 1,0

  5. Sovrascrivi tutte le cifre di ogni corsa alternando 1'e 0', iniziando sempre con 1'.

    ad esempio 000, 111, 11, 1, 0111, 000, 11, 0,1

  6. Concatena il risultato per ottenere un nuovo numero binario.

    ad esempio 111, 000, 11, 0, 11110001101= 909in decimale

Quando tracciate i valori prodotti da questo processo, ottenete un grafico piuttosto accurato:

Trama di Temple Skyline fino al 1024

Ed è apparentemente chiaro il motivo per cui sto chiamando la sequenza risultante la sequenza di Temple Skyline :

Temple Skyline

Sfida

Scrivi un programma o una funzione che accetta un numero intero non negativo N e stampa o restituisce il corrispondente numero di sequenza di Temple Skyline. Sia l'input che l'output devono essere decimali.

es. Se l'ingresso è 571l'uscita dovrebbe essere 909.

Vince il codice più breve in byte.

Per riferimento, ecco i termini nella sequenza da N = 0 a 20:

0   1
1   1
2   2
3   3
4   6
5   5
6   6
7   7
8   14
9   13
10  10
11  13
12  12
13  13
14  14
15  15
16  30
17  29
18  26
19  25
20  26

Ecco i termini da 0 a 1023.

Risposte:


4

Pyth, 20 19 byte

ACr.BQ8|is*V_SGH2 1

1 byte salvato da Jakube

Test Suite

Utilizza il fatto che dopo la codifica di lunghezza di esecuzione, le esecuzioni sono le esecuzioni desiderate nell'output.

Caso speciale perso 3 byte 0.


14

CJam, 25 23 22 byte

ri1e>2be`z($W%a\+ze~2b

Solo un po 'di codifica run-length. -1 grazie a @ MartinBüttner.

Provalo online / Suite di test .

Spiegazione

ri        Read n from input as int
1e>       Take max with 1 (special case for n = 0)
2b        Convert n to binary
e`        Run length encode
z         Zip, giving a pair [<counts> <10101.. array>]
($W%      Drop the counts array and sort decending
a\+z      Add it back to the 10101.. array and re-zip
e~        Run length decode
2b        Convert from binary

11

Pyth - 21 20 byte

Grazie a @sok per avermi salvato un byte!

is.em%hk2hb_Sr.BQ8 2

Provalo qui online .


Puoi usare .BQinvece di jQ2, il che significa che puoi perdere lo spazio tra il 8e il precedente 2.
Ha

is*R`s=!Z_ShMr.BQ8 2è un'interessante soluzione della stessa lunghezza. Principalmente la pubblicazione perché non mi aspettavo davvero che l'assegnazione in un argomento della mappa funzionasse.
FryAmTheEggman,

1
@FryAmTheEggman Sostituisci `scon ]. Salva un byte.
Jakube,

6

Python 2, 121 byte 125

121: Grazie a Sp3000 per la rasatura di 4 byte!

import re;print int("".join(n*`~i%2`for i,n in enumerate(sorted(map(len,re.split('(1*|0+)',bin(input())[2:])))[::-1])),2)

125

import re;print int("".join("10"[i%2]*n for i,n in enumerate(sorted(map(len,re.split('(1*|0+)',bin(input())[2:])))[::-1])),2)

1
Bello! Credo che anche tu puoi fare n*`~i%2`forinvece di"10"[i%2]*n for
Sp3000 il

Grazie per il montaggio! Ho dovuto affrettarmi ma volevo presentarmi perché pensavo fosse una bella sfida e una buona prima presentazione. Controllerò la tua presentazione a breve!
enpenax,

Penso che puoi salvare alcuni byte usando sorted(...,key=len)invece di usare map(len,...ma al momento non comprendo appieno il tuo programma, quindi non sono sicuro che ti sarebbe di beneficio.
Cole

Hey @Cole Sto mappando lenperché questa è l'unica informazione di cui ho bisogno per replicare la quantità di 1 e 0. Ho provato il tuo suggerimento e aggiunge 2 byte, dato che dovrò usare lendue volte, ma grazie per il suggerimento!
enpenax,

5

JavaScript ES6, 110 byte 113 116 119 120

Salvato 3 byte grazie a @intrepidcoder

Salvato 3 byte grazie a @NinjaBearMonkey

n=>+('0b'+n.toString(2).split(/(0+)/).sort((b,a)=>a.length-b.length).map((l,i)=>l.replace(/./g,i-1&1)).join``)

Approccio diretto. Non mi piace la lunghezza della funzione di ordinamento, ma non riesco a pensare a un modo per giocare a golf.


Penso che puoi usare un +invece di eval.
intrepidcoder,

@intrepidcoder grazie, che ha salvato 3 byte!
Downgoat,

Non posso provarlo, ma split(/(0+)/g)dovrei essere in grado di sostituirlo match(/(.)\1*/g).
NinjaBearMonkey il

@NinjaBearMonkey grazie, che ha salvato 3 byte!
Downgoat,

Salvataggio di un byte: +(s=0, ... .map(l=>l.replace(/./g,s^=1))...)
Spero di poter aiutare il

5

C ++, 535 527 byte

(grazie zereges per aver rasato alcuni byte.)

Ora che ci siamo sbarazzati di quei byte, il programma è ora competitivo;)

#include<iostream>
#include<cmath>
int main(){int I,D;std::cin>>I;while(I>int(pow(2,D))){D++;}int L[99];int X=0;int Z=0;int O=0;for(int i=D-1;i>=0;i--){if( int(pow(2,i))&I){if(Z>0){L[X]=Z;Z=0; X++;}O++;}else{if(O>0){L[X] = O;O=0;X++;}Z++;}}if(Z>0){L[X]=Z;Z=0;X++;}if(O>0){L[X]=O;O=0;X++;}int P=0;bool B = true;int W = D-1;for(int j=0;j<X;j++){int K=0;int mX=0;for(int i=0;i<X;i++){if(L[i]>K){K=L[i];mX=i;}}L[mX]=0;if(B){for(int k=0;k<K;k++){P+=int(pow(2,W));W--;}}else{for(int k=0;k<K;k++){W--;}}B^=1;}std::cout<<P;return 0;}

Sono nuovo nel golf, quindi per favore dammi alcuni consigli nei commenti .

Cose come "non hai bisogno di quelle parentesi" o "usa printf" sono tutte utili, ma apprezzo anche i consigli sulla logica. Grazie in anticipo!

Per facilità di lettura, presento la versione non golfata:

#include<iostream>
#include<cmath>
int main()
{
int input,digits;

std::cin>>input;
while(input > int(pow(2,digits))){digits++;}

int list[99];
int index=0;
int zCounter=0;
int oCounter=0;

for(int i=digits;i>0;i--)
{
    if( int(pow(2,i-1))&input)
    {
        if(zCounter>0)
        {
            list[index] = zCounter;
            zCounter=0;
            index++;
        }
        oCounter++;
    }
    else
    {
        if(oCounter>0)
        {
            list[index] = oCounter;
            oCounter=0;
            index++;
        }
        zCounter++;
    }
}
if(zCounter>0)
{
        list[index] = zCounter;
        zCounter=0;
        index++;
}
if(oCounter>0)
{
        list[index] = oCounter;
        oCounter=0;
        index++;
}

int output = 0;
bool ones = true;
int power = digits-1;
for(int j=0;j<index;j++)
{
    int max=0;
    int mIndex=0;
    for(int i=0;i<index;i++)
    {
        if(list[i]>max){max=list[i];mIndex=i;}
    }
    list[mIndex]=0;

    if(ones)
    {
        for(int k=0;k<max;k++)
        {
            output+=int(pow(2,power));
            power--;
        }
    }
    else
    {
        for(int k=0;k<max;k++)
        {
            power--;
        }
    }
    ones^=1;

}
std::cout<<output;
return 0;
}

EDIT versione golfata ha portato giù un paio di byte, versione non modificata invariata


Puoi invece di int a; int b;usare int a,b;. Anche le variabili in ambito globale vengono inizializzate con 0. Inoltre non devi usare parentesi graffe quando c'è un solo comando da eseguire. Inoltre ones=!ones;può essere semplificato comeones ^= 1;
Zereges il

Salvati alcuni byte grazie
Liam,

Sposta il tuo primo forloop di 1, cioè for(int i=D;i;i--)e usa pow(2,i-1)dentro il loop.
nimi,

@LiamNoronha In realtà non hai salvato ciò che ho raccomandato :)
Zereges,

1
@LiamNoronha Dai un'occhiata . C'è ancora molto spazio per il miglioramento. Ad esempio il riutilizzo delle variabili (salva la definizione), onespuò anche essere int. Forse macroing int(pow(i))in P(i). Ti consiglierei di leggere la discussione qui
Zereges,

2

Haskell, 132 131 byte

import Data.List
g 0=[]
g n=mod n 2:g(div n 2)
q=[1]:[0]:q
f=foldl((+).(2*))0.concat.zipWith(<*)q.sortOn((-)0.length).group.g.max 1

Esempio di utilizzo:

> map f [0..20]
[1,1,2,3,6,5,6,7,14,13,10,13,12,13,14,15,30,29,26,25,26]

Come funziona:

                 max 1         -- fix n=0: f(0) is the same as f(1)
               g               -- turn into binary, i.e. list of 0s and 1s
            group              -- group sequences of equal elements
         sortOn((-)0.length)   -- sort groups on negative length
      zipWith(<*)q             -- map each element in a group to constant 1 or 0 by turns
   concat                      -- flatten all groups into a single list
foldl((+).(2*))0               -- convert back to decimal

2

J - 30 byte

Funzione che prende numero intero a destra. Gestisce correttamente 0.

(\:~#2|#\)@(#;.1~1,2~:/\])&.#:
  • #: - Prendi la rappresentazione binaria.
  • 1,2~:/\]- Tra ogni cifra, segnala True se sono diversi. Prepend a True in modo che l'elenco abbia True all'inizio di ogni "esecuzione".
  • (#;.1~...) - Usando il vettore booleano sopra, prendi la lunghezza di ogni corsa.
  • \:~ - Ordina queste lunghezze dal più lungo al più corto.
  • 2|#\ - Prendi un elenco di alternanza 1 0 1 0 ... purché l'elenco delle lunghezze.
  • (...#...) - Per ogni numero a sinistra (lunghezze ordinate), prendi quanti più elementi corrispondenti a destra (alternando 1 e 0)
  • &. - Converti questa nuova rappresentazione binaria in un numero.

Esempi:

   (\:~#2|#\)@(#;.1~1,2~:/\])&.#: 571
909
   i.21   NB. zero to twenty
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
   (\:~#2|#\)@(#;.1~1,2~:/\])&.#: every i.21   NB. apply separately to every number
1 1 2 3 6 5 6 7 14 13 10 13 12 13 14 15 30 29 26 25 26

2

Perl 5.10, 121 101

say oct"0b".join'',map{$|=1-$|;$_=~s/./$|/gr}sort{length$b<=>length$a}(sprintf"%b",shift)=~/(0*|1*)/g

Penso che la parte di ordinamento possa essere più breve.

Modifica: -20 byte, grazie a symbabque!


È possibile sbarazzarsi di \ne mnon è necessario per la corrispondenza delle espressioni regolari. Nella tua sostituzione, basta usare al .posto del gruppo di caratteri.
simbabque il

Neanche la grepparte è necessaria. Il octè però ordinata :)
simbabque

Grazie, ho accidentalmente lasciato quelle parti dal codice originale.
Laposhasú Acsa,

1

Python 3, 146 136 byte

import re;print(int(''.join(len(j)*'01'[i%2<1]for i,j in enumerate(sorted(re.findall('1+|0+',bin(int(input()))[2:]),key=len)[::-1])),2))

Piuttosto che mapcon un lambda, sarebbe meglio fare ''.join(... for ... in ...)?
Sp3000,

1

Mathematica, 83 byte

Flatten[0#+(d=1-d)&/@SortBy[d=0;Split[#~IntegerDigits~2],-Length@#&]]~FromDigits~2&

Questo definisce una funzione senza nome.


0

Ruby, 107 104 102 byte

(salvato 3 byte grazie a nimi )

Non riuscirò a battere artisti del calibro di CJam, ma l'ho preso abbastanza piccolo per un linguaggio sano.

p gets.to_i.to_s(2).scan(/((.)\2*)/).map{|e|e[i=0].size}.sort.reverse.map{|e|"#{i=1-i}"*e}.join.to_i 2

Alcuni byte da salvare: (i+=1)%2è i=1-i.
nimi,

@nimi Ah, grazie. Stavo cercando di capire come accorciarlo.
Ripristina Monica iamnotmaynard il

0

Java 8, 179 176 byte

(x)->{int g[]=new int[32],h=0,i=highestOneBit(x);g[0]=1;while(i>1)g[((x&i)>0)^((x&(i>>=1))>0)?++h:h]++;sort(g);for(i=32,h=0;g[--i]>0;)while(g[i]-->0)h=h<<1|i%2;return x<1?1:h;}

Ho usato due importazioni statiche: java.util.Integer.highestOneBitejava.util.Arrays.sort .

Per leggibilità, ecco il codice ungolfed:

java.util.function.ToIntFunction<Integer> f = (x) -> {
  int g[] = new int[32], h = 0, i = java.util.Integer.highestOneBit(x);
  g[0] = 1;
  while (i > 1) {
    g[((x & i) > 0) ^ ((x & (i >>= 1)) > 0) ? ++h : h]++;
  }
  java.util.Arrays.sort(g);
  for (i = 32, h = 0; g[--i] > 0;) {
    while (g[i]-- > 0) {
      h = h << 1 | i % 2;
    }
  }
  return x < 1 ? 1 : h; // handle zero
};

-1

Python 2, 170 byte

def t(n):
  from itertools import groupby;lst=sorted([''.join(g) for n,g in groupby(bin(n)[2:])],key=len)[::-1];s=''
  for i in lst:s+=str(i)
  return int(s,2)

4
Benvenuti in PPCG! Purtroppo penso che questo dia i valori sbagliati per alcuni numeri, ad esempio t(0) = 0quando 1è previsto e t(4) = 1quando è previsto 6
Sp3000
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.