การสั่งซื้อแปลก ๆ ของ Sharkovskii


33

บทนำ

ในความท้าทายนี้เราจะจัดการกับการเรียงลำดับของจำนวนเต็มบวก การสั่งซื้อจะเป็นดังนี้:

   3,    5,    7,    9,    11, ...
 2*3,  2*5,  2*7,  2*9,  2*11, ...
 4*3,  4*5,  4*7,  4*9,  4*11, ...
 8*3,  8*5,  8*7,  8*9,  8*11, ...
16*3, 16*5, 16*7, 16*9, 16*11, ...
 ...
... 64, 32, 16, 8, 4, 2, 1

อันดับแรกเราแสดงจำนวนเต็มแปลกทั้งหมดที่มากกว่า 1 ในลำดับจากน้อยไปหามาก จากนั้นเราจะแสดงรายการจำนวนเต็มคี่สองครั้งที่มากกว่า 1 จากนั้น 4 ครั้งจากนั้น 8 ครั้งและต่อไปนี้: สำหรับkทั้งหมดเราแสดง2 kคูณจำนวนเต็มคี่ที่มากกว่า 1 ในลำดับที่สูงขึ้น ในที่สุดเราจะแสดงพลังของสองตามลำดับจากมากไปน้อยสิ้นสุดที่ 1 ทุกจำนวนเต็มบวกเกิดขึ้นใน "รายการ" นี้เพียงครั้งเดียว

เพิ่มเติมอย่างชัดเจนพิจารณาสองจำนวนเต็มบวกชัดเจนA = n · 2 PและB = m · 2 คิวที่n, ม. 1 ≥แปลกและP, Q ≥ 0 ดังนั้นAมาก่อนBในการสั่งซื้อหากหนึ่งในเงื่อนไขดังต่อไปนี้มี:

  • n> 1 , m> 1และp <q
  • 1 <n <mและp = q
  • n> m = 1
  • n = m = 1และp> q

การจัดเรียงนี้จะปรากฏในผลลัพธ์ทางคณิตศาสตร์ที่น่าประหลาดใจที่รู้จักกันในชื่อทฤษฎีบทของ Sharkovskiiซึ่งเกี่ยวข้องกับประเด็นของระบบพลวัต ฉันจะไม่เข้าไปดูรายละเอียดที่นี่

งาน

งานของคุณในการท้าทายนี้คือการคำนวณลำดับข้างต้น อินพุตของคุณเป็นจำนวนเต็มบวกAและBซึ่งอาจเท่ากับ ผลลัพธ์ของคุณเป็นค่าความจริงหากAมาก่อนBในการสั่งซื้อและค่าที่ผิดพลาดเป็นอย่างอื่น ถ้าA = Bผลลัพธ์ของคุณควรเป็นจริง คุณสามารถใช้AและBตามลำดับใดก็ได้ตราบใดที่คุณสอดคล้อง

คุณไม่ต้องกังวลเกี่ยวกับจำนวนเต็มล้น แต่อัลกอริทึมของคุณควรทำงานในทางทฤษฎีสำหรับอินพุตขนาดใหญ่โดยพลการ

กรณีทดสอบ

อินสแตนซ์ที่แท้จริง

3 11
9 6
48 112
49 112
158 158
36 24
14 28
144 32
32 32
32 8
3 1
1 1

อินสแตนซ์ที่เป็นเท็จ

1 2
1 5
11 5
20 25
2 8
256 255
256 257
72 52
2176 1216
2176 2496

คำตอบ:


5

Python 2, 87 71 ไบต์

k=lambda n:[n&~-n<1,(n&-n)*cmp(n&~-n,1),n/(n&-n)]
lambda a,b:k(a)<=k(b)

สิ่งนี้อาจจะไม่ชนะรางวัลขนาดใด ๆ แต่คำตอบนี้ใช้ได้โดยการสร้าง 3-tuple โดยใช้ 3 นิพจน์จากจำนวนเต็มว่าเมื่อเรียงลำดับพจนานุกรมจะส่งผลในการสั่งซื้อที่ถูกต้อง

ในแง่ที่สามารถอ่านได้ tuple ใช้สำหรับA = n · 2 p :

[n == 0, p * (1 - 2*(n == 0)), n]

5

JavaScript (ES6), 53 49 ไบต์

f=(a,b)=>b<2||a>1&&(a&b&1?a<=b:a&1|~b&f(a/2,b/2))

คำอธิบาย:

  • หาก b คือ 1 ดังนั้น a นำหน้า (หรือเท่ากับ) b
  • มิฉะนั้นถ้า a คือ 1 ดังนั้น a จะไม่นำหน้า b
  • มิฉะนั้นถ้าทั้ง a และ b เป็นเลขคี่ให้ใช้การตรวจสอบความไม่เท่าเทียมปกติ
  • มิฉะนั้นถ้า a เป็นคี่มันจะนำหน้า b
  • มิฉะนั้นถ้า b เป็นเลขคี่ค่า a จะไม่นำหน้า b
  • มิฉะนั้นให้แบ่งทั้ง a และ b ด้วย 2 แล้วลองอีกครั้ง

แก้ไข: บันทึก 2 ไบต์ขอบคุณ @Arnauld


ดี ฉันไม่ได้คิดถึงการใช้การสอบถามซ้ำที่นี่ จะa&1|~b&1&f(a/2,b/2)ทำงานอย่างไร
Arnauld

@Arnauld ฉันไม่แน่ใจฉันกังวลว่ามันจะวนซ้ำไปเรื่อย ๆ
Neil

มันเป็นไปไม่ได้เพราะb<2ในที่สุดจะเป็นจริง ตอนนี้ปัญหาอื่นคือคุณจะดำเนินการซ้ำมากกว่าที่จำเป็นและรับค่าทศนิยม แต่ฉันไม่พบตัวอย่างตัวอย่างที่ไม่ทำงานตามที่คาดไว้
Arnauld

@Arnauld Ah ใช่ฉันไม่ได้ใช้b<2ตอนแรก แต่ฉันคิดว่ามันจะใช้งานได้ในขณะนี้
Neil

@Arnauld ยังดีกว่าเนื่องจากf(a/2,b/2)ผลตอบแทนเพียง0, 1, falseหรือฉันไม่ได้ต้องการtrue &1
Neil

5

Python 2, 50 ไบต์

lambda*l:cmp(*[([-n][n&n-1:],n&-n,n)for n in l])<1

แต่ละหมายเลขจะถูกจับคู่กับสามซึ่งเรียงลำดับเป็นลำดับที่ต้องการ

  • ค่าหลักคือ [-n][n&n-1:]ซึ่งจัดการกับพลังของ 2 ในตอนท้าย ค่าบิต "และ" n&n-1เป็นศูนย์ว่าเมื่อเป็นอำนาจของn 2ถ้าเป็นเช่นนั้นเราได้รับรายการ[-n]และอื่น ๆ []รายการที่ว่างเปล่า สิ่งนี้ทำให้พลังทั้งหมดของ 2 ในตอนท้ายของคำสั่งในการลดคำสั่ง
  • ค่ารองจะn&-nแยกตัวประกอบกำลังของn2
  • ค่าสุดท้ายntiebreaks เท่ากับกำลังสองเท่ากับจำนวนที่มากกว่า

tuples นั้นจะส่งผ่านไปเพื่อดูว่าการเปรียบเทียบว่าเป็นcmp <=0งูหลาม 3 จะประหยัดไบต์ที่มีการแบ่งลอย(n&n-1<1)/nสำหรับค่าแรกในสาม cmpแต่ขาด


ไม่cmp(...)<=0เทียบเท่ากับcmp(...)<1?
mathmandan

@mathmandan ใช่ :)
xnor

ฉันคิดว่ามันอนุญาตให้ใช้จำนวนเต็มในลำดับย้อนกลับและใช้~แทน<1
Mitch Schwartz

4

JavaScript (ES6), 70 64 ไบต์

อาจจะเล่นกอล์ฟได้มากกว่านี้ แต่เป็นความพยายามครั้งแรก:

x=>y=>(a=x&-x,x/=a,b=y&-y,y/=b,y<2?x>1|b<=a:x>1&(b>a|b==a&y>=x))

(x)(y)จะเข้ากับไวยากรณ์ currying ผลตอบแทน/01

กรณีทดสอบ


คุณสามารถนำวงเล็บไปรอบ ๆ และข้างในb>a||(b==a&&y>=x)ไม่สร้างความแตกต่างให้กับการดำเนินการ
XavCo7

@ XavCo7 ไม่เป็นไรที่จะลบวงเล็บข้างในออก กรณีทดสอบที่มีอยู่ทั้งหมดจะยังคงผ่านไป แต่ข้อมูลเช่น[1, 5]จะระบุอย่างไม่ถูกต้องว่าเป็นความจริง
Arnauld

1
@Arnauld ฉันจะเพิ่มว่าเป็นกรณีทดสอบใหม่สำหรับอนาคต
Zgarb

3

Perl 6 , 89 84 ไบต์

->\a,\b{my \u=*>max a,b;a==first a|b,flat [1,2,4...u].&{(3*$_,5*$_...u for $_),.reverse}}

{my \u=*>@_.max;@_[0]==first @_.any,flat [1,2,4...u].&{.map(*X*(3,5...u)),.reverse}}

(ลองออนไลน์ )

ไม่สั้นอย่างแน่นอน แต่ฉันคิดว่ามันน่าสนใจที่จะเขียนวิธีแก้ปัญหาที่สร้างลำดับการสั่งซื้อ (ขึ้นอยู่กับขอบเขตบนที่ปลอดภัยสำหรับแต่ละลำดับย่อย) จากนั้นตรวจสอบอินพุตที่ปรากฏก่อน

ตัวอย่างเช่น:

  • สำหรับการป้อนข้อมูล2, 3มันสร้าง:

    3 5
    6
    12
    4 2 1
    ... และแล้วสังเกตว่าปรากฏขึ้นก่อน32

  • สำหรับการป้อนข้อมูล9, 6มันสร้าง:

    3 5 7 9 11
    6 10
    12
    24
    48
    16 8 4 2 1
    ... และแล้วสังเกตว่าปรากฏขึ้นก่อน96

มันอาจฉลาดกว่าและสร้างลำดับน้อยกว่า แต่ก็ต้องใช้รหัสไบต์เพิ่มขึ้น


2

Python 2, 54 ไบต์

f=lambda a,b:b<2or[f(a/2,b/2),a>1,0,1<a<=b][a%2+b%2*2]

โซลูชันแบบเรียกซ้ำคล้ายกับนีล


ดูเหมือนว่าจะทำให้กรณีทดสอบเกิดความสับสน มันบอกว่าf(158,158)เป็นเท็จและf(2,8)เป็นจริง
xnor

@xnor โอ๊ะโอควรได้รับการแก้ไขแล้ว
orlp

สิ่งนี้บอกว่าf(1,5)เป็นเท็จ
xnor

ไม่ดีของฉันฉันหมายความว่าf(1,5)ควรเป็นเท็จ แต่รหัสให้จริง
xnor

@xnor Ah ฉันเห็นข้อผิดพลาดได้รับการแก้ไขแล้ว (เพื่อความหวังดี) ฉันทำตามคำอธิบายของ Neil เล็กน้อยเกินไปคับ
orlp

1

Mathematica, 65 ไบต์

OrderedQ[{1,#}&/@#//.{a_,b_/;EvenQ@b}->{2a,b/2}/.{a_,1}->{∞,-a}]&

ฟังก์ชั่นที่ไม่ได้ตั้งชื่อใช้รายการของจำนวนเต็มบวกและส่งคืนTrueถ้ารายการเป็นลำดับจากน้อยไปมากในลำดับ Sharkovskii Falseมิฉะนั้น (โดยเฉพาะรายการอินพุตไม่จำเป็นต้องมีเพียงสององค์ประกอบ - เราได้รับฟังก์ชั่นเพิ่มฟรี)

หัวใจของอัลกอริธึมคือฟังก์ชั่น{1,#}&/@#//.{a_,b_/;EvenQ@b}->{2a,b/2}ซึ่งจะย้ายปัจจัย 2 รอบซ้ำ ๆ เพื่อแปลงจำนวนเต็มของฟอร์มm*2^kด้วยmคี่เป็นคู่ที่สั่ง{2^k,m}(และจะทำกับทุกองค์ประกอบของรายการอินพุต) OrderedQจากนั้นตัดสินใจว่ารายการผลลัพธ์ของคู่ที่สั่งซื้อจะถูกเรียงลำดับแล้วหรือไม่ โดยค่าเริ่มต้นนั่นหมายถึงในการสั่งซื้อที่เพิ่มขึ้นโดยองค์ประกอบแรกแล้วเพิ่มการสั่งซื้อโดยองค์ประกอบที่สอง

นั่นคือสิ่งที่เราต้องการยกเว้นตัวเลขที่มีอำนาจ 2 ตามกฎที่แตกต่างกัน ดังนั้นก่อนที่จะตรวจสอบด้วยOrderingQเราจะใช้กฎข้อสุดท้าย/.{a_,1}->{∞,-a}ที่แปลง (ตัวอย่าง) {64,1}เป็น{∞,-64}; ที่ทำให้พลังของ 2 ในจุดที่ถูกต้องในการสั่งซื้อ


0

Haskell, 143 138 ไบต์

โดยทั่วไปแล้วการใช้เกณฑ์ค่อนข้างง่าย

e n=head[k-1|k<-[0..],n`mod`(2^k)>0]   -- exponent of 2
f n=n`div`2^e n                        -- odd part
a#b|n<-f a,p<-e a,m<-f b,q<-e b=n>1&&(m>1&&p<q||n<m&&p==q||m<2)||n<2&&m<2&&p>q||a==b  

ลองออนไลน์!


0

Python, 159 158 153 144 142 141 ไบต์

ที่บันทึกไว้2 ไบต์ขอบคุณที่ Kritixi Lithos!

นี่เป็นเพียงการฝึกเล่น Python ของฉันเป็นหลัก!
ใช้สูตรที่กำหนดโดย OP แทนที่จะเป็นวิธีที่คำตอบที่ฉลาดกว่าทั้งหมด

f=lambda a,p=0:(a&1)*(a,p)or f(a>>1,p+1)
t=lambda(n,p),(m,q):(n==1)*(m==1)&(p>=q)or (m>1)&(p<=q)|(n<=m)&(p==q)or m==1
lambda a,b:t(f(a),f(b))

คุณสามารถกอล์ฟมันโดยการลบช่องว่างที่ไม่จำเป็น: ยกตัวอย่างเช่นในในบรรทัดที่สองที่คุณสามารถลบช่องว่างระหว่างเครื่องหมายจุลภาคและ(a, b) b
Kritixi Lithos
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.