1, 2, 4, 8, 16, ... 33?

25

2

Challenge

Write a function/program that outputs either the n'th element, or the first n elements, in the well known number sequence:

         1, 2, 4, 8, 16 ...

Oh, wait... I forgot the first few numbers:

1, 1, 1, 1, 2, 4, 8, 16 ...

Heck, I'll add a few more for good measure:

1, 1, 1, 1, 2, 4, 8, 16, 33, 69, 146, 312, 673, 1463, 3202, 7050, 15605, 34705 ...

The numbers are Generalized Catalan numbers given by the (zero-indexed) formula:

$$a(n+1)= a(n) + \sum_{k=2}^{n-1} a(k)\cdot a(n-1-k)$$

where

$$a(0)= a(1)= a(2)= a(3) = 1$$

This is OEIS A004149.

You may choose if you want to have the sequence zero- or one-indexed. The sequence must of course be the same, so you must rewrite the formula if you have it one-indexed.

Stewie Griffin

Posted 2019-09-19T12:10:49.870

Reputation: 43 471

Correct me if I'm wrong here, but the modification for a one-indexed formula is to change a(n-1-k) to a(n-k) , correct? – Sumner18 – 2019-09-19T14:08:37.223

9

This reminds me of The strong law of small numbers

– Luis Mendo – 2019-09-19T14:13:31.340

Answers

23

Python, 51 bytes

f=lambda n,k=2:n<3or k<n and f(k)*f(n-k-2)+f(n,k+1)

Try it online!

Simplifies the formula a bit:

$$a(n) = \sum_{k=2}^{n-1} a(k)\cdot a(n-2-k)$$

$$ a(-1) = a(0)= a(1)= a(2) = 1$$

xnor

Posted 2019-09-19T12:10:49.870

Reputation: 115 687

8Congrats on the 100k!! – Stewie Griffin – 2019-09-19T17:39:10.763

Since I also arrived to this solution independently, I must say that the path towards it is a bit bumpy... – Erik the Outgolfer – 2019-09-19T23:43:12.877

10

Perl 6, 44 bytes

{1,1,1,1,{sum @_[2..*]Z*@_[@_-4...0,0]}...*}

Try it online!

Anonymous code block that returns a lazy infinite sequence of values. This pretty much implements the sequence as described, with the shortcut that it zip multiplies all the elements so far after the second element with the reverse of the list starting from the fourth element and adding an extra 1 at the end.

Explanation:

{                                          }  # Anonymous code block
                                       ...*   # Create an infinite sequence
 1,1,1,1,                                     # Starting with four 1s
         {                            }       # Where each new element is:
          sum                                   # The sum of
              @_[2..*]                          # The second element onwards
                      Z*                        # Zip multiplied with
                        @_[@_-4...0  ]          # The fourth last element backwards
                                   ,0           # And 1

Jo King

Posted 2019-09-19T12:10:49.870

Reputation: 38 234

10

05AB1E, 14 13 11 bytes

$ƒˆ¯Âø¨¨¨PO

Try it online!

Outputs the nth element, 0-indexed.

$                # push 1 and the input
 ƒ               # repeat (input+1) times
  ˆ              #  add the top of the stack (initially 1) to the global array
   ¯             #  push the global array
    Â            #  and a reversed copy of it
     ø           #  zip the two together, giving a list of pairs
      ¨¨¨        #  drop the last 3 pairs
         P       #  take the product of each pair (or 1 if the list is empty)
          O      #  take the sum of those products
                 #  after the last iteration, this is implicitly output;
                 #  otherwise, it's added to the global array by the next iteration

Grimmy

Posted 2019-09-19T12:10:49.870

Reputation: 12 521

7

JavaScript (ES6), 42 bytes

A port of xnor's solution.

0-indexed.

f=(n,k=2)=>n<3||k<n&&f(k)*f(n+~++k)+f(n,k)

Try it online!


JavaScript (ES6),  83  75 bytes

A faster, less recursive, but significantly longer solution.

0-indexed.

f=(n,i,a=[p=1])=>a[n]||f(n,-~i,[...a,p+=(h=k=>k<i&&a[k]*a[i-++k]+h(k))(2)])

Try it online!

Arnauld

Posted 2019-09-19T12:10:49.870

Reputation: 111 334

7

Haskell, 49 43 39 bytes

a n=max(sum[a k*a(n-2-k)|k<-[2..n-1]])1              

Try it online!

For n<3 the sum is 0, so max ... 1 raises it to 1.

Edit: -6 bytes thanks to @Jo King.

nimi

Posted 2019-09-19T12:10:49.870

Reputation: 34 639

6

Wolfram Language (Mathematica), 36 bytes

Sum[#0@i#0[#-i-1],{i,3,#-1}]/. 0->1&

Try it online!

1-indexed.

The 2-indexed sequence is 4 bytes shorter: Sum[#0@i#0[#-i],{i,#-4}]/. 0->1&. Try it online!

attinat

Posted 2019-09-19T12:10:49.870

Reputation: 3 495

2Impressive that this is shorter than the built in CatalanNumber ! – erfink – 2019-09-20T22:20:26.213

6

05AB1E, 17 13 bytes

4Å1λ£₁λ¨Â¦¦s¦¦*O+

Not shorter than the existing 05AB1E answer, but I wanted to try the recursive functionality of the new 05AB1E version as practice for myself. Could perhaps be golfed by a few bytes. EDIT: And it indeed can, see the recursive version of @Grimy's 05AB1E answer below, which is 13 bytes.

Outputs the first \$n\$ items: Try it online.

Could be changed to the 0-based \$n\$'th item when replacing £ with è: Try it online;
or an infinite list by removing £: Try it online.

Explanation:

This implements the formula used in the challenge description like this:
\$a(n)= a(n-1) + \sum_{k=2}^{n-1}(a(k)\cdot a(n-1-k))\$

\$a(0)=a(1)=a(2)=a(3)=1\$

   λ               # Create a recursive environment,
    £              # to output the first (implicit) input amount of results after we're done
4Å1                # Start this recursive list with [1,1,1,1], thus a(0)=a(1)=a(2)=a(3)=1
                   # Within the recursive environment, do the following:
      λ            #  Push the list of values in the range [a(0),a(n)]
       ¨           #  Remove the last one to make the range [a(0),a(n-1)]
        Â          #  Bifurcate this list (short for Duplicate & Reverse copy)
         ¦¦        #  Remove the first two items of the reversed list,
                   #  so we'll have a list with the values in the range [a(n-3),a(0)]
           s       #  Swap to get the [a(0),a(n-1)] list again
            ¦¦     #  Remove the first two items of this list as well,
                   #  so we'll have a list with the values in the range [a(2),a(n-1)]
              *    #  Multiply the values at the same indices in both lists,
                   #  so we'll have a list with the values [a(n-3)*a(2),...,a(0)*a(n-1)]
               O   #  Take the sum of this list
     ₁          +  #  And add it to the a(n-1)'th value
                   # (afterwards the resulting list is output implicitly)

13 bytes version of @Grimy (make sure to upvote his answer if you haven't yet!):

1λ£λ1šÂ¨¨¨øPO

Outputs the first \$n\$ items: Try it online.

Can again be changed to 0-based indexing or an infinite list instead:
- (0-based) indexing 1λèλ1šÂ¨¨¨øPO: Try it online;
- Infinite list λλ1šÂ¨¨¨øPO: Try it online. (Note that 2 bytes are saved here instead of 1, because the recursive environment starts with \$a(0)=1\$ by default.)

Explanation:

This instead implements the formula found by @xnor for his Python answer like this:
\$a(n) = \sum_{k=2}^{n-1}(a(k)\cdot a(n-2-k))\$

\$a(-1) = a(0) = a(1) = a(2) = 1\$

 λ             # Create a recursive environment,
  £            # to output the first (implicit) input amount of results after we're done
1              # Start this recursive list with 1, thus a(0)=1
               # Within the recursive environment, do the following:
   λ           #  Push the list of values in the range [a(0),a(n)]
    1š         #  Prepend 1 in front of this list
      Â        #  Bifurcate the list (short for Duplicate & Reverse copy)
       ¨¨¨     #  Remove (up to) the last three value in this reversed list
          ø    #  Create pairs with the list we bifurcated earlier
               #  (which will automatically remove any trailing items of the longer list)
           P   #  Get the product of each pair (which will result in 1 for an empty list)
            O  #  And sum the entire list
               # (afterwards the resulting list is output implicitly)

Kevin Cruijssen

Posted 2019-09-19T12:10:49.870

Reputation: 67 575

1Interesting that this can solve a(1200) in 40 second on tio, while other recursive approaches time out for numbers n than 100... – Stewie Griffin – 2019-09-20T10:32:38.837

1

I also made (but didn't publish) a recursive version. It's 13 bytes for the first n terms, or 11 bytes for an infinite list. Special-casing a(n-1) costs a lot of bytes and isn't needed (see for example xnor's formula).

– Grimmy – 2019-09-20T11:00:36.343

@Grimy Do you mind if I add your recursive solutions to my answer (crediting you of course)? I will leave my original answer as well. But it's nice to see the differences between the original formula and xnor's byte-saving formula. :) – Kevin Cruijssen – 2019-09-20T11:47:43.497

1Sure, that's fine! – Grimmy – 2019-09-20T11:50:28.563

@StewieGriffin Yeah, I was also impressed by the speed of these recursive infinite functions. Maybe one of Elixir's strengths, and definitely due to the builtin lazy-loading. It calculates n=100 in 0.65 seconds, but when I disable lazy-loading, it will time out after 60 seconds instead, even for n=25.

– Kevin Cruijssen – 2019-09-20T11:53:21.050

5

Python 3, 59 bytes

really inefficient, a(13) doesn't finish on TIO.

a=lambda n,k=2:n<4or(n-k<2)*a(n-1)or a(k)*a(n-k-2)+a(n,k+1)

Try it online!

ovs

Posted 2019-09-19T12:10:49.870

Reputation: 21 408

3

Jelly, 17 bytes

1WṪ;+¥×Uṫ3SƲ;@Ʋ⁸¡

Try it online!

A monadic link taking the zero-indexed \$n\$ and returning the list of generalized Catalan numbers from \$0\$ to \$n\$.

Nick Kennedy

Posted 2019-09-19T12:10:49.870

Reputation: 11 829

2

APL (Dyalog Extended), 34 bytesSBCS

-2 thanks to dzaima.

Anonymous prefix lambda.

{⍵≤3:1⋄+/(∇⍵-1),⍵(-×⍥∇¯2+⊢)¨4…⍵}

Try it online!

Adám

Posted 2019-09-19T12:10:49.870

Reputation: 37 779

@dzaima Thanks. TFW someone knows my language better than me :-) – Adám – 2019-09-19T13:59:57.727

2

Haskell, 76 bytes

1:1:1:f[1,1,1]
f(x:z)|y<-x+sum(zipWith(*)(init$init z)$reverse z)=y:f(y:x:z)

Try it online!

flawr

Posted 2019-09-19T12:10:49.870

Reputation: 40 560

2

Japt, 19 17 16 bytes

Outputs the nth term, 1-indexed.

@Zí*Zz2)Ťx}g4Æ1

Try it

@Zí*Zz2)Ťx}g4Æ1     :Implicit input of integer U
@                    :Function taking an array as an argument via parameter Z
 Zí                  :  Interleave Z with
    Zz2              :  Z rotated clockwise by 180 degrees (simply reversing would be a bye shorter but would modify the original array)
   *                 :  Reduce each pair by multiplcation
       )             :  End interleave
        Å            :  Slice off the first element
         ¤           :  Slice off the first 2 elements
          x          :  Reduce by addition
           }         :End function
            g        :Pass the following as Z, push the result back to it and repeat until it has length U
             4Æ1     :Map the range [0,4) to 1s
                     :Implicit output of the last element

Shaggy

Posted 2019-09-19T12:10:49.870

Reputation: 24 623

1

Haskell, 65 bytes

f a|a<4=1|z<-g[2..a]=sum$zipWith(*)z$reverse(1:g[0..a-4])
g=map f

Try it online!

You can use either f to get a single element of a sequence, or pass a list of values to g and get all the indexes for that list.

Jo King

Posted 2019-09-19T12:10:49.870

Reputation: 38 234

1

Ruby, 42 41 bytes

f=->n{n<4?1:(4..n).sum{|i|f[i-1]*f[n-i]}}

Try it online!

1-indexed (to save 1 byte)

G B

Posted 2019-09-19T12:10:49.870

Reputation: 11 099

1

Octave, 73 bytes

g=(1:4).^0;for(i=3:(n=input('')))g(i+2)=g(4:i+1)*g(i-(2:i-1))';end;g(end)

Try it online!

-2 bytes thanks to Stewie Griffin. Once more, the imperative approach wins over the functional recursive approach. That one is shown below.

Octave, 75 bytes

f(f=@(a)@(n){@()sum(arrayfun(@(k)a(a)(k)*a(a)(n-2-k),2:n-1)),1}{2-(n>3)}())

Try it online!

Captcha wanted to verify I was a human when posting this. To be honest, I'm not so sure.

Sanchises

Posted 2019-09-19T12:10:49.870

Reputation: 8 530

I can't see any obvious ways to shorten the loop approach... It looks pretty well golfed! Also, it's not often I see zero-based indexing in Octave :) – Stewie Griffin – 2019-09-20T12:50:49.410

@StewieGriffin Since the recursion has some offsets it doesn't really matter if you pick zero- or one indexing. I think maybe I could shave some bytes of if I did 2-indexing, but that seemed like cheating. Anyway, your intuition was right - somehow, this was indeed shorter in an anonymous recursive way. I think the main advantage is that it handles creating the four initial values very well because it just returns 1 for n<4. – Sanchises – 2019-09-20T13:00:00.780

1@StewieGriffin Of course, good old matrix multiplication. Well done! – Sanchises – 2019-09-22T15:49:29.413

1

Forth (gforth), 99 81 bytes

: f recursive dup 4 > if 0 over 3 do over 1- i - f i f * + loop else 1 then nip ;

Try it online!

Output is nth term and input is 1-indexed

Edit: Saved 17 bytes by switching to xnor's formula. Saved another 1 byte by using 1-indexed

Code Explanation

: f                     \ start a new word definition
  recursive             \ mark that this word will be recursive
  dup 4 >               \ duplicate the input and check if it is greater than 4
  if                    \ if it is:
    0 over              \ create an accumulator and copy n to top of stack
    3 do                \ start counted loop from 3 to n-1
      over 1- i - f     \ recursively calculate f(n-1-i)
      i f               \ recursively calculate f(i)
      * +               \ multiply results and add to accumulator
    loop                \ end the counted loop        
  else                  \ otherwise, if n < 5
    1                   \ put 1 on the stack
  then                  \ end the if block
  nip                   \ drop n from the stack
;                       \ end the word definition

reffu

Posted 2019-09-19T12:10:49.870

Reputation: 1 361

1

Charcoal, 26 bytes

F⁵⊞υ¹FN⊞υΣ✂E⮌υ×κ§υλ³→I§υ±⁴

Try it online! Link is to verbose version of code. Prints the 0-indexed nth number, although it calculates using 1-indexing internally. Explanation:

F⁵⊞υ¹

Start with a[0] = a[1] = a[2] = a[3] = a[4] = 1. Yes, this is 1-indexed, but then with an extra zeroth value. That's code golf for you.

FN

Calculate an additional n terms. This is overkill, but it makes finding the desired term easier when n<5.

⊞υΣ✂E⮌υ×κ§υλ³

For each term, compute the next term as the sum of the terms so far termwise multiplied by the reverse of the terms so far, excluding three terms.

This is a no-op used to trick Charcoal into parsing the 2-argument form of Slice, otherwise I would have to use a less golfy way of removing three terms.

I§υ±⁴

Output the 4th last term.

Neil

Posted 2019-09-19T12:10:49.870

Reputation: 95 035

1

Pyth, 30 bytes

J*4]1VQ=+J+eJsPP*M.t,PJ_PJ0;<J

Try it online!

Returns the first \$n\$ elements of the sequence.

J*4]1VQ=+J+eJsPP*M.t,PJ_PJ0;<JQ # Full program, last Q = input (implicitly added)
J*4]1                  # J = 4 * [1] (=[1,1,1,1])
VQ                     # for N in range(Q):
  =+J                  #  J +=
     +eJ               #   J[-1] + 
        s              #    sum(                           )
           *M          #     map(__operator_mul,          )
             .t      0 #      transpose(          , pad=0)
               ,       #       [       ,         ]
                PJ     #         J[:-1] 
                  _PJ  #                 J[1::-1]
<JQ                    # J[::Q]

Alternative: Replace < with @ to return the \$n\$-th element of the sequence, 0-indexed.

ar4093

Posted 2019-09-19T12:10:49.870

Reputation: 531

0

Perl 5 -MList::Util=sum, 61 bytes

sub a{my$b=-2+pop;$b<2||sum a($b+1),map{a($_)*a($b-$_)}2..$b}

Try it online!

Xcali

Posted 2019-09-19T12:10:49.870

Reputation: 7 671

0

C/C++, 70 69 67 bytes

-1 bytes thanks to Jonathan.

int a(int n){int k=2,s=0;while(++k<n)s+=a(k)*a(n+~k);return s?s:1;}

Try it online!

polfosol ఠ_ఠ

Posted 2019-09-19T12:10:49.870

Reputation: 519

Can a(n-1-k) be a(n+~k)? – Jonathan Frech – 2019-09-21T12:00:08.470

@JonathanFrech even a(++k)*a(n-k) is likely to work, and it drops further 2 bytes from for. But I smell undefined behavior. – polfosol ఠ_ఠ – 2019-09-21T12:25:55.727

That appears to be a sequencing issue; most definitely UB. – Jonathan Frech – 2019-09-21T18:16:01.967