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.

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.


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

11

Pyth - 21 20 bajtów

Dzięki @sok za uratowanie mi jednego bajtu!

is.em%hk2hb_Sr.BQ8 2

Wypróbuj tutaj online .


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)

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.


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


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

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

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!


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

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ę.


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

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

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

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.