สร้างลำดับของ Temple Skyline


39

พิจารณากระบวนการต่อไปนี้:

  1. รับจำนวนเต็ม N ที่ไม่เป็นลบ

    เช่น N = 571

  2. แสดงเป็นเลขฐานสองโดยไม่มีเลขศูนย์นำหน้า (ศูนย์ตัวเองเป็นข้อยกเว้นเพียงอย่างเดียวเท่านั้น0)

    เช่น571= 1000111011ในไบนารี

  3. แยกการทำงานของเลขศูนย์และศูนย์ในการแทนเลขฐานสองนี้

    เช่น10001110111, 000, 111, 0,11

  4. เรียงลำดับการวิ่งจากที่ยาวที่สุดไปที่สั้นที่สุด

    เช่น1, 000, 111, 0, 11000, 111, 11, 1,0

  5. เขียนทับตัวเลขทั้งหมดในการวิ่งแต่ละครั้งด้วยการสลับ1และ0เริ่มต้นด้วย1เสมอ

    เช่น000, 111, 11, 1, 0111, 000, 11, 0,1

  6. ต่อผลลัพธ์เพื่อรับเลขฐานสองใหม่

    เช่น111, 000, 11, 0, 11110001101= 909ในทศนิยม

เมื่อคุณพล็อตค่าที่สร้างโดยกระบวนการนี้คุณจะได้กราฟที่สวยงาม:

พล็อตเส้นขอบฟ้า Temple เป็น 1024

และหวังเป็นอย่างชัดเจนว่าเหตุใดฉันจึงเรียกลำดับผลลัพธ์ตามลำดับTemple Skyline :

Temple Skyline

ท้าทาย

เขียนโปรแกรมหรือฟังก์ชั่นที่รับจำนวนเต็ม N ที่ไม่เป็นลบและพิมพ์หรือส่งกลับหมายเลขลำดับ Temple Skyline ที่เกี่ยวข้อง อินพุตและเอาต์พุตของคุณควรเป็นทศนิยม

เช่นถ้าใส่เป็นผลผลิตที่ควรจะเป็น571909

รหัสที่สั้นที่สุดในหน่วยไบต์ชนะ

สำหรับการอ้างอิงต่อไปนี้เป็นคำในลำดับจาก N = 0 ถึง 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

นี่คือข้อกำหนดตั้งแต่ 0 ถึง 1023

คำตอบ:


4

Pyth, 20 19 ไบต์

ACr.BQ8|is*V_SGH2 1

บันทึก 1 ไบต์โดย Jakube

ชุดทดสอบ

ใช้ความจริงที่ว่าหลังจากการเข้ารหัสความยาวรันการรันคือการรันที่ต้องการในเอาต์พุต

สูญเสียเคสพิเศษ 3 ไบต์ 0


14

CJam, 25 23 22 ไบต์

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

เพียงแค่การเข้ารหัสความยาวในการใช้งาน -1 ต้องขอบคุณ @ MartinBüttner

ลองมันออนไลน์ / ชุดทดสอบ

คำอธิบาย

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 ไบต์

ขอบคุณ @sok ที่ช่วยฉันหนึ่งไบต์!

is.em%hk2hb_Sr.BQ8 2

ลองมันนี่เกมออนไลน์


คุณสามารถใช้.BQแทนjQ2ซึ่งหมายความว่าคุณจะสูญเสียพื้นที่ระหว่างและก่อนหน้านี้8 2
Sok

is*R`s=!Z_ShMr.BQ8 2เป็นการแก้ปัญหาความยาวเดียวกันที่น่าสนใจ การโพสต์ส่วนใหญ่เพราะฉันไม่ได้คาดหวังว่าการกำหนดในอาร์กิวเมนต์แผนที่จะทำงาน
FryAmTheEggman

1
@FryAmTheEggman แทนที่ด้วย`s ]บันทึกหนึ่งไบต์
Jakube

6

Python 2, 121 ไบต์125

121: ขอบคุณ Sp3000 สำหรับการโกน 4 ไบต์!

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
ดี! ฉันเชื่อว่าคุณสามารถทำได้n*`~i%2`forแทน"10"[i%2]*n for
Sp3000

ขอบคุณสำหรับการแก้ไข! ฉันต้องรีบออกไปอย่างรวดเร็ว แต่ต้องการส่งเพราะฉันคิดว่านี่เป็นความท้าทายที่สวยงามและเป็นสิ่งที่ดีสำหรับการส่งครั้งแรก ฉันจะตรวจสอบการส่งของคุณในไม่ช้า!
enpenax

ฉันคิดว่าคุณสามารถบันทึกไบต์โดยใช้sorted(...,key=len)แทนการใช้map(len,...แต่ฉันไม่เข้าใจโปรแกรมของคุณอย่างเต็มที่ในขณะนี้ดังนั้นฉันจึงไม่ดีที่จะเป็นประโยชน์กับคุณ
โคล

สวัสดี @Cole ฉันทำแผนที่lenเพราะนั่นเป็นข้อมูลเดียวที่ฉันต้องการเพื่อทำซ้ำจำนวน 1 และ 0 ฉันลองใช้คำแนะนำของคุณและมันเพิ่ม 2 ไบต์เนื่องจากฉันจะต้องใช้lenสองครั้งแล้ว แต่ขอบคุณสำหรับคำแนะนำ!
enpenax

5

JavaScript ES6, 110 ไบต์113 116 119 120

บันทึก 3 ไบต์ด้วย @intrepidcoder

บันทึก 3 ไบต์ด้วย @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``)

วิธีการตรงไปข้างหน้า ไม่ชอบความยาวของฟังก์ชั่นการเรียงลำดับ แต่ฉันไม่สามารถคิดวิธีตีกอล์ฟได้


ฉันคิดว่าคุณสามารถใช้แทน+ eval
intrepidcoder

@intrepidcoder ขอบคุณที่บันทึกไว้ 3 ไบต์!
Downgoat

ฉันไม่สามารถทดสอบสิ่งนี้ได้ แต่split(/(0+)/g)ควรจะสามารถแทนที่match(/(.)\1*/g)ได้
NinjaBearMonkey

@NinjaBearMonkey ขอบคุณที่บันทึกไว้ 3 ไบต์!
Downgoat

ออมทรัพย์หนึ่ง byte: +(s=0, ... .map(l=>l.replace(/./g,s^=1))...)
หวังว่าฉันสามารถช่วย

5

C ++, 535 527 Bytes

(ขอบคุณ zereges สำหรับการปิดไบท์บางส่วน)

ตอนนี้เรากำจัดไบต์เหล่านี้แล้วตอนนี้โปรแกรม competetive;)

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

ฉันใหม่เพื่อการเล่นกอล์ฟจึงโปรดให้ฉันเคล็ดลับบางอย่างในการแสดงความคิดเห็น

สิ่งต่างๆเช่น "คุณไม่ต้องการวงเล็บเหล่านั้น" หรือ "use printf" ล้วน แต่มีประโยชน์ แต่ฉันก็ขอขอบคุณสำหรับคำแนะนำเกี่ยวกับตรรกะ ขอบคุณล่วงหน้า!

เพื่อความสะดวกในการอ่านฉันขอนำเสนอเวอร์ชันที่ไม่ดี:

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

ฉบับแก้ไขกอล์ฟนำลงสองสามไบต์รุ่นที่ไม่ได้รับการแก้ไข


คุณสามารถแทนการใช้งานint a; int b; นอกจากนี้ยังมีตัวแปรในในขอบเขตทั่วโลกจะเริ่มต้นได้ด้วยint a,b; 0นอกจากนี้คุณไม่จำเป็นต้องใช้วงเล็บปีกกาเมื่อมีคำสั่งเดียวที่จะดำเนินการ นอกจากนี้ยังones=!ones;สามารถประยุกต์เป็นones ^= 1;
Zereges

บันทึกบางส่วนขอบคุณ
Liam

เลื่อนลูปแรกของคุณforด้วย1เช่นfor(int i=D;i;i--)และใช้pow(2,i-1)ภายในลูป
nimi

@LiamNoronha คุณจริงไม่ได้บันทึกสิ่งที่ฉันแนะนำ :)
Zereges

1
@LiamNoronha ลองดูสิ ยังมีพื้นที่เหลือเฟือสำหรับการปรับปรุง เช่นตัวแปร reusing (ประหยัดนิยาม) นอกจากนี้ยังสามารถones intบางที macroing เข้าint(pow(i)) P(i)ฉันอยากจะแนะนำให้คุณอ่านการสนทนาที่นี่
Zereges

2

Haskell, 132 131 ไบต์

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

ตัวอย่างการใช้งาน:

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

มันทำงานอย่างไร:

                 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 ไบต์

ฟังก์ชั่นรับจำนวนเต็มด้านขวา จัดการ 0 อย่างถูกต้อง

(\:~#2|#\)@(#;.1~1,2~:/\])&.#:
  • #: - รับการเป็นตัวแทนไบนารี
  • 1,2~:/\]- ระหว่างตัวเลขแต่ละตัวให้รายงานTrueหากมีความแตกต่างกัน เตรียมTrueเพื่อให้รายการมีTrueเมื่อเริ่มต้นแต่ละ "run"
  • (#;.1~...) - ใช้เวกเตอร์บูลีนด้านบนใช้ความยาวของการวิ่งแต่ละครั้ง
  • \:~ - เรียงความยาวเหล่านี้จากยาวที่สุดถึงสั้นที่สุด
  • 2|#\- จดรายการการสลับ1 0 1 0 ...ตราบใดที่รายการความยาว
  • (...#...) - สำหรับแต่ละหมายเลขทางด้านซ้าย (ความยาวที่เรียง) ใช้รายการที่เกี่ยวข้องทางด้านขวาให้มากที่สุด (สลับ 1 และ 0)
  • &. - แปลงการแทนค่าฐานสองใหม่นี้กลับไปเป็นตัวเลข

ตัวอย่าง:

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

ฉันคิดว่าส่วนการเรียงลำดับอาจสั้นกว่านี้ได้

แก้ไข: -20 ไบต์ขอบคุณ symbabque!


คุณสามารถกำจัด\nและmไม่จำเป็นสำหรับการจับคู่นิพจน์ปกติ ในการทดแทนของคุณเพียงใช้.แทนกลุ่มถ่าน
simbabque

ไม่จำเป็นต้องมีgrepส่วนใดส่วนหนึ่ง octเป็นระเบียบแม้ว่า :)
simbabque

ขอบคุณฉันตั้งใจทิ้งส่วนเหล่านั้นจากรหัสต้นฉบับ
Laposhasú Acsa

1

Python 3, 146 136 ไบต์

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

แทนที่จะmapมีlambdaมันจะดีกว่าที่จะทำ''.join(... for ... in ...)?
Sp3000

1

Mathematica, 83 ไบต์

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

นี่เป็นการกำหนดฟังก์ชันที่ไม่มีชื่อ


0

Ruby, 107 104 102 ไบต์

(บันทึก 3 ไบต์ด้วยnimi )

จะไม่เอาชนะการชอบของ CJam แต่ฉันได้รับมันค่อนข้างเล็กสำหรับภาษาที่มีสติ

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

ไม่กี่ไบต์ที่จะบันทึก: คือ(i+=1)%2 i=1-i
nimi

@nimi Ah ขอบคุณ ฉันพยายามคิดให้สั้นลง
Reinstate Monica iamnotmaynard

0

Java 8, 179 176 ไบต์

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

ผมใช้สองนำเข้าแบบคงที่: และjava.util.Integer.highestOneBitjava.util.Arrays.sort

เพื่อความสะดวกในการอ่านนี่คือรหัสที่ไม่ได้รับการปรับปรุง:

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 ไบต์

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
ยินดีต้อนรับสู่ PPCG! น่าเสียดายที่ฉันคิดว่านี่จะให้ค่าที่ไม่ถูกต้องสำหรับบางตัวเลขเช่นt(0) = 0เมื่อ1ถูกคาดหวังและt(4) = 1เมื่อมีการคาดหวัง 6 ครั้ง
Sp3000
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.