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 1000111011→ 1, 000, 111, 0,11

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

    np 1, 000, 111, 0, 11→ 000, 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, 0→ 111, 000, 11, 0,1

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

    np 111, 000, 11, 0, 1→ 1110001101= 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.