ลำดับของ Stewie: + * - / + * - /


29

มาใช้การดำเนินการพื้นฐานสี่อย่างบวกการ+เพิ่มการ*ลบ-และการหาร/(float ไม่ใช่จำนวนเต็ม)

ลำดับของ Stewieถูกกำหนดดังนี้:

x = [x(1), x(2)]    // Two initial numbers (one indexed)
x(3) = x(1) + x(2)
x(4) = x(2) * x(3)
x(5) = x(3) - x(4)
x(6) = x(4) / x(5)
x(7) = x(5) + x(6)
... and so on.

ท้าทาย:

รับจำนวนเต็มสองจำนวนที่ไม่เป็นลบ ( x(1), x(2)) และจำนวนเต็มบวกหนึ่งค่าNเป็นอินพุต

x(1)และx(2)จะเป็นตัวเลขสองตัวแรกของลำดับของคุณและNจะเป็นความยาวของลำดับที่คุณต้องส่งออก (คุณสามารถเลือกให้มีรายการตาม 0 ซึ่งในกรณีนี้Nจะน้อยกว่าความยาวหนึ่งรายการ)

  • x(2) >= x(1)คุณไม่สามารถสรุปได้ว่า
  • Nจะเป็น>2ถ้าใช้แบบ 1 เสมอ( >1ถ้าใช้แบบ 0)
  • คุณไม่ต้องจัดการกับการหารด้วยข้อผิดพลาดที่เป็นศูนย์
    • สังเกตกรณีทดสอบครั้งที่ 2 คุณจะไม่ได้รับ0, 1และN=6เป็น input ตั้งแต่ที่จะส่งผลให้หารด้วยศูนย์ แต่คุณต้องสนับสนุนและ0, 1N=5
  • สมมติว่าป้อนข้อมูลที่ถูกต้องเท่านั้นที่จะได้รับ
  • อินพุตและเอาต์พุตสามารถอยู่ในรูปแบบที่สะดวกใด ๆ แต่คุณต้องสนับสนุนอย่างน้อย 3 หลักหลังจุดทศนิยมถ้าเอาต์พุตไม่ใช่จำนวนเต็ม

กรณีทดสอบ:

1 3
8
1, 3, 4, 12, -8, -1.5, -9.5, 14.25

0 1
5
0, 1, 1, 1, 0     // N=6 would give division by zero error. You don't need to handle that case.

1 0
9
1, 0, 1, 0, 1, 0, 1, 0, 1

6 3
25
6, 3, 9, 27, -18, -1.5, -19.5, 29.25, -48.75, -0.6, -49.35, 29.61, -78.96, -0.375, -79.335, 29.7506, -109.086, -0.272727, -109.358, 29.825, -139.183, -0.214286, -139.398, 29.8709, -169.269

ฟังก์ชั่นสามารถใช้ x (1) และ x (2) เป็นรายการได้หรือไม่? หรือแยกอาร์กิวเมนต์?
FlipTack

สิ่งที่สะดวกสบายสำหรับคุณ :)
Stewie Griffin

สามารถNใช้แบบ 0 ได้? ดังนั้นรับอินพุต 1 น้อยกว่า N ที่แสดงในตัวอย่างของคุณ ฉันเดาว่าการรับ N-2 นั้นมากเกินไปที่จะขอ ... :-P
หลุยส์เมนโด

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

1
@Emigna ไม่ฉันคิดว่ามันเป็นอะไรที่ยืดเกินไป ... ตัวเลขควรอยู่ในลำดับที่ถูกต้อง
Stewie Griffin

คำตอบ:


3

MATL , 19 18 17 ไบต์

q:"y'+*-/'@)hyhUV

อินพุตอยู่ในรูปแบบ: N(อิงตาม 0) x(1),, x(2)(เป็นสตริง); ทั้งหมดคั่นด้วยการขึ้นบรรทัดใหม่

ลองออนไลน์! หรือตรวจสอบกรณีทดสอบทั้งหมด (รหัสที่แก้ไขเล็กน้อยลำดับการส่งออกคั่นด้วยบรรทัดว่าง)

คำอธิบาย

MATL ไม่มีevalฟังก์ชันที่เหมาะสมแต่U( str2num) สามารถประเมินนิพจน์ตัวเลขด้วยตัวดำเนินการมัด

คำศัพท์ใหม่แต่ละคำจะถูกคำนวณและผลักลงบนสแต็กเพื่อรักษาคำก่อนหน้า สแต็กทั้งหมดถูกพิมพ์ที่ท้าย

q          % Implicitly input N (0-based). Subtract 1
:"         % Repeat that many times
  y        %   Duplicate x(n-1), where n is the number of already computed terms
           %   In the first iteration, which corresponds to n=2, this implicitly 
           %   inputs x(1) and x(2) as strings (and then duplicates x(1))
  '+*-/'   %   Push this string
  @)       %   Push iteration number and apply as modular index into the string. 
           %   So this gives '+' in the first iteration, '*' in the second etc
  h        %   Concatenate horizontally. This gives a string of the form
           %   '*x(n-1)+', where '+' is the appropriate operator 
  &y       %   Duplicate x(n)
  hh       %   Concatenate horizontally. This gives a string of the form
           %   'x(n-1)+x(n)'
  U        %   Convert to number. This evaluates the string
  V        %   Convert back to string. This is the new term, x(n+1)
           % Implicitly end loop and display stack

7

Haskell, 69 68 64 ไบต์

x#n=take n$x++zipWith3 id(cycle[(+),(*),(-),(/)])(x#n)(tail$x#n)

x1และx2ถูกนำมาเป็นรายการ ตัวอย่างการใช้งาน: ->[1,3] # 8[1.0,3.0,4.0,12.0,-8.0,-1.5,-9.5,14.25]

ความเกียจคร้านทำให้สามารถกำหนดรายการเรียกซ้ำแบบไม่สิ้นสุดที่เราใช้องค์ประกอบ n แรก

Haskell, 66 ไบต์

(h%g)y x=x:g(h x y)y
a=(+)%b
b=(*)%c
c=(-)%d
d=(/)%a
(.a).(.).take 

วิธีการที่แตกต่างกันอีกต่อไปเล็กน้อย เพื่ออาร์กิวเมนต์N, ,x2 x1ตัวอย่างการใช้งาน: ->( (.a).(.).take ) 8 3 1[1.0,3.0,4.0,12.0,-8.0,-1.5,-9.5,14.25]

กำหนด 4 ฟังก์ชั่นa, b, cและdซึ่งใช้เวลาสองมีปากเสียงy, x และทำรายการโดยใส่xในหน้าของการเรียกร้องให้ฟังก์ชั่นถัดไปที่มีyเป็นอาร์กิวเมนต์ที่สองและx op yเป็นครั้งแรก ตัวอย่างเช่นa: a y x = x : (b (x+y) y), bทำการคูณ: b y x = x : (c (x*y) y), ฯลฯ

แก้ไข: @Michael Klein บันทึกไบต์ในตัวแปรที่ 1 ( #) โชคดีที่ฉันยังพบหนึ่งไบต์สำหรับตัวแปรที่สองดังนั้นทั้งสองจึงมีความยาวเท่ากันอีกครั้ง

แก้ไข II: @Zgarb พบ 2 ไบต์ในรุ่นที่สองเพื่อบันทึกและฉัน 4 ในครั้งแรกดังนั้นจึงไม่มีความยาวเท่ากันอีกต่อไป


ยอมรับข้อโต้แย้งเป็นรายการ (อนุญาต) สำหรับไบต์
Michael Klein

ฉันมักจะสับสนถ้า(.)ประกอบด้วยฟังก์ชั่นอื่น ๆ : p
tomsmeding

g x=(`take`f)whereไม่ได้บันทึกไบต์: - /
Bergi

บันทึก 2 ไบต์ด้วยวิธีการอื่น:(h%g)y x=x:g(h x y)y
Zgarb

@Zgarb: โอ้นั่นเป็นสิ่งที่ดี ขอบคุณ! BTW เมื่อแก้ไขคำแนะนำของคุณฉันพบ 4 ไบต์เพื่อบันทึกไปพร้อมกันในเวอร์ชันแรก
nimi

6

ES6 (Javascript) 79, 67, 65 ไบต์

UPDATE

  • ลบ 2 ไบต์โดยเริ่มต้นด้วย i = 2 ตามที่แนะนำโดย @ETHProductions
  • บันทึกแล้ว 3 ไบต์ขอบคุณคำแนะนำดี ๆ จาก @Neil!

แข็งแรงเล่นกอล์ฟ

S=(n,a,i=2)=>i<n?S(n,a,a.push(eval(a[i-2]+"-/+*"[i%4]+a[i-1]))):a

ทดสอบ

S=(n,a,i=2)=>i<n?S(n,a,a.push(eval(a[i-2]+"-/+*"[i%4]+a[i-1]))):a

>S(8,[1,3])
Array [ 1, 3, 4, 12, -8, -1.5, -9.5, 14.25 ]

>S(5,[0,1])
Array [ 0, 1, 1, 1, 0 ]

>S(9,[1,0])
Array [ 1, 0, 1, 0, 1, 0, 1, 0, 1 ]

>S(25,[6,3])
Array [ 6, 3, 9, 27, -18, -1.5, -19.5, 29.25, -48.75, -0.6, ...]

1
คุณไม่สามารถใช้++iเพื่อหลีกเลี่ยงการเพิ่ม 1 ถึงiสองครั้งได้หรือไม่?
Neil

1
หรือมิฉะนั้นการเขียน?S(n,a,i+1,a.push(...)):aอาจช่วยให้คุณประหยัดไบต์
Neil

1
หรือบางทีคุณอาจใช้ข้อเท็จจริงที่a.pushส่งคืนความยาวใหม่S=(n,a,i=2)=>i<n?S(n,a,a.push(...)):a
นีล

1
ผมยังคิดว่าคุณสามารถบันทึกไบต์มากขึ้นโดยเริ่มต้นที่i=2ว่า
Neil

1
ด้วยคำแนะนำของ Neil ฉันคิดว่าคุณสามารถทำได้S=(n,a,i=2)=>i<n?S(n,a,a.push(eval(a[i-2]+"+*-/"[i%4]+a[i-1]))):aเพื่อประหยัด 2 ไบต์
ETHproductions

5

Python 3, 90 80 74 ไบต์

xnor อาจจะมาและทำลายวิธีนี้ ...

def F(s,n,i=2):
 while i<n:s+=eval('%s'*3%(s[-2],'-/+*'[i%4],s[-1])),;i+=1

ฟังก์ชั่นปรับเปลี่ยนรายการที่ส่งผ่านไป ใช้แบบนี้:

s = [1,3] 
F(s,8)

ลองใช้ repl.it!

-6 ไบต์ต้องขอบคุณ Copper


เนื่องจากคุณใช้เพียงOครั้งเดียวคุณสามารถบันทึกไม่กี่ไบต์ด้วยการทำและลบประกาศของ'-/+*'[i%4] Oนอกจากนี้คุณอาจจะสามารถที่จะได้รับรอบซ้ำโทรออกไปด้วยการทำสิ่งที่ชอบstr eval('%s'*3%(s[-2],'-/+*'[i%4],s[-1]))
ทองแดง

โอ้ใช่และs+=[...]สามารถถูกแทนที่ด้วยs+=...,(หมายเหตุเครื่องหมายจุลภาคต่อท้าย)
ทองแดง

xnor ไม่ใช่คนเดียวที่สามารถทำลายทางออกของคุณ มีคนอื่นด้วยเช่นกัน: เดนนิส (ตัวดัดแปลง)
Erik the Outgolfer

คุณรับประกันว่าจะได้รับiเป็นอินพุตดังนั้นคุณไม่จำเป็นต้องมีค่าเริ่มต้นสำหรับมัน ( i=2เป็นได้i) ปิดสองไบต์
ArtOfCode

1
หากได้รับอนุญาตให้ส่งคืนnรายการลำดับที่ตามมาแทนนี่คือ 1 ไบต์ที่สั้นลงด้วยการเรียกซ้ำ:f=lambda x,n:n<2and x[n-1]or eval('%s'*3%(f(x,n-2),'*-/+'[n%4],f(x,n-1)))
mbomb007

5

Perl 6 ,  75 71  61 ไบต์

->\a,\b,\c{$_=[|(&[+],&[*],&[-],&[/])xx*];(a,b,{.shift.($^a,$^b)}...*)[^c]}

ทดสอบมัน

{$_=[|(&[+],&[*],&[-],&[/])xx*];($^a,$^b,{.shift.($^a,$^b)}...*)[^$^c]}

ทดสอบมัน

{($^a,$^b,{(&[+],&[*],&[-],&[/])[$++%4]($^a,$^b)}...*)[^$^c]}

ทดสอบมัน

ขยาย:

{ # bare block lambda with placeholder parameters 「$a」 「$b」 「$c」

  # generate sequence
  (
    # initialize sequence
    $^a, # declare and use first argument
    $^b, # second argument

    {  # bare block lambda with two placeholder parameters 「$a」 「$b」

      (

        &[+], &[*], &[-], &[/] # the four operators

      )[             # index into the list of operators

         $++        # increment (++) an anonymous state variable ($)
         % 4        # modulo 4

      ]( $^a, $^b ) # and use it on the previous two values in sequence

    }

    ...  # repeat that until

    *    # indefinitely

  )[     # take only

    ^    # upto and excluding:     ( Range object )
    $^c  # third argument

  ]
}

4

Mathematica, 68 ไบต์

(±1=#;±2=#2;±n_:=1##[#-#2,#/#2,+##][[n~Mod~4]]&[±(n-2),±(n-1)];±#3)&

แอบเข้าไปที่ 3 แทบไม่! ฟังก์ชันที่ไม่มีชื่อของอาร์กิวเมนต์สามตัวซึ่งใช้ตัวดำเนินการตัวช่วย unary ±ซึ่งนั่น±nคือองค์ประกอบที่ n x (n) ของลำดับ Stewie อาร์กิวเมนต์สองตัวแรกคือ x (1) และ x (2) และอาร์กิวเมนต์ที่สามคือ N ระบุว่า x (N) ใดที่เราส่งออก

การนำไปใช้โดยตรงโดยใช้การคำนวณ mod-4 เพื่อเลือกฟังก์ชันไบนารีที่จะใช้กับคำสองคำก่อนหน้านี้ เลือกฟังก์ชั่นไบนารีที่ถูกต้องซึ่งเป็นสิ่งที่1##[#-#2,#/#2,+##]จะช่วยให้มีใช้ไม่กี่ของเหล่านี้สนุก Mathematica เทคนิคการเล่นกอล์ฟ


3

05AB1E , 21 19 18 ไบต์

ป้อนข้อมูลดำเนินการในการสั่งซื้อN (0-based) x (2) , x (1)
ที่บันทึกไว้ 1 ขอบคุณไบต์carusocomputing

GUDXsX"/+*-"Nè.V})

ลองออนไลน์!

คำอธิบาย

 G                   # for N in [0 ... n-1] do:
  U                  # save top element of stack in X
   D                 # duplicate top of stack
    X                # push X
     s               # swap top 2 elements on stack
      X              # push X
       "/+*-"Nè      # index into the string with the current iteration number
               .V    # evaluate
                 }   # end loop
                  )  # wrap stack in list

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


1
ฉันคิดไม่ออก แต่ใช้XYและUVอาจช่วยคุณประหยัดได้
Magic Octopus Urn

1
@carusocomputing: จับดี! ที่บันทึกไว้ผมไบต์ที่หายไปจากการลงทะเบียนไม่ได้ทำงานกับการป้อนข้อมูลโดยปริยายใช้UX:)
Emigna

2

เสียงกระเพื่อมสามัญ 158

(lambda(x y n)(loop repeat n for a = x then b for b = y then r for o in '#1=(+ * - / . #1#)for r =(ignore-errors(funcall o a b))collect(coerce a'long-float)))

ไม่ได้แข่งขันกันจริงๆ แต่ฉันชอบที่มันแสดงออกอย่างเป็นธรรมชาติ:

(lambda (x y n)
  (loop 
    repeat n
    for a = x then b
    for b = y then r
    for o in '#1=(+ * - / . #1#)
    for r = (ignore-errors (funcall o a b))
    collect (coerce a 'long-float)))

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

การทดสอบ

เราตั้งชื่อฟังก์ชั่นFและตรวจสอบว่าค่าที่คาดหวังจะเท่ากับค่าที่ทดสอบ

(loop
  for (args expected)
    in
  '(((1 3 8)
     (1 3 4 12 -8 -1.5 -9.5 14.25))

    ((0 1 5)
     (0 1 1 1 0))

    ((1 0 9)
     (1 0 1 0 1 0 1 0 1))

    ((6 3 25)
     (6 3 9 27 -18 -1.5 -19.5 29.25 -48.75 -0.6 -49.35 29.61 -78.96 -0.375 -79.335 29.7506 -109.086 -0.272727 -109.358 29.825 -139.183 -0.214286 -139.398 29.8709 -169.269)))

  for result = (apply #'f args)
  always (every (lambda (u v) (< (abs (- u v)) 0.001)) result expected))

=> T

เหตุผลสำหรับการทดสอบโดยประมาณนั้นเป็นเพราะค่าที่คำนวณได้มีความแม่นยำมากกว่าเล็กน้อย ที่นี่สำหรับ(f 6 3 25):

(6.0d0 3.0d0 9.0d0 27.0d0 -18.0d0 -1.5d0 -19.5d0 29.25d0 -48.75d0 -0.6d0
 -49.35d0 29.61d0 -78.96d0 -0.375d0 -79.335d0 29.750625d0 -109.085625d0
 -0.2727272727272727d0 -109.35835227272727d0 29.825005165289255d0
 -139.18335743801654d0 -0.21428571428571427d0 -139.39764315230224d0
 29.870923532636194d0 -169.26856668493843d0)

2

dc, 112 110 108 bytes

5k?sarfsmsn[pSnla1-Sa]sh[lmlndSm]sv[lvx/lhx]sb[lvx+lhx]sc[lvx*lhx]sd[lvx-lhx]se[lcx2la>d2la>e2la>b2la>j]dsjx

บางครั้งdcคำตอบอาจยาวมากและบางครั้งก็สั้นมาก ทุกอย่างขึ้นอยู่กับความท้าทายในมือเช่นเดียวกับกรณีอื่น ๆ อีกหลายภาษา ต่อไปนี้จะพร้อมต์สำหรับอินพุตบรรทัดรับคำสั่งที่ทำดัชนีด้วยหนึ่งช่องว่างของจำนวนเต็ม 3 จำนวนx(1), x(2), Nเมื่อเรียกใช้และส่งออกแต่ละองค์ประกอบของลำดับบนบรรทัดแยกต่างหากด้วยเอาต์พุตที่ไม่ใช่จำนวนเต็มที่มี 5 หลักหลังจุดทศนิยม

ตัวอย่างเช่นการป้อนข้อมูล6 3 25ผลลัพธ์ในผลลัพธ์ต่อไปนี้:

6
3
9
27
-18
-1.50000
-19.50000
29.25000
-48.75000
-.60000
-49.35000
29.61000
-78.96000
-.37500
-79.33500
29.75062
-109.08562
-.27272
-109.35834
29.82420
-139.18254
-.21428
-139.39682
29.86995
-169.26677

2

Perl, 62 + 3 ( -plaตั้งค่าสถานะ) = 65 ไบต์

push@F,eval$F[-2].qw(* - / +)[$_%4].$F[-1]for 3..pop@F;$_="@F"

โดยใช้:

perl -plae 'push@F,eval$F[-2].qw(* - / +)[$_%4].$F[-1]for 3..pop@F;$_="@F"' <<< '1 3 8'

1

Ruby, 79 ไบต์

->(b,c,d){a=[b,c];(d-2).times{|i|a<<a[i].send(%i{+ * - /}[i%4],a[i+1]).to_f};a}

ฉันสงสัยว่ามันอยู่ไกลจากคำตอบที่ดีที่สุด (และฉันยังไม่ได้ดูคำตอบอื่น ๆ ) แต่มันก็สนุกดี

ผมอยากที่จะมีความสนุกสนานบางคนที่มีEnumerable#cycleแต่เศร้ามันเป็น 4 %4ตัวอักษรน้อยลงไปเพียงแค่ใช้


1

C ++ 14, 118 ไบต์

[](auto&v,int N){for(int i=0;++i<N-1;){auto p=v.rbegin(),q=p+1;v.push_back(i%4?i%4<2?*q+*p:i%4<3?*q**p:*q-*p:*q/ *p);}

แลมบ์ดาเป็นชื่อที่ไม่มีการแก้ไขการป้อนข้อมูล ต้องใช้vให้เป็นหรือvector<double>vector<float>

Ungolfed และการใช้งาน:

#include<iostream>
#include<vector>

auto f=
[](auto&v,int N){
  for(int i=0; ++i<N-1;){
    auto p=v.rbegin(),q=p+1;
    v.push_back(
      i%4 ?
        i%4<2 ? *q+*p : 
          i%4<3 ? *q**p : *q-*p
      : *q/ *p
    );
  }
};

int main(){
  std::vector<double> v={1,3};
  f(v,8);
  for (auto x:v) std::cout << x << ", ";
  std::cout << "\n";
}

1

รหัสเครื่อง x86-64 ขนาด 34 ไบต์

ระเบียบการเรียก = x86-64 ระบบ V x32 ABI (ลงทะเบียน args ด้วยตัวชี้แบบ 32 บิตในโหมดยาว)

void stewie_x87_1reg(float *seq_buf, unsigned Nterms);ลายเซ็นเป็นฟังก์ชั่น ฟังก์ชั่นได้รับค่าเมล็ด x0 และ x1 ในสององค์ประกอบแรกของอาร์เรย์และขยายลำดับออกไปอย่างน้อย N องค์ประกอบเพิ่มเติม บัฟเฟอร์ต้องถูกขยายให้มีค่าเป็น 2 + N- ปัดเศษขึ้นเป็นต่อไป - ต่อไป - หลายคู่ของ 4 (เช่น2 + ((N+3)&~3)หรือเพียงแค่ N + 5)

ต้องการบัฟเฟอร์เบาะเป็นเรื่องปกติในการชุมนุมสำหรับฟังก์ชั่นที่มีประสิทธิภาพสูงหรือ SIMD-vectorized และการวนลูปที่ไม่ได้ม้วนนี้คล้ายกันดังนั้นฉันไม่คิดว่ามันจะดัดกฏมากเกินไป ผู้เรียกสามารถ (และควร) ละเว้นองค์ประกอบทั้งหมดได้อย่างง่ายดาย

การผ่าน x0 และ x1 เป็นฟังก์ชั่นหาเรื่องที่ไม่ได้อยู่ในบัฟเฟอร์จะทำให้เราเสียค่าใช้จ่ายเพียง 3 ไบต์ (สำหรับ a movlps [rdi], xmm0หรือmovups [rdi], xmm0) แม้ว่านี่จะเป็นรูปแบบการโทรที่ไม่ได้มาตรฐานเนื่องจาก System V ส่งผ่านการstruct{ float x,y; };ลงทะเบียน XMM สองรายการ

นี่เป็นobjdump -drw -Mintelเอาต์พุตที่มีการจัดรูปแบบเล็กน้อยเพื่อเพิ่มความคิดเห็น

0000000000000100 <stewie_x87_1reg>:
       ;; load inside the loop to match FSTP at the end of every iteration
       ;; x[i-1] is always in ST0
       ;; x[i-2] is re-loaded from memory
 100:   d9 47 04                fld    DWORD PTR [rdi+0x4]
 103:   d8 07                   fadd   DWORD PTR [rdi]
 105:   d9 57 08                fst    DWORD PTR [rdi+0x8]
 108:   83 c7 10                add    edi,0x10            ; 32-bit pointers save a REX prefix here

 10b:   d8 4f f4                fmul   DWORD PTR [rdi-0xc]
 10e:   d9 57 fc                fst    DWORD PTR [rdi-0x4]

 111:   d8 6f f8                fsubr  DWORD PTR [rdi-0x8]
 114:   d9 17                   fst    DWORD PTR [rdi]

 116:   d8 7f fc                fdivr  DWORD PTR [rdi-0x4]
 119:   d9 5f 04                fstp   DWORD PTR [rdi+0x4]

 11c:   83 ee 04                sub    esi,0x4
 11f:   7f df                   jg     100 <stewie_x87_1reg>
 121:   c3                      ret    

0000000000000122 <stewie_x87_1reg.end>:
## 0x22 = 34 bytes

การประยุกต์ใช้การอ้างอิง C นี้คอมไพล์ (กับgcc -Os) ถึงรหัสที่ค่อนข้างคล้ายกัน gcc เลือกกลยุทธ์เดียวกับที่ฉันทำโดยเก็บค่าเพียงค่าเดียวไว้ในทะเบียน

void stewie_ref(float *seq, unsigned Nterms)
{
    for(unsigned i = 2 ; i<Nterms ; ) {
        seq[i] = seq[i-2] + seq[i-1];       i++;
        seq[i] = seq[i-2] * seq[i-1];       i++;
        seq[i] = seq[i-2] - seq[i-1];       i++;
        seq[i] = seq[i-2] / seq[i-1];       i++;
    }
}

ฉันทำการทดลองด้วยวิธีอื่นรวมถึงรุ่น x87 สองทะเบียนที่มีรหัสเช่น:

; part of loop body from untested 2-register version.  faster but slightly larger :/
; x87 FPU register stack    ;       x1, x2   (1-based notation)
fadd    st0, st1            ; x87 = x3, x2
fst     dword [rdi+8 - 16]  ; x87 = x3, x2

fmul    st1, st0            ; x87 = x3, x4
fld     st1                 ; x87 = x4, x3, x4
fstp    dword [rdi+12 - 16] ; x87 = x3, x4
; and similar for the fsubr and fdivr, needing one fld st1

คุณจะทำแบบนี้ถ้าคุณต้องการความเร็ว (และ SSE ไม่พร้อมใช้งาน)

การวางโหลดจากหน่วยความจำไว้ในลูปแทนที่จะเป็นหนึ่งครั้งอาจช่วยได้เนื่องจากเราสามารถเก็บผลลัพธ์ย่อยและ div ตามลำดับ แต่ก็ยังต้องการคำแนะนำ FLD สองคำสั่งในการตั้งค่าสแต็กในรายการ

ฉันยังลองใช้คณิตศาสตร์สเกลาร์ SSE / AVX (เริ่มต้นด้วยค่าใน xmm0 และ xmm1) แต่ขนาดคำสั่งที่ใหญ่กว่านั้นก็คือ killer การใช้addps(เนื่องจากสั้นกว่า 1B addss) จะช่วยนิดหน่อย ฉันใช้คำนำหน้า AVX VEX สำหรับคำแนะนำที่ไม่ใช่การสับเปลี่ยนเนื่องจาก VSUBSS มีความยาวเพียงหนึ่งไบต์มากกว่า SUBPS (และความยาวเท่ากับ SUBSS)

; untested.  Bigger than x87 version, and can spuriously raise FP exceptions from garbage in high elements
addps   xmm0, xmm1      ; x3
movups  [rdi+8 - 16], xmm0
mulps   xmm1, xmm0      ; xmm1 = x4,  xmm0 = x3
movups  [rdi+12 - 16], xmm1
vsubss  xmm0, xmm1, xmm0      ; not commutative.  Could use a value from memory
movups  [rdi+16 - 16], xmm0
vdivss  xmm1, xmm0, xmm1      ; not commutative
movups  [rdi+20 - 16], xmm1

ทดสอบกับชุดทดสอบนี้:

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

int main(int argc, char**argv)
{
    unsigned seqlen = 100;
    if (argc>1)
        seqlen = atoi(argv[1]);
    float first = 1.0f, second = 2.1f;
    if (argc>2)
        first = atof(argv[2]);
    if (argc>3)
        second = atof(argv[3]);

    float *seqbuf = malloc(seqlen+8);  // not on the stack, needs to be in the low32
    seqbuf[0] = first;
    seqbuf[1] = second;

    for(unsigned i=seqlen ; i<seqlen+8; ++i)
        seqbuf[i] = NAN;

    stewie_x87_1reg(seqbuf, seqlen);
//  stewie_ref(seqbuf, seqlen);
    for (unsigned i=0 ; i< (2 + ((seqlen+3)&~3) + 4) ; i++) {
        printf("%4d: %g\n", i, seqbuf[i]);
    }

    return 0;
}

รวบรวมกับ nasm -felfx32 -Worphan-labels -gdwarf2 golf-stewie-sequence.asm &&
gcc -mx32 -o stewie -Og -g golf-stewie-sequence.c golf-stewie-sequence.o

รันกรณีทดสอบแรกด้วย ./stewie 8 1 3

ถ้าคุณไม่ได้ x32 ห้องสมุดติดตั้งการใช้งานnasm -felf64และการลา GCC -m64โดยใช้ค่าเริ่มต้น ฉันใช้mallocแทนfloat seqbuf[seqlen+8](บนสแต็ก) เพื่อรับแอดเดรสต่ำโดยไม่ต้องสร้างเป็น x32


ความจริงเรื่องสนุก: YASM มีข้อบกพร่อง: มันใช้ rel32 jcc สำหรับสาขาของลูปเมื่อเป้าหมายสาขามีที่อยู่เดียวกับสัญลักษณ์ทั่วโลก

global stewie_x87_1reg
stewie_x87_1reg:
   ;; ended up moving all prologue code into the loop, so there's nothing here
.loop:

...
sub    esi, 4
jg     .loop

ประกอบกับ ... 11f: 0f 8f db ff ff ff jg 100 <stewie_x87_1reg>




0

Bash, 224 ไบต์ (ไม่มีการประกวด)

การดำเนินขนาดใหญ่อย่างมากในการทุบตี

รับหน้าที่อย่างแท้จริงและทำทุกอย่างในท่อต่อเนื่องหนึ่งเดียวโดยไม่มีโครงสร้างการไหลหรือการเรียกซ้ำที่ไม่บริสุทธิ์

อินพุต

$ 1, $ 2 - องค์ประกอบเริ่มต้น

$ 3 - ขนาดลำดับเป้าหมาย

แข็งแรงเล่นกอล์ฟ

{ echo "a[0]=$1;a[1]=$2;a[0];a[1]";paste <() <(seq 2 $[$3-1]) <(seq 0 $[$3-3]) <(printf '%.0s+*-/' `seq $[$3/4]`|fold -1|head -$[$3-2]) <(seq 1 $[$3-2]);}|sed -r '1 ! s/(.+)\s(.+)\s(.+)\s(.)/a[\1]=a[\2]\3a[\4];a[\1];/'|bc -l

หัก Golfed

{ 
 echo "a[0]=$1;a[1]=$2;a[0];a[1]";
 paste <() <(seq 2 $[$3-1]) <(seq 0 $[$3-3]) <(printf '%.0s+*-/' `seq $[$3/4]`|fold -1|head -$[$3-2]) <(seq 1 $[$3-2]);
}\
|sed -r '1 ! s/(.+)\s(.+)\s(.+)\s(.)/a[\1]=a[\2]\3a[\4];a[\1];/' \
|bc -l

ทดสอบ

>./stewie.sh 1 3 8
1
3
4
12
-8
-1.50000000000000000000
-9.50000000000000000000
14.25000000000000000000

ไปป์ไลน์

สร้างตารางขององค์ประกอบดัชนี + op สำหรับแต่ละองค์ประกอบลำดับผลลัพธ์ (หนึ่งรายการต่อบรรทัด):

...
2   0   +   1
3   1   *   2
4   2   -   3
5   3   /   4
6   4   +   5
7   5   *   6
...

ใช้sedเพื่อแปลงสิ่งนี้เป็นโปรแกรม Linear bc :

...
a[2]=a[0]+a[1];a[2];
a[3]=a[1]*a[2];a[3];
a[4]=a[2]-a[3];a[4];
a[5]=a[3]/a[4];a[5];
a[6]=a[4]+a[5];a[6];
a[7]=a[5]*a[6];a[7];
...

ป้อนสิ่งนี้เป็นbcและปล่อยให้มันทำทุกอย่าง


0

Pyth - 20 ไบต์

การส่งออกnค่าใช้จ่ายทั้งหมดฉัน

u+Gvj@"+*-/"H>2GttEQ

ใช้งาน cuz แบบออนไลน์ไม่ได้


0

Ceylon, 195 ไบต์

Float[]s(Integer a,Integer b,Integer n)=>loop([a.float,b.float,[Float.divided,Float.plus,Float.times,Float.minus].cycled.rest])(([x,y,o])=>[y,(o.first else nothing)(x)(y),o.rest]).take(n)*.first;

จัดรูปแบบและแสดงความคิดเห็น:

// Print the first n entries of the Stewies sequence with given starting entries.
//
// Question:  http://codegolf.stackexchange.com/q/101145/2338
// My answer: http://codegolf.stackexchange.com/a/101251/2338

// Declare a function `s` which takes three integers, and returns a tuple
// of floats. (The more common syntax for the return value is [Float*],
// but Float[] is shorter.)
Float[] s(Integer a, Integer b, Integer n)
       // it is implemented by evaluating the following expression for each call.
         =>
        // start a loop with ...
        loop([
              // ... float versions of the integers, and ...
              a.float, b.float,
              // ... an infinite sequence of the four operators, ever repeating.
              // I needed the `.rest` here so the whole thing gets a {...*} type
              // instead of {...+}, which doesn't fit to what o.rest returns.
              // Each operator has the type Float(Float)(Float), i.e. you apply
              // it twice to one float each to get a Float result.
              [Float.divided, Float.plus, Float.times, Float.minus].cycled.rest])
               // in each iteration of the loop, map the triple of two numbers
               // and a sequence of operators to a triple of ... 
            (([x, y, o]) => [
               // the second number, 
                y,
               //the result of the first operator with both numbers
               // (using this "else nothing" here to convince the
               //  compiler that o.first is not null),
                   (o.first else nothing)(x)(y),
               // and the sequence of operators without its first element.
               // (that one unfortunately has a {...*} type, i.e. a possibly
               //  empty sequence.)
                                                 o.rest])
            // now we got an infinite sequence of those triples.
            // We just want the first n of them ...
                .take(n)
            // and of each triple just the first element.
            // (The *. syntax produces a tuple, non-lazily.
            //  We could also have used .map((z) => z.first)
            //  or .map(Iterable.first) or .map((z) => z[0]), each of
            //  which would return a (lazy) sequence, but they all would be
            //  longer.)
                *.first;

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

shared void run() {
    print(s(1, 3, 8));
    print(s(0,1,11));
    print(s(1,0,9));
    print(s(6, 3, 29));
}

ตัวอย่างผลลัพธ์:

[1.0, 3.0, 4.0, 12.0, -8.0, -1.5, -9.5, 14.25]
[0.0, 1.0, 1.0, 1.0, 0.0, Infinity, Infinity, Infinity, NaN, NaN, NaN]
[1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0]
[6.0, 3.0, 9.0, 27.0, -18.0, -1.5, -19.5, 29.25, -48.75, -0.6, -49.35, 29.61, -78.96000000000001, -0.37499999999999994, -79.33500000000001, 29.750625, -109.08562500000001, -0.2727272727272727, -109.35835227272727, 29.825005165289255, -139.18335743801651, -0.2142857142857143, -139.39764315230224, 29.870923532636194, -169.26856668493843, -0.17647058823529413, -169.44503727317374, 29.90206540114831, -199.34710267432206]

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


0

Clojure, 99 ไบต์

#(let[ops[+ * - /]](take %3(map first(iterate(fn[[a b i]][b((ops i)a b)(mod(inc i)4)])[%1 %2 0]))))

รุ่นนี้ดีกว่าที่จะใช้ในทางปฏิบัติ แต่มี 110 ไบต์:

(defn f[a b n](let[ops[+ * - /]](take n(map first(iterate(fn[[a b i]][b((ops i)a b)(mod(inc i)4)])[a b 0])))))

ฉันมีปัญหาในการ fuzing ฟังก์ชั่นที่วนซ้ำและลำดับการดำเนินการเป็นวัฏจักรดังนั้นฉันจึงต้องใช้ตัวนับแทน ลองใช้ตารางการเปลี่ยนแปลง FSM เช่น{+ * * - - / / +}แต่ฉันไม่สามารถบีบให้รหัสน้อยลง

สามารถแสดงเป็นฟังก์ชันที่ไม่ระบุชื่อได้

ยกเลิกแข็งแรงเล่นกอล์ฟ:

(defn f [a b n]
  (let [ops [+ * - /]]
    (->> [a b 0]
         (iterate (fn [[a b i]]
                    [b
                     ((ops i) a b)
                     (mod (inc i) 4)]))
         (map first)
         (take n))))

จะต้องเรียกด้วยการลอยเช่น(f 6.0 3.0 25)มิฉะนั้นคุณจะได้รับตัวเลขที่มีเหตุผลออก หรืออาจเริ่มต้นการทำซ้ำ[a (float b) 0]ซึ่งนำอักขระพิเศษมาให้


0

อ็อกเทฟ , 91 ไบต์

@(x,n)eval 'for i=3:n,x(i)=eval([(n=@num2str)(x(i-2)),"*-/+"(mod(i,4)+1),n(x(i-1))]);end,x'

ลองออนไลน์!

กอล์ฟบางส่วน:

  • ไม่มีวงเล็บสำหรับการevalโทรครั้งแรก
  • ไม่มีการต่อข้อมูลสำหรับevalสายแรก
  • การกำหนดแบบอินไลน์ของ*-/+(ไม่สามารถทำได้ใน MATLAB)
  • รวมกัน'และ"เพื่อหลีกเลี่ยงการหนีออกมาจากเครื่องหมายอัญประกาศเดี่ยว (เป็นไปไม่ได้ใน MATLAB)
  • การจัดเก็บn=@num2strเนื่องจากมีการใช้งานสองครั้ง (ไม่สามารถทำได้ใน MATLAB)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.