กำลังโปรแกรม: O (1 ^ N), O (N ^ 1), O (2 ^ N), O (N ^ 2) ทั้งหมดในที่เดียว


65

เขียนโปรแกรม (หรือฟังก์ชั่น) ที่แสดงความซับซ้อนของเวลาO ขนาดใหญ่ สี่ทั่วไปขึ้นอยู่กับวิธีการทำงาน ในรูปแบบใดก็จะใช้เวลาในจำนวนเต็มบวก N ที่คุณอาจคิดน้อยกว่า 2 วันที่ 31

  1. เมื่อโปรแกรมทำงานในรูปแบบดั้งเดิมควรมีความซับซ้อนคงที่ นั่นคือความซับซ้อนควรจะΘ (1)หรือเท่ากันΘ (1 ^ N)

  2. เมื่อโปรแกรมกลับด้านและรันควรมีความซับซ้อนเชิงเส้น นั่นคือความซับซ้อนควรจะΘ (N)หรือเท่ากันΘ (N ^ 1)
    (สิ่งนี้สมเหตุสมผลเนื่องจากN^1มีการ1^Nย้อนกลับ)

  3. เมื่อโปรแกรมสองเท่า , ตัดแบ่งเช่นกับตัวเองและเรียกมันควรจะมีการชี้แจงความซับซ้อนโดยเฉพาะ2 N นั่นคือความซับซ้อนควรจะΘ (2 ^ N)
    (นี้ทำให้รู้สึกตั้งแต่2ใน2^Nเป็นสองเท่า1ใน1^N.)

  4. เมื่อโปรแกรมสองเท่าและย้อนกลับและเรียกมันควรจะมีพหุนามความซับซ้อนโดยเฉพาะN 2 นั่นคือความซับซ้อนควรจะΘ (N ^ 2)
    (สิ่งนี้สมเหตุสมผลเนื่องจากN^2มีการ2^Nย้อนกลับ)

สี่กรณีนี้เป็นกรณีเดียวที่คุณต้องจัดการ

โปรดทราบว่าเพื่อความแม่นยำฉันใช้สัญลักษณ์ขนาดใหญ่ที (Θ)แทนO ใหญ่เพราะรันไทม์ของโปรแกรมของคุณจะต้องล้อมรอบทั้งด้านบนและด้านล่างด้วยความซับซ้อนที่จำเป็น มิฉะนั้นเพียงแค่เขียนฟังก์ชั่นใน O (1) จะตอบสนองทั้งสี่จุด มันไม่สำคัญเกินไปที่จะเข้าใจความแตกต่างที่นี่ ส่วนใหญ่หากโปรแกรมของคุณกำลังดำเนินการ k * f (N) สำหรับค่าคงที่ k บางค่าอาจเป็นΘ (f (N))

ตัวอย่าง

ถ้าโปรแกรมเดิมถูก

ABCDE

จากนั้นเรียกใช้มันควรจะใช้เวลาคงที่ นั่นคือไม่ว่าอินพุต N เป็น 1 หรือ 2147483647 (2 31 -1) หรือค่าใด ๆ ที่อยู่ระหว่างนั้นควรจะสิ้นสุดลงในเวลาเท่ากัน

เวอร์ชันที่ตรงกันข้ามของโปรแกรม

EDCBA

ควรใช้เวลาเชิงเส้นในแง่ของ N นั่นคือเวลาที่ใช้ในการยุติควรเป็นสัดส่วนประมาณ N ดังนั้น N = 1 ใช้เวลาน้อยที่สุดและ N = 2147483647 ใช้เวลามากที่สุด

โปรแกรมเวอร์ชันสองเท่า

ABCDEABCDE

ควรใช้เวลาสอง-to--N ในแง่ของเอ็นนั่นคือเวลาที่ใช้ในการยุติควรจะเป็นสัดส่วนถึง 2 N ดังนั้นหาก N = 1 ยุติลงในเวลาประมาณหนึ่งวินาที N = 60 จะใช้เวลานานกว่าอายุของเอกภพที่จะยุติ (ไม่คุณไม่ต้องทดสอบ)

เวอร์ชันของโปรแกรมสองเท่าและกลับด้าน

EDCBAEDCBA

ควรใช้เวลายกกำลังสองในแง่ของ N นั่นคือเวลาที่ใช้ในการยุติควรเป็นสัดส่วนประมาณ N * N ดังนั้นหาก N = 1 ยุติลงในเวลาประมาณหนึ่งวินาที N = 60 จะใช้เวลาประมาณหนึ่งชั่วโมงในการยกเลิก

รายละเอียด

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

  • มันก็โอเคถ้าในทางปฏิบัติเวลาที่โปรแกรมของคุณไม่ได้แสดงถึงความซับซ้อนของมันอย่างสมบูรณ์ (หรือแม้แต่กำหนดขึ้น) เช่นอินพุต N + 1 บางครั้งอาจทำงานเร็วกว่า N

  • สภาพแวดล้อมที่คุณใช้งานโปรแกรมของคุณนั้นสำคัญ คุณสามารถตั้งสมมติฐานพื้นฐานว่าภาษายอดนิยมไม่เคยเสียเวลาในขั้นตอนวิธีอย่างไรตัวอย่างเช่นถ้าคุณรู้ว่า Java เวอร์ชันเฉพาะของคุณใช้การจัดเรียงฟองแทนที่จะเป็นอัลกอริทึมการเรียงลำดับที่เร็วขึ้นคุณควรคำนึงถึงเรื่องนั้นด้วย .

  • สำหรับความซับซ้อนทั้งหมดที่นี่สมมติว่าเรากำลังพูดถึงสถานการณ์กรณีที่เลวร้ายที่สุดไม่ใช่กรณีที่ดีที่สุดหรือกรณีเฉลี่ย

  • ความซับซ้อนของพื้นที่ของโปรแกรมไม่สำคัญเพียงความซับซ้อนของเวลาเท่านั้น

  • โปรแกรมอาจแสดงผลอะไรก็ได้ มันสำคัญแค่ว่าพวกมันใช้จำนวนเต็มบวก N และมีความซับซ้อนของเวลาที่ถูกต้อง

  • อนุญาตให้แสดงความคิดเห็นและโปรแกรมหลายบรรทัดได้ (คุณอาจสันนิษฐานว่า\r\nตรงกันข้าม\r\nสำหรับความเข้ากันได้กับ Windows)

การแจ้งเตือน Big O

ตั้งแต่เร็วที่สุดไปจนถึงช้าที่สุดO(1), O(N), O(N^2), O(2^N)(สั่งซื้อ 1, 2, 4, 3 ด้านบน)

O(2^N + N^2 + N) = O(2^N)แง่ช้าเสมอครองเช่น

O(k*f(N)) = O(f(N))สำหรับค่าคงที่ k ดังนั้นและO(2) = O(30) = O(1)O(2*N) = O(0.1*N) = O(N)

โปรดจำไว้และO(N^2) != O(N^3)O(2^N) != O(3^N)

แผ่นชีท O ขนาดใหญ่เรียบร้อย

เกณฑ์การให้คะแนน

นี่คือรหัสกอล์ฟปกติ โปรแกรมดั้งเดิมที่สั้นที่สุด (เวลาหนึ่งคงที่) เป็นไบต์ชนะ


คำถามยอดเยี่ยม! จุดรอง: เราไม่ต้องระบุตัวพิมพ์ที่แย่ที่สุด / กรณีที่ดีที่สุด / ค่าเฉลี่ยเนื่องจากอินพุตเดียวที่นับเป็นขนาด N คือตัวเลข N เอง (ซึ่ง BTW ไม่ใช่ความคิดปกติของขนาดอินพุต: ที่จะ ปฏิบัติต่ออินพุต N ว่าเป็นขนาดบันทึก N) ดังนั้นมีเพียงกรณีเดียวสำหรับแต่ละ N ซึ่งเป็นกรณีที่ดีที่สุดเลวร้ายที่สุดและโดยเฉลี่ย
ShreevatsaR

5
ดูเหมือนว่าคุณเบี่ยงเบนไปจากคำจำกัดความความซับซ้อนตามปกติ เรามักจะกำหนดเวลาซับซ้อนของอัลกอริทึมเป็นหน้าที่ของขนาดของการป้อนข้อมูลของตน ในกรณีที่อินพุตเป็นตัวเลขขนาดของอินพุตคือลอการิทึมฐาน 2 ของหมายเลขนั้น ดังนั้นโปรแกรมn = input(); for i in xrange(n): passจึงมีความซับซ้อนแบบเอกซ์โพเนนเชียลเพราะมัน2 ** kทำตามขั้นตอนซึ่งk = log_2(n)เป็นขนาดอินพุต คุณควรชี้แจงว่าเป็นกรณีนี้หรือไม่เนื่องจากมีการเปลี่ยนแปลงข้อกำหนดอย่างมาก
wchargin

คำตอบ:


36

Python 3 , 102 ไบต์

try:l=eval(input());k=1#)]0[*k**l(tnirp
except:k=2#2=k:tpecxe
print(k**l*[0])#1=k;))(tupni(lave=l:yrt

ลองออนไลน์!

นี่คือ O (1 ^ n) เนื่องจากนี่คือสิ่งที่โปรแกรมทำ:

  • ประเมินอินพุต
  • สร้างอาร์เรย์ [0]
  • พิมพ์มัน

ย้อนกลับ


try:l=eval(input());k=1#)]0[*l**k(tnirp
except:k=2#2=k:tpecxe
print(l**k*[0])#1=k;))(tupni(lave=l:yrt

ลองออนไลน์!

นี่คือ O (n ^ 1) เนื่องจากนี่คือสิ่งที่โปรแกรมทำ:

  • ประเมินอินพุต
  • สร้างอาร์เรย์ [0] * อินพุต (0 ซ้ำหลาย ๆ ครั้งเป็นอินพุต)
  • พิมพ์มัน

สองเท่า

try:l=eval(input());k=1#)]0[*k**l(tnirp
except:k=2#2=k:tpecxe
print(k**l*[0])#1=k;))(tupni(lave=l:yrt
try:l=eval(input());k=1#)]0[*k**l(tnirp
except:k=2#2=k:tpecxe
print(k**l*[0])#1=k;))(tupni(lave=l:yrt

ลองออนไลน์!

นี่คือ O (2 ^ n) เนื่องจากนี่คือสิ่งที่โปรแกรมทำ:

  • ประเมินอินพุต
  • สร้างอาร์เรย์ [0]
  • พิมพ์มัน
  • พยายามประเมินอินพุต
  • ล้มเหลว
  • สร้างอาร์เรย์ [0] * (อินพุต 2 ^) (0 ซ้ำหลาย ๆ ครั้งเป็น 2 ^ อินพุต)
  • พิมพ์มัน

สองเท่าและกลับรายการ:


try:l=eval(input());k=1#)]0[*l**k(tnirp
except:k=2#2=k:tpecxe
print(l**k*[0])#1=k;))(tupni(lave=l:yrt
try:l=eval(input());k=1#)]0[*l**k(tnirp
except:k=2#2=k:tpecxe
print(l**k*[0])#1=k;))(tupni(lave=l:yrt

ลองออนไลน์!

นี่คือ O (n ^ 2) เนื่องจากนี่คือสิ่งที่โปรแกรมทำ:

  • ประเมินอินพุต
  • สร้างอาร์เรย์ [0] * อินพุต (0 ซ้ำหลาย ๆ ครั้งเป็นอินพุต)
  • พิมพ์มัน
  • พยายามประเมินอินพุต
  • ล้มเหลว
  • สร้างอาร์เรย์ [0] * (อินพุต ^ 2) (0 ซ้ำหลาย ๆ ครั้งเมื่ออินพุตกำลังสอง)
  • พิมพ์มัน

มันไม่ทำไมไม่แขวนรอการโต้ตอบกับผู้ใช้เมื่อมีหลายสายเพื่อinput()?
Jonathan Allan

1
เป็นช่องโหว่ที่ "สิ้นสุดการส่งสัญญาณ" ถูกส่งเมื่อสิ้นสุดการส่งหรือไม่
Leun Nun

1
คุณอธิบายได้ไหม
Brain Guider

1
Re: อาร์กิวเมนต์ "จุดสิ้นสุดไฟล์" คุณกำลังมองสิ่งต่าง ๆ ย้อนหลัง เมื่อคุณใช้เทอร์มินัลคำขอให้ป้อนข้อมูลหยุดทำงานเนื่องจากมีบางสิ่งเชื่อมต่ออยู่ ctrl-D สามารถส่งเพื่อส่งอินพุตอย่างไม่ชัดเจน หากอินพุตถูกเชื่อมต่อกับไฟล์ว่างเปล่า (เช่น TIO จะทำอย่างไรถ้าคุณปล่อยให้กล่องอินพุตว่างเปล่า) หรือถ้ามันเชื่อมต่อกับไฟล์ที่อินพุตทั้งหมดถูกอ่านแล้วคุณไม่จำเป็นต้องขอให้อินพุตทำอะไร มันรู้อยู่แล้วว่าไม่มีการป้อนข้อมูล บน UNIX / Linux "จุดสิ้นสุดไฟล์" และ "ไม่มีอินพุต" จะไม่สามารถแยกแยะได้ในไฟล์ปกติ

3
สำหรับกรณีแรกkคืออินพุตและlเป็นหนึ่งดังนั้นคุณยังคงคำนวณ1**kใช่ไหม สิ่งใดควรใช้O(log(k))เวลาแม้จะมีความจริงที่ว่าคุณและฉันและทุกคนรู้ล่วงหน้าว่าเป็นสิ่งนั้น
Richard Rast

18

Perl 5, 82 73 71 + 1 (สำหรับแฟล็ก -n) = 72 ไบต์

ฉันแน่ใจว่าฉันสามารถเล่นกอล์ฟนี้ได้มากขึ้น แต่ถึงเวลานอนฉันได้ใช้เวลาในการดีบั๊กมากพอแล้วและฉันก็ภูมิใจในสิ่งที่ฉันมี

#x$=_$;
$x.=q;#say for(1..2**$_)#)_$..1(rof _$=+x$;;
eval $x;$x=~s/#//;

ตัวโปรแกรมเองไม่ได้ใช้อินพุตและเพียงประเมินสตริงที่ขึ้นต้นด้วยความคิดเห็นจากนั้นทำการแทนที่สตริงเดี่ยวดังนั้นนี่จึงเป็นเวลาที่ชัดเจน โดยพื้นฐานแล้วเทียบเท่ากับ:

$x="#";
eval $x;
$x=~s/#//;

สองเท่า

#x$=_$;
$x.=q;#say for(1..2**$_)#)_$..1(rof _$=+x$;;
eval $x;$x=~s/#//;
#x$=_$;
$x.=q;#say for(1..2**$_)#)_$..1(rof _$=+x$;;
eval $x;$x=~s/#//;

บิตที่ใช้เวลาเอ็กซ์โพเนนเชียลคือ eval ตัวที่สอง: ประเมินค่าคำสั่งsay for(1..2**$_)ซึ่งแสดงรายการหมายเลขทั้งหมดตั้งแต่ 1 ถึง 2 ^ N ซึ่งใช้เวลาอย่างชัดเจน

ย้อนกลับ

;//#/s~=x$;x$ lave
;;$x+=$_ for(1..$_)#)_$**2..1(rof yas#;q=.x$
;$_=$x#

นี้ (ไร้เดียงสา) คำนวณผลรวมของอินพุตซึ่งใช้เวลาเชิงเส้นอย่างชัดเจน (เนื่องจากการเพิ่มแต่ละครั้งอยู่ในเวลาคงที่) รหัสที่ได้รับจริงรันเทียบเท่ากับ:

$x+=$_ for(1..$_);
$_=$x;

บรรทัดสุดท้ายเป็นเพียงเพื่อว่าเมื่อคำสั่งเหล่านี้ซ้ำแล้วซ้ำอีกมันจะใช้เวลากำลังสอง

ย้อนกลับและเป็นสองเท่า:

;//#/s~=x$;x$ lave
;;$x+=$_ for(1..$_)#)_$**2..1(rof yas#;q=.x$
;$_=$x#
;//#/s~=x$;x$ lave
;;$x+=$_ for(1..$_)#)_$**2..1(rof yas#;q=.x$
;$_=$x#

ตอนนี้ใช้การรวมยอดรวมของอินพุต (และเพิ่มลงในยอดรวมของอินพุต แต่ไม่รวมอะไร) เนื่องจากมันจะN^2เพิ่มคำสั่งนี้ใช้เวลากำลังสอง โดยพื้นฐานแล้วเทียบเท่ากับ:

$x=0;
$x+=$_ for(1..$_);
$_=$x;
$x+=$_ for(1..$_);
$_=$x;

บรรทัดที่สองพบว่าผลรวมของการป้อนข้อมูลการทำNเพิ่มเติมในขณะที่สี่ไม่เพิ่มเติมซึ่งเป็นsummation(N)O(N^2)


ที่ดี! การทำเช่นนั้นในภาษากระแสหลักคงเป็นเรื่องยาก! นี่คือ upvote ของฉัน!
Arjun

ทำได้ดีนี่มันค่อนข้างดี คุณอาจหมายถึง$x.=q;##say...แทนที่จะเป็น$x.=q;#say...(ด้วยสอง#แทน 1) (นั่นจะอธิบายว่าทำไมคุณนับ 76 ไบต์แทน 75) นอกจากนี้คุณควรนับการ-nตั้งค่าสถานะเป็นจำนวนของคุณเนื่องจากโปรแกรมของคุณไม่ได้ทำอะไรมากหากไม่มี
Dada

@Dada ฉัน transposed โดยบังเอิญevalและs///คำสั่ง ถ้าคุณทำครั้งแรกที่คุณจะต้องหนึ่งeval #จับดี!
Chris

@ Chris ขวามันใช้งานได้จริง คุณอาจจะสามารถที่จะละเว้นสุดท้าย#: $x=~s/#//;ย้อนกลับไปผลิตซึ่งในบริบทของคุณไม่ทำอะไรเลยในขณะที่มันจะมีชั้นนำ;//#/s~=x$ #(ฉันยังไม่ได้ทดสอบ) ไม่ว่าจะมี +1!
Dada

@ ดาดาดีจับอีกครั้ง!
Chris

17

ที่จริงแล้ว 20 ไบต์

";(1╖╜ⁿr"ƒ"rⁿ@╜╖1(;"

ลองออนไลน์!

การป้อนข้อมูล: 5

เอาท์พุท:

rⁿ@╜╖1(;
[0]
5

ย้อนกลับ

";(1╖╜@ⁿr"ƒ"rⁿ╜╖1(;"

ลองออนไลน์!

เอาท์พุท:

rⁿ╜╖1(;
[0, 1, 2, 3, 4]
5

สองเท่า

";(1╖╜ⁿr"ƒ"rⁿ@╜╖1(;"";(1╖╜ⁿr"ƒ"rⁿ@╜╖1(;"

ลองออนไลน์!

เอาท์พุท:

rⁿ@╜╖1(;
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
rⁿ@╜╖1(;
rⁿ@╜╖1(;
[0]

สองเท่าและกลับรายการ:

";(1╖╜@ⁿr"ƒ"rⁿ╜╖1(;"";(1╖╜@ⁿr"ƒ"rⁿ╜╖1(;"

ลองออนไลน์!

เอาท์พุท:

rⁿ╜╖1(;
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]
rⁿ╜╖1(;
rⁿ╜╖1(;
[0, 1, 2, 3, 4]

แนวคิดหลัก

จริง ๆ แล้วเป็นภาษาที่ใช้กองซ้อน

  • abcเป็นโปรแกรมที่มีความซับซ้อนO (1 n ) และ double ของมันมีความซับซ้อนO (2 n )
  • defเป็นโปรแกรมที่มีความซับซ้อนO (n 1 ) และสองของมันมีความซับซ้อนO (n 2 )

จากนั้นการส่งของฉันคือ"abc"ƒ"fed"ที่การƒประเมิน ด้วยวิธีนี้"fed"จะไม่ถูกประเมิน

การสร้างโปรแกรมเฉพาะบุคคล

รหัสเทียมขององค์ประกอบแรก;(1╖╜ⁿr:

register += 1 # register is default 0
print(range(register**input))

pseudocode ขององค์ประกอบที่สอง;(1╖╜ⁿ@r:

register += 1 # register is default 0
print(range(input**register))

ฉันไม่เคยคิดเลยว่ามันจะเป็นไปได้! เยี่ยมมากครับ! +1
อาร์จัน

@Arjun ขอบคุณสำหรับความชื่นชมของคุณ
Leun Nun

นี่เป็นสิ่งที่ยอดเยี่ยมและเพิ่มขึ้นอย่างแท้จริงต่อความท้าทายโดยไม่ใช้ความคิดเห็น IMO น่ากลัว!
ShreevatsaR

1
อย่างนี้จริงมีความคิดเห็น ... สตริงที่มี unevaluated และ nops ...
รั่วนูน

4

เยลลี่ , 20 ไบต์

แรงบันดาลใจบางส่วนจากการรั่วของแม่ชีแก้ปัญหาจริง

ขึ้นบรรทัดใหม่ชั้นนำและต่อท้ายมีความสำคัญ

ปกติ:


⁵Ŀ⁵
R
R²
2*R
‘
⁵Ŀ⁵

ลองออนไลน์!

การป้อนข้อมูล: 5

เอาท์พุท:

610

ย้อนกลับ


⁵Ŀ⁵
‘
R*2
²R
R
⁵Ŀ⁵

ลองออนไลน์!

การป้อนข้อมูล: 5

เอาท์พุท:

[1, 2, 3, 4, 5]10

สองเท่า


⁵Ŀ⁵
R
R²
2*R
‘
⁵Ŀ⁵

⁵Ŀ⁵
R
R²
2*R
‘
⁵Ŀ⁵

ลองออนไลน์!

การป้อนข้อมูล: 5

เอาท์พุท:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]10

เพิ่มเป็นสองเท่าและกลับรายการ


⁵Ŀ⁵
‘
R*2
²R
R
⁵Ŀ⁵

⁵Ŀ⁵
‘
R*2
²R
R
⁵Ŀ⁵

ลองออนไลน์!

การป้อนข้อมูล: 5

เอาท์พุท:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]10

คำอธิบาย

กุญแจอยู่ตรงนี้Ŀซึ่งหมายความว่า "เรียกลิงค์ที่ index n เป็น monad" ลิงก์จะถูกจัดทำดัชนีจากบนลงล่างเริ่มต้นที่ 1 ยกเว้นลิงค์หลัก (ล่างสุด) Ŀเป็นแบบแยกส่วนเช่นกันดังนั้นหากคุณพยายามโทรไปยังลิงค์หมายเลข 7 จาก 5 ลิงก์คุณจะเรียกลิงก์ 2 จริง ๆ

ลิงก์ที่ถูกเรียกในโปรแกรมนี้จะเป็นลิงค์ที่ดัชนี 10 ( ) ไม่ว่าจะเป็นเวอร์ชั่นใดของโปรแกรม อย่างไรก็ตามลิงค์ใดอยู่ที่ดัชนี 10 ขึ้นอยู่กับเวอร์ชัน

สิ่งที่ปรากฏหลังจากแต่ละรายการĿอยู่ที่นั่นจึงไม่แตกเมื่อกลับด้าน Ŀโปรแกรมจะเกิดข้อผิดพลาดออกที่แยกเวลาถ้ามีเป็นจำนวนก่อนที่จะไม่มี มีหลังจากมันเป็น nilad นอกสถานที่ซึ่งเพิ่งตรงไปที่ผลลัพธ์

เวอร์ชันดั้งเดิมเรียกลิงก์ซึ่งคำนวณ n + 1

เวอร์ชันที่กลับด้านเรียกลิงก์Rซึ่งสร้างช่วง 1 .. n

รุ่นสองเท่าเรียกการเชื่อมโยง2*Rซึ่งคำนวณ 2 nและสร้างช่วง 1 .. 2 n

สองเท่าและตรงกันข้ามรุ่นเรียกการเชื่อมโยง²Rซึ่งคำนวณ n 2และสร้างช่วง 1 .. n 2


4

Befunge-98 , 50 ไบต์

ปกติ

\+]#:\-1vk  !:;#
@k!:-1 .: ;#]#$ <;
[*:>@ 
&$< ^&;

นี่เป็นโปรแกรมที่ง่ายที่สุดของ 4 - คำสั่งเดียวที่ถูกเรียกใช้มีดังต่อไปนี้:

\+]
  !
  : @
&$< ^&;

โปรแกรมนี้ทำสิ่งที่ไม่เกี่ยวข้องก่อนที่จะกดคำสั่ง "เลี้ยวขวา" ( ]) และลูกศร จากนั้นก็จะฮิต2 "ใช้การป้อนข้อมูล" คำสั่ง เนื่องจากมีอินพุตเพียง 1 หมายเลขและเนื่องจากวิธีการที่ TIO ปฏิบัติต่อ&โปรแกรมจึงออกหลังจาก 60 วินาที หากมี 2 อินพุต (และเพราะฉันทำได้โดยไม่ต้องเพิ่มไบต์) IP จะเดินทางไปยังฟังก์ชัน "โปรแกรมสิ้นสุด"

ลองออนไลน์!

ย้อนกลับ

;&^ <$&
 @>:*[
;< $#]#; :. 1-:!k@
#;:!  kv1-\:#]+\

อันนี้ซับซ้อนกว่าเล็กน้อย คำสั่งที่เกี่ยวข้องมีดังนี้:

;&^  $
  >:*[
;< $#]#; :. 1-:!k@
  :

ซึ่งเทียบเท่ากับ

;&^                   Takes input and sends the IP up. the ; is a no-op
  :                   Duplicates the input.
  >:*[                Duplicates and multiplies, so that the stack is [N, N^2
     $                Drops the top of the stack, so that the top is N
     ]#;              Turns right, into the loop
         :.           Prints, because we have space and it's nice to do
            1-        Subtracts 1 from N
              :!k@    If (N=0), end the program. This is repeated until N=0
;< $#]#;              This bit is skipped on a loop because of the ;s, which comment out things

ส่วนที่สำคัญที่นี่คือ:. 1-:!k@บิต มันมีประโยชน์เพราะตราบใดที่เราผลักความซับซ้อนที่ถูกต้องไปยังสแต็กก่อนที่จะดำเนินการในเวลาที่ซับซ้อนน้อยกว่าเราจะได้สิ่งที่ต้องการ สิ่งนี้จะถูกใช้ใน 2 โปรแกรมที่เหลือด้วยวิธีนี้

ลองออนไลน์!

สองเท่า

\+]#:\-1vk  !:;#
@k!:-1 .: ;#]#$ <;
[*:>@ 
&$< ^&;\+]#:\-1vk  !:;#
@k!:-1 .: ;#]#$ <;
[*:>@ 
&$< ^&;

และคำสั่งที่เกี่ยวข้องคือ:

\+]
  !
  :
&$< ^&;\+]#:\-1vk  !:;#
@k!:-1 .: ;#]#$ <;

โปรแกรมนี้แบ่งเป็น 2 ลูป อย่างแรกมันเป็นไปตามเส้นทางเดียวกับโปรแกรมปกติซึ่งจะผลัก 1 และ N ไปยังสแต็ก แต่แทนที่จะล้อมรอบไปที่สอง&IP จะข้ามความคิดเห็นไปที่ลูปที่กด2^N:

        vk!:    If N is 0, go to the next loop.
      -1        Subtract 1 from N
 +  :\          Pulls the 1 up to the top of the stack and doubles it
  ]#            A no-op
\               Pulls N-1 to the top again

บิตอื่น ๆ ในบรรทัด 4 ถูกข้ามโดยใช้;s

หลังจาก (2 ^ N) ถูกผลักลงบนสแต็กเราจะย้ายบรรทัดลงในลูปการพิมพ์ที่กล่าวมาข้างต้น เนื่องจากการวนซ้ำครั้งแรกความซับซ้อนของเวลาคือΘ (N + 2 ^ N) แต่ลดลงเป็นΘ (2 ^ N)

ลองออนไลน์!

เพิ่มเป็นสองเท่าและกลับรายการ

;&^ <$&
 @>:*[
;< $#]#; :. 1-:!k@
#;:!  kv1-\:#]+\;&^ <$&
 @>:*[
;< $#]#; :. 1-:!k@
#;:!  kv1-\:#]+\

คำสั่งที่เกี่ยวข้อง:

;&^

;< $#]#; :. 1-:!k@

 @>:*[

  :

ฟังก์ชั่นนี้เกือบเหมือนกันกับโปรแกรมที่กลับด้าน แต่N^2ไม่ได้ถูกแตกออกจากสแต็กเพราะบรรทัดแรกของสำเนาที่สองของโปรแกรมจะถูกผนวกเข้ากับบรรทัดสุดท้ายของบรรทัดแรกซึ่งหมายความว่าคำสั่งปล่อย ( $) ไม่เคยถูกดำเนินการ ดังนั้นเราจึงเข้าไปในลูปการพิมพ์N^2ที่ด้านบนสุดของสแต็ก

ลองออนไลน์!

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