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

24

Défi

Écrivez une fonction / un programme qui génère soit le n'e élément, soit les premiers néléments, dans la séquence de nombres bien connue:

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

Oh, attendez ... J'ai oublié les premiers chiffres:

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

Heck, je vais ajouter quelques autres pour faire bonne mesure:

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

Les nombres sont des nombres catalans généralisés donnés par la formule (indexée zéro):

a(n+1)=a(n)+k=2n1a(k)a(n1k)

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

Il s'agit d' OEIS A004149 .

Vous pouvez choisir si vous souhaitez que la séquence soit indexée à zéro ou à un. La séquence doit bien sûr être la même, vous devez donc réécrire la formule si vous l'avez à un index.

Stewie Griffin
la source
Corrigez-moi si je me trompe ici, mais la modification d'une formule à un index est de passer a(n-1-k)à a(n-k), n'est -ce pas?
Sumner18
9
Cela me rappelle la loi forte des petits nombres
Luis Mendo

Réponses:

23

Python , 51 octets

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

Essayez-le en ligne!

Simplifie un peu la formule:

a(n)=k=2n1a(k)a(n2k)

a(1)=a(0)=a(1)=a(2)=1

xnor
la source
8
Félicitations pour le 100k !!
Stewie Griffin
Puisque je suis également arrivé à cette solution indépendamment, je dois dire que le chemin vers elle est un peu cahoteux ...
Erik the Outgolfer
10

Perl 6 , 44 octets

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

Essayez-le en ligne!

Bloc de code anonyme qui renvoie une séquence de valeurs infinie paresseuse. Cela implémente à peu près la séquence telle que décrite, avec le raccourci qu'il multiplie par zip tous les éléments jusqu'à présent après le deuxième élément avec l'inverse de la liste à partir du quatrième élément et en ajoutant un supplémentaire 1à la fin.

Explication:

{                                          }  # 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
la source
10

05AB1E , 14 13 11 octets

$ƒˆ¯Âø¨¨¨PO

Essayez-le en ligne!

Génère le nième élément, indexé 0.

$                # 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
la source
7

JavaScript (ES6), 42 octets

Un port de la solution de xnor .

0 indexé.

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

Essayez-le en ligne!


JavaScript (ES6),  83  75 octets

Une solution plus rapide, moins récursive, mais nettement plus longue.

0 indexé.

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

Essayez-le en ligne!

Arnauld
la source
7

Haskell, 49 43 39 octets

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

Essayez-le en ligne!

Pour n<3le sumest 0, le fait max ... 1monter à1 .

Edit: -6 octets grâce à @Jo King.

nimi
la source
6

05AB1E , 17 13 octets

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

Pas plus court que la réponse 05AB1E existante , mais je voulais essayer la fonctionnalité récursive de la nouvelle version 05AB1E comme pratique pour moi-même. Pourrait peut-être être joué par quelques octets. EDIT: Et il peut en effet, voir la version récursive de @Grimy réponse 05AB1E s » ci - dessous, qui est de 13 octets .

Sort le premier narticles: Essayez-le en ligne .

Pourrait être changé en base 0 n'e élément lors du remplacement £par è: Essayez-le en ligne ;
ou une liste infinie en supprimant £: Essayez-le en ligne .

Explication:

Cela implémente la formule utilisée dans la description du défi comme ceci:
une(n)=une(n-1)+k=2n-1(une(k)une(n-1-k))

une(0)=une(1)=une(2)=une(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)

Version 13 octets de @Grimy (assurez-vous de voter pour sa réponse si vous ne l'avez pas encore fait):

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

Sort le premier 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)=k=2n1(a(k)a(n2k))

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
la source
1
Interesting that this can solve a(1200) in 40 second on tio, while other recursive approaches time out for numbers n than 100...
Stewie Griffin
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
@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
1
Sure, that's fine!
Grimmy
@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
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
la source
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
la source
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
la source
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
la source
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
la source
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
la source
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
la source
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
la source
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
la source
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
@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
1
@StewieGriffin Of course, good old matrix multiplication. Well done!
Sanchises
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 ఠ_ఠ
la source
Can a(n-1-k) be a(n+~k)?
Jonathan Frech
@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 ఠ_ఠ
That appears to be a sequencing issue; most definitely UB.
Jonathan Frech