Stewie's sequence: + * - / + * - /

30

3

Let's use the four basic operations, addition +, multiplication *, subtraction - and division / (float, not integer).

Stewie's sequence is defined as follows:

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.

Challenge:

Take two non-negative integers (x(1), x(2)), and one positive integer N as input.

x(1) and x(2) will be the two first numbers of your sequence, and N will be the length of the sequence you must output. (You can choose to have the list 0-based, in which case N will be one less than the length).

  • You can not assume that x(2) >= x(1).
  • N will always be >2 if 1-based, (>1 if 0-based).
  • You do not have to handle division by zero errors.
    • Note the 2nd test case. You will not get 0, 1, and N=6 as input, since that will result in division by zero, but you must support 0, 1 and N=5.
  • Assume only valid input will be given.
  • The input and output can be on any convenient format, but you must support at least 3 digits after the decimal points if the output is non-integer.

Test cases:

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

Stewie Griffin

Posted 2016-11-25T22:25:45.700

Reputation: 43 471

Can a function take x(1) and x(2) as a list? Or seperate arguments? – FlipTack – 2016-11-25T22:31:36.300

Whatever is convenient for you :) – Stewie Griffin – 2016-11-25T22:32:24.887

Can N be 0-based? So take as inputs 1 less than the N shown in your examples. I guess taking N-2 is too much to ask for... :-P – Luis Mendo – 2016-11-25T22:44:49.350

When you write output can be on any convenient format, does that include a list with the final element in the beginning and the start-elements at the end (a reversed list)? – Emigna – 2016-11-25T22:50:22.793

@LuisMendo N can be zero-based. And you're right about that second part :) – Stewie Griffin – 2016-11-25T22:57:43.417

1@Emigna, no I think that's a bit of a stretch... The numbers should be in the correct order – Stewie Griffin – 2016-11-25T22:58:33.280

I'm working on an x86 assembly-language function (smallest machine-code) answer. Since I can't just "return" a list, the caller has to pass a buffer as well as a length. Can I take x1 and x2 as floats already stored in the buffer? (i.e. a function that continues a sequence for N more values). Otherwise I'll just take them as floats or integers on the stack or in registers, depending on whether I decide to go for 64-bit or 32-bit code, and System V calling convention or custom. – Peter Cordes – 2016-11-27T08:10:51.410

Answers

3

MATL, 19 18 17 bytes

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

Input is in the format: N (0-based), x(1), x(2) (as strings); all separated by newlines.

Try it online! Or verify all test cases (slightly modified code; output sequences separated by a blank line).

Explanation

MATL doesn't have a proper eval function, but U (str2num) can evaluate numeric expressions with infix operators.

Each new term is computed and pushed onto the stack, keeping the previous terms. The entire stack is printed at the end.

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

Luis Mendo

Posted 2016-11-25T22:25:45.700

Reputation: 87 464

8

Haskell, 69 68 64 bytes

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

x1 and x2 are taken as a list. Usage example: [1,3] # 8 -> [1.0,3.0,4.0,12.0,-8.0,-1.5,-9.5,14.25].

Laziness makes it possible to define an infinite recursive list where we take the first n elements.

Haskell, 66 bytes

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

Different approach, slightly longer. Argument order is N, x2, x1. Usage example: ( (.a).(.).take ) 8 3 1 -> [1.0,3.0,4.0,12.0,-8.0,-1.5,-9.5,14.25].

Defines 4 functions a, b, c and d which take two arguments y, x and make a list by putting x in front of a call to the next function with y as the second argument and x op y as the first. For example a is: a y x = x : (b (x+y) y), b does multiplication: b y x = x : (c (x*y) y), etc.

Edit: @Michael Klein saved a byte in the 1st variant (#). Luckily I also found one byte for the second variant, so both have the same length again.

Edit II: @Zgarb found 2 bytes in the second version to save, and I 4 in the first, so they are no longer of the same length.

nimi

Posted 2016-11-25T22:25:45.700

Reputation: 34 639

Accept the arguments as a list (allowed) for a byte – Michael Klein – 2016-11-26T02:40:54.993

I always get confused if (.) is composed with other functions :p – tomsmeding – 2016-11-26T15:30:10.700

g x=(`take`f)where doesn't save a byte :-/ – Bergi – 2016-11-26T16:27:33.790

Save 2 bytes in the alternative approach: (h%g)y x=x:g(h x y)y – Zgarb – 2016-11-28T18:16:40.183

@Zgarb: oh, that's nice. Thanks! BTW, when editing in your suggestions I found 4 bytes to save along the way in the first version. – nimi – 2016-11-28T18:47:22.880

6

ES6 (Javascript), 79, 67, 65 bytes

UPDATE

  • minus 2 bytes, by starting with i=2, as suggested by @ETHProductions
  • Saved 3 bytes, thanks to excellent advice from @Neil !

Golfed

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

Test

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

zeppelin

Posted 2016-11-25T22:25:45.700

Reputation: 7 884

@ETHproduction Yep, but I would have to pay them back by changing a[i] => a[i-2] – zeppelin – 2016-11-25T23:38:26.110

Ah, missed that. – ETHproductions – 2016-11-25T23:39:33.737

1Can you not use ++i to avoid having to add 1 to i twice? – Neil – 2016-11-26T00:03:37.713

1Or, alternatively, writing ?S(n,a,i+1,a.push(...)):a might save you some bytes. – Neil – 2016-11-26T00:05:23.957

1Or maybe you could use the fact that a.push returns the new length, S=(n,a,i=2)=>i<n?S(n,a,a.push(...)):a – Neil – 2016-11-26T00:06:35.593

@Neil, I've made use of a push return value, and a prefix increment for it, and that saved me the whole 3 bytes ! Thank you ! – zeppelin – 2016-11-26T00:15:29.273

1I still think you can save more bytes by starting at i=2 though. – Neil – 2016-11-26T00:48:00.297

1With Neil's suggestion, I think you can do S=(n,a,i=2)=>i<n?S(n,a,a.push(eval(a[i-2]+"+*-/"[i%4]+a[i-1]))):a to save 2 bytes. – ETHproductions – 2016-11-26T04:00:57.910

@ETHProductions, works now ! Minus 2 bytes ! Thank you ! Note that I also had to remap operators from "+-/" => "-/+" (as i%4 yield them in a different order now). – zeppelin – 2016-11-26T09:32:47.750

5

Python 3, 90 80 74 bytes

xnor's probably going to come and destroy this solution...

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

The function modifies the list passed to it. Use like this:

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

Try on repl.it!

-6 bytes thanks to Copper

FlipTack

Posted 2016-11-25T22:25:45.700

Reputation: 13 242

Since you only use O once, you can save a few bytes by doing '-/+*'[i%4] and removing the declaration of O. Also, you might be able to get around the repeated calls to str by doing something like eval('%s'*3%(s[-2],'-/+*'[i%4],s[-1])). – Copper – 2016-11-25T23:08:07.830

Oh yeah, and s+=[...] can be replaced by s+=..., (note the trailing comma). – Copper – 2016-11-25T23:12:56.770

xnor is not the only one that can destroy your solution. There is another person too: Dennis (the mod). – Erik the Outgolfer – 2016-11-26T09:04:18.433

You're guaranteed to get i as input, so you don't need the default value for it (i=2 can be just i). Two bytes off. – ArtOfCode – 2016-11-26T14:24:03.407

@ArtOfCode no, argument 1 is the list and argument 2 is the number of terms to calculate up to. i is just a counter I am using. Read the "usage" section at the bottom... – FlipTack – 2016-11-26T14:26:28.617

1If it was allowed to return the nth item in the sequence instead, this is 1 byte shorter with recursion: f=lambda x,n:n<2and x[n-1]or eval('%s'*3%(f(x,n-2),'*-/+'[n%4],f(x,n-1))) – mbomb007 – 2016-12-12T22:26:25.793

Never mind. It'd have to be adjusted for x values of 0 to work. Wishful thinking... so it'd have to use ...if...else, making it the same length. – mbomb007 – 2016-12-12T22:29:23.457

5

Perl 6,  75 71  61 bytes

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

Test it

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

Test it

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

Test it

Expanded:

{ # 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

  ]
}

Brad Gilbert b2gills

Posted 2016-11-25T22:25:45.700

Reputation: 12 713

4

Mathematica, 68 bytes

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

Barely snuck into 3rd place! Unnamed function of three arguments, which uses a helper unary operator ± such that ±n is exactly the nth element x(n) of the Stewie sequence. The first two arguments are x(1) and x(2), and the third argument is the N indicating which x(N) we output.

Direct implementation, using a mod-4 calculation to choose which binary function to apply to the previous two terms. Picking the correct binary function, which is what 1##[#-#2,#/#2,+##] helps with, uses a few of these fun Mathematica golfing tricks.

Greg Martin

Posted 2016-11-25T22:25:45.700

Reputation: 13 940

4

x86-64 machine code, 34 bytes

Calling convention = x86-64 System V x32 ABI (register args with 32-bit pointers in long mode).

The function signature is void stewie_x87_1reg(float *seq_buf, unsigned Nterms);. The function receives the x0 and x1 seed values in the first two elements of the array, and extends the sequence out to at least N more elements. The buffer must be padded out to 2 + N-rounded-up-to-next-multiple-of-4. (i.e. 2 + ((N+3)&~3), or just N+5).

Requiring padded buffers is normal in assembly for high-performance or SIMD-vectorized functions, and this unrolled loop is similar, so I don't think it's bending the rules too far. The caller can easily (and should) ignore all the padding elements.

Passing x0 and x1 as a function arg not already in the buffer would cost us only 3 bytes (for a movlps [rdi], xmm0 or movups [rdi], xmm0), although this would be a non-standard calling convention since System V passes struct{ float x,y; }; in two separate XMM registers.

This is objdump -drw -Mintel output with a bit of formatting to add comments

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

This C reference implementation compiles (with gcc -Os) to somewhat similar code. gcc picks the same strategy I did, of keeping just one previous value in a register.

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

I did experiment with other ways, including a two-register x87 version that has code like:

; 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

You'd do it this way if you were going for speed (and SSE wasn't available)

Putting the loads from memory inside the loop instead of once on entry might have helped, since we could just store the sub and div results out of order, but still it needs two FLD instructions to set up the stack on entry.

I also tried using SSE/AVX scalar math (starting with values in xmm0 and xmm1), but the larger instruction size is killer. Using addps (since that's 1B shorter than addss) helps a tiny bit. I used AVX VEX-prefixes for non-commutative instructions, since VSUBSS is only one byte longer than SUBPS (and the same length as 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

Tested with this test-harness:

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

Compile with nasm -felfx32 -Worphan-labels -gdwarf2 golf-stewie-sequence.asm &&
gcc -mx32 -o stewie -Og -g golf-stewie-sequence.c golf-stewie-sequence.o

Run the first test-case with ./stewie 8 1 3

If you don't have x32 libraries installed, use nasm -felf64 and leave gcc using the default -m64. I used malloc instead of float seqbuf[seqlen+8] (on the stack) to get a low address without having to actually build as x32.


Fun fact: YASM has a bug: it uses a rel32 jcc for the loop branch, when the branch target has the same address as a global symbol.

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

assembles to ... 11f: 0f 8f db ff ff ff jg 100 <stewie_x87_1reg>

Peter Cordes

Posted 2016-11-25T22:25:45.700

Reputation: 2 810

Very nice! You beat me to a similar approach by over three years! The problem seemed to lend itself nicely to x87 stack-based operations. – 640KB – 2020-01-05T16:24:00.133

@640KB: yeah, the r forms of non-commutative operations make the stack nature of x87 bearable. IDK about "nicely"; making it small introduced a bunch of store/reloads instead of just reading both previous sequence values from registers like we can with the AVX version. – Peter Cordes – 2020-01-05T16:34:02.417

Fair enough, "nicely" is probably putting it nicely. I didn't get very far since I saw your answer before I even started. If I'm reading it right it looks like this will always run through the +,*,-,/ pattern before stopping. Will it handle the N=5 / division by 0 test case? – 640KB – 2020-01-05T17:04:15.550

@640KB: fdiv doesn't trap on division by zero with the default FP environment, merely produce a NaN. It's been 3 years since I looked at this, but presumably that was fine. (By default after finit, FP exceptions are masked. Mainstream OSes / C implementations use that same x87 environment by default). – Peter Cordes – 2020-01-05T17:40:07.617

Of course! If an exception falls in the woods, does anyone hear it? :) – 640KB – 2020-01-05T19:05:57.953

@640KB: yes, actually, it sets a sticky flag in the x87 status word register :P (Or for SSE/AVX, in MXCSR) See also How to force GCC to assume that a floating-point expression is non-negative? for a summary of how C exposes this via fenv.h and fetestexcept() / feclearexcept

– Peter Cordes – 2020-01-05T19:18:38.563

3

05AB1E, 21 19 18 bytes

Input is taken in the order N(0-based), x(2), x(1).
Saved 1 byte thanks to carusocomputing.

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

Try it online!

Explanation

 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

We iteratively build the stack with the latest element in the sequence on top, while keeping all previous elements in order.
Then we wrap the stack in a list at the end to display all values at once.

Emigna

Posted 2016-11-25T22:25:45.700

Reputation: 50 798

1I couldn't figure it out, but using XY and UV may save you bytes. – Magic Octopus Urn – 2016-11-28T17:14:20.960

1@carusocomputing: Nice catch! Saved the byte I lost from the register not working on implicit input using UX :) – Emigna – 2016-11-28T18:11:36.303

2

Common Lisp, 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)))

Not really competitive, but I like how it is is expressed quite naturally:

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

We ignore errors when computing R, which makes R (and then B) possibly take the NIL value. That allows to output the current result even if the next value is undefined. Then, eventually the loop will fail, but that's within the rules.

Tests

We name the function F and verify that the expected values are approximately equal to the tested one.

(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

The reason for the approximate test is because the computed values are a little more precise than required; here, for (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)

coredump

Posted 2016-11-25T22:25:45.700

Reputation: 6 292

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

Sometimes dc answers can be super long, and sometimes they can be super short. It all just depends on the challenge at hand as is the case with many other languages. Anyways, this prompts for a space-separated one-indexed command line input of 3 integers, x(1), x(2), N, upon invocation, and outputs each element of the sequence on separate lines with non-integer outputs containing 5 digits after the decimal point.

For example, the input 6 3 25 results in the following output:

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

R. Kap

Posted 2016-11-25T22:25:45.700

Reputation: 4 730

2

Perl, 62 + 3 (-pla flag) = 65 bytes

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

Using:

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

Denis Ibaev

Posted 2016-11-25T22:25:45.700

Reputation: 876

2

05AB1E, 12 bytes

λ£"-/+*"Nè.V

Try it online!

Grimmy

Posted 2016-11-25T22:25:45.700

Reputation: 12 521

2

Haskell, 60 bytes

g(o:z)a b=a:g z b(o a b)
p=(+):(*):(-):(/):p
(.g p).(.).take

Try it online!

Ungolfed:

ungolfed :: Int -> Double -> Double -> [Double]                                
ungolfed len x1 x2 = take len $ go (cycle [(+),(*),(-),(/)]) x1 x2
    where go (f:fs) x y = x : go fs y (f x y)

Knowing \x -> f x == f, \x -> f $ g x == f . g, and some other patterns, you can transform a normal (point-full) function into a point-free one:

f0 len x1 x2 = take len $ go p x1 x2
f1 len = \x1 x2 -> take len $ go p x1 x2
f2 len = \x1 -> take len . go p x1
f3 len = (take len .) . go p
f4 = \len -> (. go p) (take len .)
f5 = \len -> (. go p) ((.) (take len))
f6 = \len -> (. go p) . (.) $ take len
f7 = \len -> ((. go p) . (.) . take) len
f8 = (. go p) . (.) . take

\x y -> f $ g x y == (f.) . g is also a common pattern.

You could also read this backwards for adding back arguments to a point-free function.

Trioct

Posted 2016-11-25T22:25:45.700

Reputation: 21

Welcome to PPCG and nice first answer! I'd appreciate an explanation of the decomposition of (.g p).(.).take into take len $ go p x1 x2 – user41805 – 2020-01-07T17:20:49.870

@KritixiLithos To be honest, I used http://pointfree.io, but I've worked it out and added the transformation from point-full to point-free. Hopefully it's clear (and correct) enough.

– Trioct – 2020-01-08T01:08:37.450

1

Ruby, 79 bytes

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

I suspect this is very far off from optimal (and I haven't looked at the other answers yet), but it's fun nonetheless.

I wanted to have some fun with Enumerable#cycle, but sadly, it's 4 fewer characters to just use %4.

philomory

Posted 2016-11-25T22:25:45.700

Reputation: 153

1

C++14, 118 bytes

[](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);}

As unnamed lambda modifying its input. Requires v to be a vector<double> or vector<float>.

Ungolfed and usage:

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

Karl Napf

Posted 2016-11-25T22:25:45.700

Reputation: 4 131

1

Japt, 20 bytes

@OxVs2n)q"-/+*"gY}hV

Try it

Shaggy

Posted 2016-11-25T22:25:45.700

Reputation: 24 623

1

J, 49 33 29 bytes

[$_2&(],(-,%,+,*)/@{.{~4|#@])

Try it online!

-4 bytes thanks to FrownFrog

Jonah

Posted 2016-11-25T22:25:45.700

Reputation: 8 729

[$_2&(],(-,%,+,*)/@{.{~4|#@]) – FrownyFrog – 2020-01-08T06:39:06.697

Tyvm! I always forget about that little trick with Bond. – Jonah – 2020-01-08T19:02:28.787

1

PowerShell, 66 60 58 bytes

-8 bytes thanks to mazzy

param($a,$b)3..$a|%{$b+=$b[-2,-1]-join"*-/+"[$_%4]|iex}
$b

Try it online!

Builds x(n) in place by making a string out of x(n-2) and x(n-1), joined by the operator we need (determined by modulo math using the index we get for free from iterating up), and feeds it into invokeExpression. We then spit out the final array.

Veskah

Posted 2016-11-25T22:25:45.700

Reputation: 3 580

1

nice! $b is array, so you don't need brackets ,(...). Try it online!

– mazzy – 2020-01-07T18:49:18.240

@mazzy Ah, cheers. Smart move on the join as well. – Veskah – 2020-01-07T18:54:20.477

1

also we can remove ++ Try it online!

– mazzy – 2020-01-07T19:04:24.430

1@mazzy Oh yeah, guess we do already have something counting up. Nice – Veskah – 2020-01-07T19:12:11.303

0

Bash, 224 bytes (NO CONTEST)

A tremendously large implementation in BASH.

Takes the task quite literally, and does everything in one continuous pipe, w/o any unholy control flow structures or recursion.

Input

$1,$2 - initial elements

$3 - target sequence size

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

Less 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

Test

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

Pipeline Stages

Generate a table of element indices + op, for an each output sequence element (one per line):

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

Use sed to convert this into a linear bc program:

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

feed this to bc and let it do all the job

zeppelin

Posted 2016-11-25T22:25:45.700

Reputation: 7 884

0

Pyth - 20 bytes

Outputting all n costs me.

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

Doesn't work online cuz of eval.

Maltysen

Posted 2016-11-25T22:25:45.700

Reputation: 25 023

0

Ceylon, 195 bytes

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;

Formatted and commented:

// 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;

Example usage:

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

Example output:

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

The second example shows how this would handle division by zero. The last example shows that the results deviate a bit depending on which kind of arithmetic (and rounding) one is using ... I think Ceylon's 64 bit floating point arithmetic is a bit nearer to what it should be than what was posted in the question.

Paŭlo Ebermann

Posted 2016-11-25T22:25:45.700

Reputation: 1 010

0

Clojure, 99 bytes

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

This version is nicer to use in practice but has 110 bytes:

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

I had trouble fuzing iterated function and a cyclical sequence of operations so I had to use a counter instead. Also tried using a FSM transition table like {+ * * - - / / +} but I couldn't squeeze it to less code.

Could be expressed as an anonymous function

Un-golfed:

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

Must be called with floats like (f 6.0 3.0 25) as otherwise you get rational numbers out. Alternatively the iteration could be started from [a (float b) 0] which brings some extra characters.

NikoNyrh

Posted 2016-11-25T22:25:45.700

Reputation: 2 361

0

Octave, 91 bytes

@(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'

Try it online!

Some golfs:

  • No parentheses for the first eval call
  • No concatenations for the first eval call
  • Inline assignment of *-/+ (not possible in MATLAB)
  • Combined ' and " to avoid escaping the apostrophes (not possible in MATLAB)
  • Storing n=@num2str since it's used twice (not possible in MATLAB)

CG.

Posted 2016-11-25T22:25:45.700

Reputation: 401

0

cQuents, 19 bytes

=A,B&Y+Z,YZ,Y-Z,Y/Z

Try it online!

Explanation

Receives three inputs, A B n

=A,B                   first two terms in sequence are A and B
    &                  output first n terms of sequence
     Y+Z,YZ,Y-Z,Y/Z    next terms are Y+Z, then Y*Z, ..., cycling back to beginning after 4th
                       Y and Z are the previous two terms in the sequence

Stephen

Posted 2016-11-25T22:25:45.700

Reputation: 12 293