ประเมิน hyperoperation ที่ n


12

ฉันรู้ว่านี่เป็นคณิตศาสตร์ -y แต่ - ไปแล้ว

ในคณิตศาสตร์ลำดับ hyperoperation เป็นลำดับที่ไม่มีที่สิ้นสุดของการดำเนินการทางคณิตศาสตร์ (เรียกว่า hyperoperations) ที่เริ่มต้นด้วยการดำเนินการ unary ของผู้สืบทอดจากนั้นดำเนินการกับการดำเนินการแบบไบนารีของการบวกการคูณและการยกกำลังหลังจากที่ลำดับการดำเนินการเพิ่มเติม การยกกำลังโดยใช้การเชื่อมโยงทางขวา

เป้าหมายของคุณคือการเขียนโปรแกรมที่ใช้จำนวนเต็มสามจำนวน x, y และ n เป็นอินพุทและเอาท์พุทผลลัพธ์ของการไฮเปอร์พอยต์ที่ n บน x และ y

เช่น

1 1 1 เอาท์พุท 2

2 4 4 ผลลัพธ์ 65536

3 3 4 เอาต์พุต 7625597484987

  • โปรแกรมจะต้องเขียนด้วยรหัสที่สั้นที่สุด
  • คุณสามารถรับอินพุตจากSTDINหรือจากไฟล์
  • ฟังก์ชั่นห้องสมุดไม่ได้รับอนุญาต
  • ข้อ จำกัด การป้อนข้อมูล: n จะเป็น≥ 1

http://en.wikipedia.org/wiki/Tetrationมีคำอธิบายที่ดีในกรณีที่คุณไม่สามารถคาดหัวเรื่องนี้ได้


คือn=1อะไร ถ้ามันx+yหรือx+1, 1 1 1ควรกลับ2
จอห์น Dvorak

ฉันรู้ว่าฉันทำผิดพลาดที่ไหนสักแห่ง :) แก้ไขแล้วขอบคุณ
Soham Chowdhury

1
ฉันเขียนโค้ดหลอกให้ฉันจากนั้นฉันก็รู้ว่าจริงๆแล้วมันเป็นรหัสทับทิมที่ถูกต้อง (เกือบ :-()
John Dvorak

1
ไม่ n> = 1 เท่านั้น
Soham Chowdhury

คำตอบ:


4

ทับทิมช้า 86 84 83 ตัวอักษร

def f x,y,n
n>1?(c=x;2.upto(y){c=f(x,c,n-1)};c):x+y
end
p f *gets.split.map(&:to_i)

ทับทิมเร็ว 96 94 93 ตัวอักษร

def f x,y,n
n>1?(n>2?(c=x;2.upto(y){c=f(x,c,n-1)};c):x*y):x+y
end
p f *gets.split.map(&:to_i)

รุ่นแรกเป็นวิธีที่ช้าเกินไปกับกรณีทดสอบที่ผ่านมาดังนั้นฉันเพิ่มรุ่นที่ใช้คูณเป็นกรณีฐานแทนนอกจากนี้ รุ่นแรกใช้เวลานานในการคำนวณ3 3 4; อันที่สองนั้นเป็นแบบทันทีทันใด (ใน IRB console ดั้งเดิม; เวอร์ชั่นของเว็บช้าลงเล็กน้อย)

มีความงามของทับทิมอยู่มากมายที่นี่:

เกือบทุกคำพูดคือการแสดงออกในทับทิม ดังนั้นคุณสามารถเก็บเครื่องหมายอัฒภาคไว้ในตัวดำเนินการแบบไตรภาคได้หากคุณมีวงเล็บอยู่พอ กาแฟที่ยืมมานั้น นอกจากนี้ยังได้ยืมไวยากรณ์การโทร "ไม่จำเป็นต้องมี" ของรูบี้

ผลตอบแทนโดยนัย: นี่คือคุณสมบัติที่ยอดเยี่ยมและติดตามจากก่อนหน้านี้ อันที่จริงการเริ่มต้นบรรทัดสุดท้ายของฟังก์ชั่นด้วยreturnถือเป็นง่อยแม้ว่าจะไม่เล่นกอล์ฟ

ตัวเลขเป็นวัตถุในทับทิม (แม้nullเป็นวัตถุ) ใน ruby ​​จำนวนเต็มมีเมธอดtimesซึ่งประมวลผลบล็อกที่ส่งผ่านไปหลายครั้ง นี่เป็นเพียงหนึ่งในวิธีการวนซ้ำของ Ruby ที่นี่uptoวิธีการช่วยให้เราประหยัดสองตัวละครมากกว่าสิ่งที่timesช่วยให้เรา

unary *เป็นตัวดำเนินการสีแดงที่นี่ มันเปลี่ยนอาร์เรย์เป็นรายการอาร์กิวเมนต์ เช่นเดียวกับ Javascript Function#applyแต่มันสั้นกว่าและดีกว่า

unary &เปลี่ยนโพรซีเดอร์เป็นบล็อก ในขณะที่:to_iเป็นสัญลักษณ์มันแปลงเป็นขั้นตอนค่อนข้างดี กล่าวคือเปลี่ยนเป็นโพรซีเดอร์ที่เรียกto_iใช้อาร์กิวเมนต์และส่งคืนผลลัพธ์ ข้อมูลเพิ่มเติมเกี่ยวกับ Stack Overflow

มันเป็นไปได้ที่จะทำให้เร็วขึ้นโดยใช้n=3เป็นเคสพื้นฐาน แต่ฉันเกรงว่ามันไม่จำเป็น มันจะเสียค่าใช้จ่าย 11 ตัว แต่ต้องขอบคุณความงามของทับทิมอื่น: **ผู้ประกอบการยกกำลัง Python มีตัวดำเนินการนี้ แต่ไม่ใช่ตัวแรก (ตามที่ @ aka.nice สังเกต - ขอบคุณ - Fortran มีตัวดำเนินการนี้อยู่แล้ว)

ล่ามทับทิมออนไลน์มีให้ที่นี่: http://repl.it/Ikj/1


เยี่ยมมาก แต่ฉันยังรอผลจาก3 3 4:) มันช้ามาก
Soham Chowdhury

@ShaamChowdhury กรณีฐานเป็นบวก ด้วยกรณีพื้นฐานของการคูณมันจะช้ามากเช่นกัน (และอีกต่อไป) ฉันแนะนำให้ทดสอบด้วยการยกกำลังแทน ;-)
John Dvorak

มันอาจจะประหยัดเวลากับการใช้ memoization แต่ที่จะเสียค่าใช้จ่ายบางส่วนไบต์ (ค่อนข้างน้อย)
จอห์น Dvorak

เพิ่มเวอร์ชันอื่นแล้ว :)
Soham Chowdhury

1
โอเปอเรเตอร์ที่มีอยู่ใน FORTRAN ในยุค 50 และ ALGOL แล้วจะมีตัวอักษรน้อยลง 1 ตัวพร้อมลูกศรขึ้น
aka.nice

6

APL, 62

{1=3⌷⍵:2⌷+\⍵⋄0=2⌷⍵:(⍵[3]⌊3)⌷⍵[1],0,1⋄∇⍵[1],(∇⍵-0 1 0),3⌷⍵-1}⎕

{...}⎕: ใช้อินพุตที่ได้รับการประเมิน (ตัวเลขที่คั่นด้วยช่องว่างจะประเมินเป็นอาร์เรย์ตัวเลข) และใช้ฟังก์ชันกับมัน

1=3⌷⍵:: ถ้า n เท่ากับ 1 ...
2⌷+\⍵: ส่งคืนผลรวมขององค์ประกอบ 2 รายการแรก (x + y) ...
⋄0=2⌷⍵:: มิเช่นนั้นถ้า y เท่ากับ 0 ...
(⍵[3]⌊3)⌷⍵[1],0,1: สร้างอาร์เรย์ตัวเลข [x, 0,1] และดัชนีส่งคืนmin(n,3)...
⋄∇⍵[1],(∇⍵-0 1 0),3⌷⍵-1: ผลตอบแทนอื่น∇ (x, ∇ (x, y-1, n), n-1) (∇เป็นการอ้างอิงตนเอง)


ฉันได้รับโอเปอเรเตอร์ "ตัวรับสัญญาณมากเกินไป" ซึ่งรับฟังก์ชั่นและกลับมาไฮเปอร์เพตชันถัดไป

{⍺⍺/⊃⍴/⌽⍵}

ตัวอย่างเช่น+{⍺⍺/⊃⍴/⌽⍵}จะเป็นฟังก์ชันการคูณและ+{⍺⍺/⊃⍴/⌽⍵}5 3เอาต์พุต 15

แต่ไม่สามารถรับเงินคืนได้ บางทีคนอื่นสามารถทำได้


อ๊ะ APL เอาชนะ Python เพื่อความเรียบง่ายทุกวัน </sarcasm> ฉันจะรันสิ่งนี้ได้อย่างไร
Soham Chowdhury

2

Python 83

(ขึ้นอยู่กับคำตอบของ flornquake )

def h(x,y,n):r=n>2;exec"r=h(x,r,n-1);"*y*(n>1);return(x+y,r)[n>1]
print h(*input())

ช้ามากสำหรับผลลัพธ์ที่มีขนาดใหญ่

สำหรับการส่งออกเป็น2, 4, 465536


"ช้ามาก" เป็นเหตุผลที่โซลูชันตัวละคร 86 ตัวของฉันถือว่าไม่ดี
John Dvorak

1
@JanDvorak: ทำไมคุณคิดว่ามันไม่ดี? Soham Chowdhury เพิ่งบอกว่ามันช้าและคุณควรเพิ่มเวอร์ชั่นอื่นไม่ใช่เพื่อแทนที่โซลูชันของคุณ (แต่ฉันอาจเข้าใจผิดไป)
Reinstate Monica

คุณถูก; กู้คืนเวอร์ชั่นสั้น ตอนนี้ฉันเป็นคนชานานกว่าคุณ
John Dvorak

@ Wolfram แน่นอน ดีเสมอที่มีรุ่น
Soham Chowdhury


2

Golfscript, ช้า, 39 ตัวอักษร

 ~{\(.{3${[4$\2$4$.~}4$(*}{;;+}if])\;}.~

(ลิงค์สด)

นี่เป็นอัลกอริทึมแบบเรียกซ้ำมาตรฐานพร้อมตัวเรือนฐาน n = 1 (เพิ่มเติม) (เช่นช้า) เช่นเดียวกับที่ฉันเคยใช้ในโซลูชันทับทิมของฉัน

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

~{            #read the input and do (x y n f)
 \(.{         #(x y f n-1); if(n-1)
  3${         #(x y f n-1 c)
   4$\2$4$.~  #(x y f n-1 x c n-1 f); call
  }3$(*       #y-1 times
  {\;}4*
 }{           #else
  ;;+         #return (x+y)
 }if
}.~           #once

~เป็นตัวดำเนินการ eval ในกรณีของสตริงมันถือว่าสตริงเป็นโปรแกรม GolfScript โชคดีที่รายการจำนวนเต็มที่คั่นด้วยช่องว่างเป็นโปรแกรม GolfScript ที่ถูกต้องซึ่งจะผลักจำนวนเต็มเหล่านั้นลงบนสแต็ก เมื่อเทียบกับสิ่งนี้ชุดคำสั่งอินพุตรุ่นก่อนหน้าของฉัน ( " "/{~}/แยกตามช่องว่างและ Eval แต่ละอัน) ค่อนข้างง่อย ในกรณีของฟังก์ชั่นมันเรียกฟังก์ชั่น เมื่อนำหน้าด้วย.(โคลน) ฟังก์ชันจะเรียกใช้ฟังก์ชันด้วยตัวเองเป็นอาร์กิวเมนต์แรก

Golfscript ดูเหมือนจะไม่เหมาะอย่างยิ่งสำหรับการทำอัลกอริทึมแบบเรียกซ้ำ หากคุณต้องการอัลกอริทึมแบบเรียกซ้ำที่ไม่เหมาะสำหรับการโทรแบบหางคุณต้องสร้างและทำลายเฟรมสแต็กเพื่อรักษาตัวแปรของคุณ ในภาษาส่วนใหญ่จะดำเนินการโดยอัตโนมัติ ใน golfscript คุณต้องทำการโคลนตัวแปร (จริง ๆ แล้วคือรายการสแต็ค) และทำลายรายการสแต็กที่คุณไม่ต้องการอีกต่อไป Golfscript ไม่มีแนวคิดของเฟรมสแต็ก ฉันเคยบอกว่า GolfScript เป็นภาษาสแต็กหรือไม่?

ข้อกำหนดแรกเข้าใจได้ คุณต้องระบุข้อโต้แย้งอย่างใด เป็นเรื่องดีถ้าพวกเขารักษาตำแหน่งเดิมไว้ ข้อกำหนดที่สองนั้นโชคไม่ดีโดยเฉพาะอย่างยิ่งเนื่องจากค่าส่งคืนอยู่ด้านบนสุดของสแต็กและ golfscript ขาดความสามารถในการลบเฉพาะองค์ประกอบสแต็กใด ๆ คุณสามารถหมุนสแต็กและยกเลิกองค์ประกอบด้านบนใหม่ แต่สร้างได้อย่างรวดเร็ว \;ไม่เป็นไร \;\;\;\;\;ไม่ใช่ คุณสามารถทำได้\;แบบวนซ้ำ ( {\;}9*; ราคา: 6 ตัวอักษรเพื่อทิ้งองค์ประกอบ 9 ตัวหรือ 7 ตัวอักษรเพื่อยกเลิกองค์ประกอบได้ถึง 99 องค์ประกอบ) แต่เราทำได้ดีกว่า:

Golfscript มีอาร์เรย์ชั้นหนึ่ง [1 2 3 4]นอกจากนี้ยังมีอาร์เรย์ไวยากรณ์ที่แท้จริง สิ่งที่ไม่คาดคิดก็คือ[และ]ไม่ใช่ส่วนหนึ่งของไวยากรณ์ พวกมันเป็นเพียงตัวดำเนินการสองตัว: [ทำเครื่องหมายตำแหน่งปัจจุบันบนสแต็กและ]รวบรวมทุกองค์ประกอบจนกว่าจะพบเครื่องหมายเริ่มต้นของอาร์เรย์หรือวิ่งออกมาจากสแต็กและทิ้งเครื่องหมาย คุณสามารถแยกสองสิ่งนี้ออกจากกันและดูว่าเกิดอะไรขึ้น ค่อนข้างเป็นเรื่องที่น่าสนใจ:

ฉันว่าคำว่า golfscript ไม่มีแนวคิดของ stack frames หรือไม่? ฉันโกหก. [นี่คือกรอบกอง: คุณสามารถละทิ้งมันทั้งหมดในครั้งเดียว: ];. แต่ถ้าเราต้องการเก็บค่าส่งคืน คุณสามารถปิดสแต็กเฟรมในรายการฟังก์ชัน (จากนั้นเรามีแพสต์บาย - อาเรย์ - ไม่ใช่แนวคิดที่น่าสนใจ) หรือเราสามารถปิดสแต็กเฟรมและใช้องค์ประกอบสุดท้ายแทนทิ้งทั้งหมด: ]-1=หรือเรา สามารถปลดองค์ประกอบสุดท้ายออกแล้วยกเลิกเฟรม: ])\;. พวกมันมีความยาวเท่ากัน แต่ส่วนหลังนั้นค่อนข้างเย็นกว่าเล็กน้อยดังนั้นฉันจึงใช้มัน

ดังนั้นแทนที่จะเป็นตัวละคร 6 หรือ 7 ตัวในการทำความสะอาดเราสามารถทำได้ด้วย 5 ฉันยังรู้สึกว่ามันสามารถเล่นกอล์ฟได้มากกว่านี้ แต่เดี๋ยวก่อนเราได้บันทึกตัวละครไว้แล้ว


"เรียกใช้ฟังก์ชันด้วยตัวเองเป็นอาร์กิวเมนต์แรก" - แนวคิดที่น่าสนใจสำหรับการเรียกซ้ำ
aditsu ออกเนื่องจาก SE เป็นความชั่วร้าย

1

Smalltalk Squeak 4.x ได้ลิ้มรสหลายไบต์!

ฉันสามารถใช้หนึ่งในแบบฟอร์มเวียนเกิดใน Integer ใน 71 ถ่าน

f:y n:n n=1or:[^(2to:y)inject:self into:[:x :i|self f:x n:n-1]].^self+y

จากนั้นการอ่านจากไฟล์หรือ FileStream stdin จะทำให้ฉันเสียแขน ... Squeak เห็นได้ชัดว่าไม่ได้ออกแบบมาเป็นภาษาสคริปต์ ดังนั้นฉันจะใช้หลายไบต์เพื่อสร้างโปรแกรมอรรถประโยชน์วัตถุประสงค์ทั่วไปของตัวเองที่ไม่เกี่ยวข้องกับปัญหา:

ใช้เมธอดถ่าน 21 ตัวนี้ในสตรีม (เพื่อข้าม seaparators)

s self skipSeparators

ใช้วิธีการถ่าน 20 วิธีนี้ในพฤติกรรม (เพื่ออ่านตัวอย่างจากสตรีม)

<s^self readFrom:s s

จากนั้น 28 ตัวอักษรใน String (เพื่อสร้างตัวจัดการไฟล์)

f^FileDirectory default/self

จากนั้น 59 ตัวอักษรใน FileDirectory (เพื่อสร้าง readStream)

r^FileStream concreteStream readOnlyFileNamed:self fullName

จากนั้น 33 ตัวอักษรใน BlockClosure (เพื่อประเมินมัน n ครั้ง)

*n^(1to:n)collect:[:i|self value]

จากนั้น 63 chars in Array (ประเมินอาร์กิวเมนต์ด้วยตัวรับและอาร์กิวเมนต์ที่นำมาจาก Array)

`s^self first perform:s asSymbol withArguments:self allButFirst

จากนั้นแก้ไขปัญหาโดยการประเมินข้อมูลโค้ด 31 ตัวนี้เพื่ออ่านจากไฟล์ชื่อ x

|s|s:='x'f r.[0class<s]*3`#f:n:

แม้จะไม่นับสาธารณูปโภค แต่นั่นก็คือ 71 + 31 = 102 ตัวอักษรอยู่แล้ว ...

ตอนนี้เนื่องจากฉันแน่ใจว่าจะสูญเสีย codeGolf ฉันจึงมีการติดตั้งที่สนุกขึ้นใน Integer:

doesNotUnderstand:m
    (m selector allSatisfy:[:c|c=$+])or:[^super doesNotUnderstand:m].
    self class compile:
        m selector,'y y=0or:[^(2to:y)inject:self into:[:x :i|self'
        ,m selector allButLast,'x]].^'
        ,(Character digitValue:()asBit)
        ,(m selector size-2min:1)hex last.
    thisContext sender restart

วิธีนี้จะกำหนด (คอมไพล์) ข้อความไบนารีที่ทำจาก n + หากไม่มีอยู่ (ไม่ได้รับโดยผู้รับข้อความ m) และจะรีสตาร์ทการประมวลผลที่จุดเริ่มต้นของบริบทผู้ส่ง ฉันแทรกการขึ้นบรรทัดใหม่และช่องว่างเพื่อให้สามารถอ่านได้

ทราบว่าเป็นรูปแบบของ(m selector size-2min:1)hex last shorted(m selector size>2)asBit printString

หากไม่แสดงให้เห็นถึงพลังอำนาจชั่วร้ายของ Smalltalk ข้อความสุดท้ายอาจถูกแทนที่ด้วยความสั้นและง่ายกว่า

^m sendTo:self

ตอนนี้ใช้ยูทิลิตี้ 28 ตัวอักษรในตัวละคร (เพื่อทำซ้ำมัน n ครั้งในสตริง)

*n^String new:n withAll:self

จากนั้นประเมินการแสดงออก 43 ตัวอักษรนี้:

|i s|i:=0class.s:='x'f r.[i<s]*2`($+*(i<s))

เราสามารถเร่งได้เร็วขึ้นด้วย 10 ตัวอักษรโดยการใช้งานในจำนวนเต็ม:

++y^self*y

และในกรณีนี้เรายังมีรหัสที่สั้นกว่าเพราะเราสามารถแทนที่^',(m selector size-2min:1)hex lastด้วย^1'

สำหรับราคาที่สูงเช่นนี้รหัสจะทำงานกับจำนวนเต็มที่สอง = 0 :)



0

ระบบพีชคณิตคอมพิวเตอร์ AXIOM ไบต์ 69

p(x,y,n)==(n<=1=>y+x^n;n=2=>y*x;n=3=>x^y;y<=0=>1;p(x,p(x,y-1,n),n-1))

ทดสอบ:

(2) -> p(1,1,1)
   (2)  2
                                                 Type: Expression Integer
                                   Time: 0.05 (IN) + 0.03 (OT) = 0.08 sec
(3) -> p(2,4,4)
   (3)  65536
                                                 Type: Expression Integer
                                                              Time: 0 sec
(4) -> p(3,3,4)
   (4)  7625597484987
                                                 Type: Expression Integer
                                                              Time: 0 sec

สิ่งนี้จะกำจัดการสอบถามซ้ำ ... เป็นไปได้ที่ฉันสลับเป็น x และ y ในทางกลับกันบางอย่าง ... มีค่าทดสอบอื่น ๆ อีกไหม?


0

APL (NARS), ตัวอักษร 61, ไบต์ 122

{(x y n)←⍵⋄n≤1:y+x*n⋄n=2:x×y⋄n=3:x*y⋄y≤0:1⋄∇x,(∇x(y-1)n),n-1}

ทดสอบ:

  h←{(x y n)←⍵⋄n≤1:y+x*n⋄n=2:x×y⋄n=3:x*y⋄y≤0:1⋄∇x,(∇x(y-1)n),n-1}
  h 1 1 1
2
  h 2 4 4
65536
  h 3 4 4
∞
  h 3 3 4
7625597484987
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.