Gere a sequência do horizonte do templo

39

Considere o seguinte processo:

  1. Pegue um número inteiro não negativo N.

    por exemplo, N = 571

  2. Expresse-o em binário sem zeros à esquerda. (Zero em si é a única exceção, tornar-se 0.)

    por exemplo 571= 1000111011em binário

  3. Divida execuções consecutivas de uns e zeros nessa representação binária.

    por exemplo 10001110111, 000, 111, 0,11

  4. Classifique as execuções do maior para o menor.

    por exemplo 1, 000, 111, 0, 11000, 111, 11, 1,0

  5. Sobrescreva todos os dígitos em cada execução com 1's e 0' alternados , sempre começando com 1's.

    por exemplo 000, 111, 11, 1, 0111, 000, 11, 0,1

  6. Concatene o resultado para obter um novo número binário.

    por exemplo 111, 000, 11, 0, 11110001101= 909em decimal

Ao plotar os valores produzidos por esse processo, você obtém um gráfico bem organizado:

Temple Skyline plot para 1024

E espero que fique claro por que estou chamando a sequência resultante de Temple Skyline :

Skyline do templo

Desafio

Escreva um programa ou função que receba um número inteiro não negativo N e imprima ou retorne o número de sequência correspondente do Skyline do Templo. Sua entrada e saída devem estar em decimal.

Por exemplo, se a entrada é 571a saída deve ser 909.

O código mais curto em bytes vence.

Para referência, aqui estão os termos na sequência de 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

Aqui estão os termos de 0 a 1023.

Passatempos de Calvin
fonte

Respostas:

4

Pitão, 20 19 bytes

ACr.BQ8|is*V_SGH2 1

1 byte salvo por Jakube

Suíte de teste

Usa o fato de que, após a codificação do comprimento da execução, as execuções são as execuções desejadas na saída.

Perdeu 3 bytes caixa especial 0.

isaacg
fonte
14

CJam, 25 23 22 bytes

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

Apenas um pouco de codificação de execução. -1 graças a @ MartinBüttner.

Experimente on-line / suíte de testes .

Explicação

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
Sp3000
fonte
11

Pitão - 21 20 bytes

Obrigado a @sok por me salvar um byte!

is.em%hk2hb_Sr.BQ8 2

Experimente aqui online .

Maltysen
fonte
Você pode usar em .BQvez de jQ2, o que significa que pode perder o espaço entre o 8e o anterior 2.
Sok
is*R`s=!Z_ShMr.BQ8 2é uma solução interessante para o mesmo comprimento. Principalmente postando porque eu realmente não esperava que a atribuição em um argumento de mapa funcionasse.
FryAmTheEggman
1
@FryAmTheEggman Substitua `spor ]. Salva um byte.
Jakube 11/11
6

Python 2, 121 bytes 125

121: Agradecimentos ao Sp3000 por remover 4 bytes!

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)
enpenax
fonte
1
Agradável! Eu acredito que você também pode fazer em n*`~i%2`forvez de"10"[i%2]*n for
Sp3000 6/15
Obrigado pela edição! Eu tive que me apressar rapidamente, mas queria enviar, porque achei que esse era um desafio bonito e bom para uma primeira apresentação. Verificarei sua submissão em breve!
enpenax
Eu acho que você pode salvar alguns bytes usando em sorted(...,key=len)vez de usar, map(len,...mas eu não compreendo completamente o seu programa agora, então não tenho certeza de que isso os beneficiaria.
cole
Hey @Cole Estou mapeando lenporque essa é a única informação que preciso para replicar a quantidade de 1 e 0. Tentei sua sugestão e ela adiciona 2 bytes, pois terei que usar lenduas vezes, mas obrigado pela sugestão!
enpenax
5

JavaScript ES6, 110 bytes 113 116 119 120

Guardado 3 bytes graças a @intrepidcoder

Guardado 3 bytes graças 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``)

Abordagem direta. Não gosto da duração da função de classificação, mas não consigo pensar em uma maneira de jogar golfe.

Downgoat
fonte
Eu acho que você pode usar um em +vez de eval.
Intrepidcoder #
@intrepidcoder obrigado, que salvou 3 bytes!
Downgoat
Não posso testar isso, mas split(/(0+)/g)deve ser capaz de substituir match(/(.)\1*/g).
NinjaBearMonkey
@NinjaBearMonkey obrigado, que salvou 3 bytes!
Downgoat
Salvando um byte: +(s=0, ... .map(l=>l.replace(/./g,s^=1))...)
Espero poder ajudar
5

C ++, 535 527 bytes

(obrigado zereges por remover alguns bytes.)

Agora que nos livramos desses bytes, o programa agora é 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;}

Eu sou novo no golfe, por favor, me dê algumas dicas nos comentários .

Coisas como "você não precisa desses colchetes" ou "use printf" são úteis, mas também aprecio conselhos sobre a lógica. Desde já, obrigado!

Para facilitar a leitura, apresento a versão não destruída:

#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;
}

A versão EDIT golfed reduziu alguns bytes, a versão ungolfed inalterada

Liam
fonte
Você pode, em vez de int a; int b;usar int a,b;. Também variáveis ​​no escopo global são inicializadas com 0. Além disso, você não precisa usar colchetes quando houver apenas um comando a ser executado. Também ones=!ones;pode ser simplificado comoones ^= 1;
Zereges
Salvei alguns bytes graças
Liam
Mude o seu primeiro forloop por 1, ou seja, for(int i=D;i;i--)e use-o pow(2,i-1)dentro do loop.
nimi
@LiamNoronha Você realmente não salvou o que eu recomendado :)
Zereges
1
@LiamNoronha Confira isso . Ainda há muito espaço para melhorias. Por exemplo, reutilizar variáveis ​​(salva a definição) onestambém pode ser int. Talvez macroing int(pow(i))em P(i). Eu recomendo que você leia a discussão aqui
Zereges 6/15
2

Haskell, 132 131 bytes

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

Exemplo de uso:

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

Como funciona:

                 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
nimi
fonte
2

J - 30 bytes

Função tendo inteiro à direita. Lida corretamente com 0.

(\:~#2|#\)@(#;.1~1,2~:/\])&.#:
  • #: - Pegue a representação binária.
  • 1,2~:/\]- Entre cada dígito, relate True se forem diferentes. Anexe um True para que a lista tenha True no início de cada "execução".
  • (#;.1~...) - Usando o vetor booleano acima, calcule a duração de cada execução.
  • \:~ - Classifique esses comprimentos do maior para o menor.
  • 2|#\- Faça uma lista de alternâncias 1 0 1 0 ..., contanto que a lista de comprimentos.
  • (...#...) - Para cada número à esquerda (comprimentos classificados), use o item correspondente à direita (alternando 1 e 0)
  • &. - Converta essa nova representação binária de volta em um número.

Exemplos:

   (\:~#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
algoritmshark
fonte
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

Eu acho que a parte de classificação pode ser mais curta.

Edit: -20 bytes, graças ao symbabque!

Laposhasú Acsa
fonte
Você pode se livrar do \ne mnão é necessário para a correspondência de expressões regulares. Na sua substituição, basta usar em .vez do grupo de caracteres.
Simbolo 19 de
Também não há necessidade da greppeça. O que octé arrumado :)
#
Obrigado, deixei acidentalmente essas partes do código original.
Laposhasú Acsa
1

Python 3, 146 136 bytes

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))
Zach Gates
fonte
Em vez de mapcom um lambda, seria melhor fazer ''.join(... for ... in ...)?
Sp3000
1

Mathematica, 83 bytes

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

Isso define uma função sem nome.

Martin Ender
fonte
0

Ruby, 107 104 102 bytes

(salvou 3 bytes graças a nimi )

Não vou vencer os gostos de CJam, mas eu tenho um tamanho pequeno para uma linguagem sã.

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
Restabelecer Monica iamnotmaynard
fonte
Alguns bytes para salvar: (i+=1)%2é i=1-i.
Nid
@nimi Ah, obrigado. Eu estava tentando descobrir como diminuir isso.
Reintegrar Monica iamnotmaynard
0

Java 8, 179 176 bytes

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

Eu usei duas importações estáticas: java.util.Integer.highestOneBite java.util.Arrays.sort.

Para facilitar a leitura, aqui está o código não-bloqueado:

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
};
Olivier Grégoire
fonte
-1

Python 2, 170 bytes

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)
Tristan Batchler
fonte
4
Bem-vindo ao PPCG! Infelizmente eu acho que isso dá os valores errados para alguns números, por exemplo, t(0) = 0quando 1é esperado e t(4) = 1quando é esperado 6
SP3000