Tạo chuỗi đường chân trời đền


39

Hãy xem xét quá trình sau đây:

  1. Lấy một số nguyên không âm N.

    ví dụ: N = 571

  2. Thể hiện nó trong nhị phân không có số 0 đứng đầu. (Bản thân Zero là ngoại lệ duy nhất, trở thành 0.)

    vd 571= 1000111011trong nhị phân

  3. Phá vỡ các lần chạy liên tiếp của những người và số không trong biểu diễn nhị phân này.

    ví dụ 10001110111, 000, 111, 0,11

  4. Sắp xếp các bước chạy từ dài nhất đến ngắn nhất.

    ví dụ như 1, 000, 111, 0, 11000, 111, 11, 1,0

  5. Ghi đè tất cả các chữ số trong mỗi lần chạy với xen kẽ 10', luôn bắt đầu bằng 1'.

    ví dụ như 000, 111, 11, 1, 0111, 000, 11, 0,1

  6. Kết hợp kết quả để có được một số nhị phân mới.

    ví dụ như 111, 000, 11, 0, 11110001101= 909trong hệ thập phân

Khi bạn vẽ các giá trị được tạo ra bởi quá trình này, bạn sẽ nhận được một biểu đồ khá gọn gàng:

Âm mưu của Temple Skyline tới 1024

Và hy vọng rõ ràng lý do tại sao tôi gọi chuỗi kết quả là chuỗi Temple Skyline :

Đền chân trời

Thử thách

Viết chương trình hoặc hàm nhận số nguyên N không âm và in hoặc trả về số thứ tự Temple Skyline tương ứng. Đầu vào và đầu ra của bạn nên ở dạng thập phân.

ví dụ: Nếu đầu vào là 571đầu ra nên 909.

Mã ngắn nhất tính bằng byte thắng.

Để tham khảo, đây là các thuật ngữ trong chuỗi từ N = 0 đến 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

Dưới đây là các điều khoản từ 0 đến 1023.

Câu trả lời:


4

Bình thường, 20 19 byte

ACr.BQ8|is*V_SGH2 1

1 byte được lưu bởi Jakube

Phòng thử nghiệm

Sử dụng thực tế là sau khi mã hóa độ dài chạy, các lần chạy là các lần chạy mong muốn trong đầu ra.

Mất 3 byte vỏ đặc biệt 0.


14

CJam, 25 23 22 byte

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

Chỉ cần một chút mã hóa chiều dài chạy. -1 cảm ơn @ MartinBüttner.

Dùng thử trực tuyến / Bộ thử nghiệm .

Giải trình

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

Cảm ơn @sok đã tiết kiệm cho tôi một byte!

is.em%hk2hb_Sr.BQ8 2

Hãy thử nó ở đây trực tuyến .


Bạn có thể sử dụng .BQthay vì jQ2, điều đó có nghĩa là bạn có thể mất khoảng trắng giữa 8và trước đó 2.
Sok

is*R`s=!Z_ShMr.BQ8 2là một giải pháp cùng chiều dài thú vị. Chủ yếu là đăng bởi vì tôi không thực sự mong đợi bài tập trong một đối số bản đồ sẽ hoạt động.
FryAmTheEggman

1
@FryAmTheEggman Thay thế `sbằng ]. Lưu một byte.
Jakube

6

Python 2, 121 byte 125

121: Cảm ơn Sp3000 vì đã loại bỏ 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
Tốt đẹp! Tôi tin rằng bạn cũng có thể làm n*`~i%2`forthay vì"10"[i%2]*n for
Sp3000

Cảm ơn đã chỉnh sửa! Tôi đã phải vội vã rời đi nhưng muốn nộp vì tôi nghĩ đây là một thử thách đẹp và là một thử thách tốt cho lần gửi đầu tiên. Tôi sẽ kiểm tra trình của bạn trong thời gian ngắn!
enpenax

Tôi nghĩ rằng bạn có thể lưu một số byte bằng cách sử dụng sorted(...,key=len)thay vì sử dụng map(len,...nhưng tôi không hoàn toàn hiểu chương trình của bạn ngay bây giờ vì vậy tôi không tích cực sẽ có lợi cho bạn.
cole

Xin chào @Cole Tôi đang lập bản đồ lenvì đó là thông tin duy nhất tôi cần sao chép số lượng 1 và 0. Tôi đã thử đề xuất của bạn và nó thêm 2 byte, vì tôi sẽ phải sử dụng lenhai lần sau đó, nhưng cảm ơn vì lời đề nghị!
enpenax

5

JavaScript ES6, 110 byte 113 116 119 120

Đã lưu 3 byte nhờ @intrepidcoder

Đã lưu 3 byte nhờ @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``)

Tiếp cận thẳng về phía trước. Không thích độ dài của chức năng sắp xếp nhưng tôi không thể nghĩ ra cách chơi golf.


Tôi nghĩ rằng bạn có thể sử dụng một +thay vì eval.
intrepidcoder

@intrepidcoder cảm ơn, đã lưu 3 byte!
Hạ cấp

Tôi không thể kiểm tra điều này, nhưng split(/(0+)/g)sẽ có thể thay thế match(/(.)\1*/g).
NinjaBearMonkey 6/10/2015

@NinjaBearMonkey cảm ơn, đã lưu 3 byte!
Hạ cấp

Tiết kiệm một byte: +(s=0, ... .map(l=>l.replace(/./g,s^=1))...)
Hy vọng tôi có thể giúp

5

C ++, 535 527 byte

(cảm ơn zereges đã cạo một số byte.)

Bây giờ chúng tôi đã loại bỏ các byte đó, chương trình hiện đang cạnh tranh;)

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

Tôi mới chơi golf, vì vậy xin vui lòng cho tôi một số lời khuyên trong các ý kiến .

Những thứ như "bạn không cần những dấu ngoặc đó" hay "sử dụng printf" đều hữu ích, nhưng tôi cũng đánh giá cao lời khuyên về logic. Cảm ơn trước!

Để dễ đọc, tôi trình bày phiên bản không có bản quyền:

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

Phiên bản golf EDIT mang lại một vài byte, phiên bản không được thay đổi


Bạn có thể thay vì int a; int b;sử dụng int a,b;. Ngoài ra các biến trong phạm vi toàn cầu được khởi tạo với 0. Ngoài ra, bạn không phải sử dụng dấu ngoặc nhọn khi chỉ có một lệnh được thực thi. Cũng ones=!ones;có thể được đơn giản hóa nhưones ^= 1;
Zereges 6/10/2015

Đã lưu một số byte cảm ơn
Liam

Thay đổi forvòng lặp đầu tiên của bạn bằng 1, tức là for(int i=D;i;i--)và sử dụng pow(2,i-1)bên trong vòng lặp.
nimi

@LiamNoronha Bạn thực sự đã không lưu những gì tôi khuyên dùng :)
Zereges

1
@LiamNoronha Kiểm tra này . Vẫn còn rất nhiều không gian để cải thiện. Ví dụ, sử dụng lại các biến (lưu định nghĩa), onescũng có thể được int. Có thể vĩ mô int(pow(i))vào P(i). Tôi khuyên bạn nên đọc cuộc thảo luận ở đây
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

Ví dụ sử dụng:

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

Làm thế nào nó hoạt động:

                 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

Hàm lấy số nguyên bên phải. Xử lý đúng 0.

(\:~#2|#\)@(#;.1~1,2~:/\])&.#:
  • #: - Lấy đại diện nhị phân.
  • 1,2~:/\]- Giữa mỗi chữ số, báo cáo Đúng nếu chúng khác nhau. Chuẩn bị một True để danh sách có True khi bắt đầu mỗi lần "chạy".
  • (#;.1~...) - Sử dụng vectơ boolean ở trên, lấy độ dài của mỗi lần chạy.
  • \:~ - Sắp xếp các độ dài này từ dài nhất đến ngắn nhất.
  • 2|#\- Lấy một danh sách xen kẽ 1 0 1 0 ...miễn là danh sách độ dài.
  • (...#...) - Đối với mỗi số ở bên trái (độ dài được sắp xếp), hãy lấy bao nhiêu mục tương ứng ở bên phải (xen kẽ 1 và 0)
  • &. - Chuyển đổi biểu diễn nhị phân mới này trở lại một số.

Ví dụ:

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

Tôi nghĩ rằng phần sắp xếp có thể ngắn hơn.

Chỉnh sửa: -20 byte, nhờ symbabque!


Bạn có thể thoát khỏi \nmkhông bắt buộc đối với biểu thức chính quy. Thay thế bạn, chỉ cần sử dụng .thay vì nhóm char.
simbabque

Không cần grepmột phần. Các octlà mặc dù gọn gàng :)
simbabque

Cảm ơn bạn, tôi vô tình để lại những phần đó từ mã gốc.
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))

Thay vì mapvới một lambda, nó sẽ tốt hơn để làm gì ''.join(... for ... in ...)?
Sp3000

1

Toán học, 83 byte

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

Điều này xác định một chức năng không tên.


0

Ruby, 107 104 102 byte

(đã lưu 3 byte nhờ nimi )

Sẽ không đánh bại những người như CJam, nhưng tôi đã nhận được nó khá nhỏ cho một ngôn ngữ lành mạnh.

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

Một vài byte để lưu: (i+=1)%2i=1-i.
nimi

@nimi À, cảm ơn bạn. Tôi đã cố gắng tìm ra cách để rút ngắn điều đó.
Phục hồi Monica iamnotmaynard

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

Tôi đã sử dụng hai nhập khẩu tĩnh: java.util.Integer.highestOneBitjava.util.Arrays.sort.

Để dễ đọc, đây là mã không được mã hóa:

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
Chào mừng đến với PPCG! Thật không may, tôi nghĩ rằng điều này cung cấp các giá trị sai cho một số số, ví dụ: t(0) = 0khi nào 1được mong đợi và t(4) = 1khi nào được dự kiến ​​là 6
Sp3000
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.