Wygeneruj sekwencję panoramy świątyni

39

Rozważ następujący proces:

  1. Weź nieujemną liczbę całkowitą N.

    np. N = 571

  2. Wyrażaj to w postaci binarnej bez zer wiodących. (Samo zero jest jedynym wyjątkiem, który się staje 0.)

    np. 571= 1000111011binarnie

  3. Rozbij kolejne ciągi zer i jedynek w tej reprezentacji binarnej.

    np 10001110111, 000, 111, 0,11

  4. Sortuj przebiegi od najdłuższego do najkrótszego.

    np 1, 000, 111, 0, 11000, 111, 11, 1,0

  5. Nadpisuj wszystkie cyfry w każdym przebiegu naprzemiennymi znakami 1„i 0”, zawsze zaczynając od 1„s”.

    np 000, 111, 11, 1, 0111, 000, 11, 0,1

  6. Połącz wynik, aby uzyskać nową liczbę binarną.

    np 111, 000, 11, 0, 11110001101= 909dziesiętnie

Kiedy kreślisz wartości wygenerowane przez ten proces, otrzymujesz całkiem czysty wykres:

Działka Temple Skyline do 1024

I mam nadzieję, że jest oczywiste, dlaczego nazywam powstałą sekwencję sekwencją Skyline świątyni :

Świątynia Skyline

Wyzwanie

Napisz program lub funkcję, która przyjmuje nieujemną liczbę całkowitą N i drukuje lub zwraca odpowiedni numer porządkowy Temple Skyline. Dane wejściowe i wyjściowe powinny być w systemie dziesiętnym.

np. jeśli wejście jest 571wyjściem powinno być 909.

Najkrótszy kod w bajtach wygrywa.

Dla odniesienia, oto terminy w sekwencji od N = 0 do 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

Oto warunki od 0 do 1023.

Hobby Calvina
źródło

Odpowiedzi:

4

Pyth, 20 19 bajtów

ACr.BQ8|is*V_SGH2 1

1 bajt zapisany przez Jakube

Pakiet testowy

Wykorzystuje fakt, że po kodowaniu długości przebiegu, przebiegi są pożądanymi przebiegami na wyjściu.

Utracono 3 bajty specjalną obudowę 0.

isaacg
źródło
14

CJam, 25 23 22 bajtów

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

Tylko trochę kodowania długości. -1 dzięki @ MartinBüttner.

Wypróbuj online / pakiet testowy .

Wyjaśnienie

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
źródło
11

Pyth - 21 20 bajtów

Dzięki @sok za uratowanie mi jednego bajtu!

is.em%hk2hb_Sr.BQ8 2

Wypróbuj tutaj online .

Maltysen
źródło
Możesz użyć .BQzamiast jQ2, co oznacza, że ​​możesz stracić przestrzeń między 8poprzednim a poprzednim 2.
Sok
is*R`s=!Z_ShMr.BQ8 2to interesujące rozwiązanie o tej samej długości. Głównie publikowanie, ponieważ tak naprawdę nie spodziewałem się, że argument przypisania w mapie działa poprawnie.
FryAmTheEggman
1
@FryAmTheEggman Wymień `sz ]. Oszczędza jeden bajt.
Jakube,
6

Python 2, 121 bajtów 125

121: Dzięki Sp3000 za golenie 4 bajtów!

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
źródło
1
Miły! Wierzę, że możesz to zrobić n*`~i%2`forzamiast"10"[i%2]*n for
Sp3000,
Dzięki za edycję! Musiałem szybko spieszyć, ale chciałem się poddać, ponieważ uważałem, że to piękne wyzwanie i dobre na pierwsze zgłoszenie. Wkrótce sprawdzę twoje zgłoszenie!
enpenax,
Myślę, że możesz zaoszczędzić trochę bajtów, używając sorted(...,key=len)zamiast używać, map(len,...ale nie rozumiem teraz w pełni twojego programu, więc nie jestem pewien , czy przyniosłoby to ci korzyść.
cole
Hej @Cole Mapuję, lenponieważ to jedyna informacja, której potrzebuję, aby zreplikować liczbę 1 i 0. Wypróbowałem twoją sugestię i dodaje ona 2 bajty, ponieważ będę musiał użyć lendwa razy, ale dziękuję za sugestię!
enpenax,
5

JavaScript ES6, 110 bajtów 113 116 119 120

Zaoszczędzono 3 bajty dzięki @intrepidcoder

Zaoszczędź 3 bajty dzięki @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``)

Proste podejście. Nie podoba mi się długość funkcji sortowania, ale nie mogę wymyślić sposobu na golfa.

Downgoat
źródło
Myślę, że możesz użyć +zamiast eval.
intrepidcoder,
@intrepidcoder dzięki, że zapisałeś 3 bajty!
Downgoat,
Nie mogę tego przetestować, ale split(/(0+)/g)powinienem móc go wymienić match(/(.)\1*/g).
NinjaBearMonkey,
@NinjaBearMonkey dzięki, że zapisałeś 3 bajty!
Downgoat,
Zapisywanie jednego bajtu: +(s=0, ... .map(l=>l.replace(/./g,s^=1))...)
Mam nadzieję, że mogę pomóc
5

C ++, 535 527 bajtów

(dzięki zereges za golenie niektórych bajtów.)

Teraz, kiedy pozbyliśmy się tych bajtów, program jest teraz konkurencyjny;)

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

Jestem nowym golfistą, więc proszę o wskazówki w komentarzach .

Rzeczy takie jak „nie potrzebujesz tych nawiasów” lub „użyj printf” są pomocne, ale doceniam również porady dotyczące logiki. Z góry dziękuję!

Dla ułatwienia czytania przedstawiam wersję bez golfa:

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

EDYCJA wersja gry w golfa obniżyła kilka bajtów, wersja bez golfa pozostała niezmieniona

Liam
źródło
Możesz zamiast int a; int b;używać int a,b;. Również zmienne w zakresie globalnym są inicjowane za pomocą 0. Nie musisz także używać nawiasów klamrowych, gdy jest tylko jedno polecenie do wykonania. Również ones=!ones;można uprościćones ^= 1;
Zereges
Zaoszczędziłem trochę bajtów dzięki
Liam,
Przesuń swoją pierwszą forpętlę 1, tj. for(int i=D;i;i--)I użyj pow(2,i-1)wewnątrz pętli.
nimi
@LiamNoronha W rzeczywistości nie zapisałeś tego, co
zaleciłem
1
@LiamNoronha Sprawdź to . Wciąż jest dużo miejsca na ulepszenia. Np. Ponowne użycie zmiennych (zapisuje definicję), onesmoże być również int. Może makrowanie int(pow(i))do P(i). Polecam przeczytanie dyskusji tutaj
Zereges
2

Haskell, 132 131 bajtów

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

Przykład użycia:

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

Jak to działa:

                 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
źródło
2

J - 30 bajtów

Funkcja przejmująca liczbę całkowitą po prawej stronie. Prawidłowo obsługuje 0.

(\:~#2|#\)@(#;.1~1,2~:/\])&.#:
  • #: - Weź reprezentację binarną.
  • 1,2~:/\]- Między każdą cyfrą zgłoś Prawda, jeśli są różne. Przygotuj wartość True, aby lista miała wartość True na początku każdego „uruchomienia”.
  • (#;.1~...) - Używając powyższego wektora boolowskiego, oblicz długość każdego przebiegu.
  • \:~ - Sortuj te długości od najdłuższego do najkrótszego.
  • 2|#\- Weź listę naprzemiennie 1 0 1 0 ...tak długo, jak lista długości.
  • (...#...) - Dla każdej liczby po lewej (posortowane długości) weź tyle odpowiednich pozycji po prawej stronie (naprzemiennie 1 i 0)
  • &. - Przekształć tę nową reprezentację binarną z powrotem na liczbę.

Przykłady:

   (\:~#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
algorytmshark
źródło
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

Myślę, że sortowanie może być krótsze.

Edycja: -20 bajtów, dzięki symbabque!

Laposhasú Acsa
źródło
Możesz się go pozbyć \ni mnie jest on wymagany do dopasowywania wyrażeń regularnych. W zamianie po prostu użyj .zamiast grupy char.
simbabque
grepCzęść też nie jest potrzebna . octJest schludny chociaż :)
simbabque
Dziękuję, przypadkowo zostawiłem te części z oryginalnego kodu.
Laposhasú Acsa
1

Python 3, 146 136 bajtów

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
źródło
Zamiast mapz lambda, byłoby lepiej zrobić ''.join(... for ... in ...)?
Sp3000,
1

Mathematica, 83 bajty

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

Definiuje nienazwaną funkcję.

Martin Ender
źródło
0

Rubin, 107 104 102 bajtów

(3 bajty zapisywane dzięki Nimi )

Nie zamierzam pokonać takich jak CJam, ale mam dość mały jak na rozsądny język.

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
Przywróć Monikę iamnotmaynard
źródło
Kilka bajtów do zapisania: (i+=1)%2jest i=1-i.
nimi
@nimi Ah, dziękuję. Próbowałem wymyślić, jak to skrócić.
Przywróć Monikę iamnotmaynard
0

Java 8, 179 176 bajtów

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

Użyłem dwóch importów statycznych: java.util.Integer.highestOneBiti java.util.Arrays.sort.

Dla czytelności, oto kod nierozszyfrowany:

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
źródło
-1

Python 2, 170 bajtów

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
źródło
4
Witamy w PPCG! Niestety myślę, że daje to nieprawidłowe wartości dla niektórych liczb, np. t(0) = 0Kiedy 1jest oczekiwane, a t(4) = 1kiedy 6
Sp3000