Counting Fountains

17

1

A fountain is arrangement of coins in rows so that each coin touches two coins in the row below it, or is in the bottom row, and the bottom row is connected. Here's a 21 coin fountain:

From http://mathworld.wolfram.com/Fountain.html


Your challenge is to count how many different fountains can be made with a given number of coins.

You will be given as input a positive integer n. You must output the number of different n-coin fountains that exist.

Standard I/O rules, standard loopholes banned. Solutions should be able to calculate n = 10 in under a minute.


Desired output for n = 1 ... 10:

1, 1, 2, 3, 5, 9, 15, 26, 45, 78

This sequence is OEIS A005169.


This is code golf. Fewest bytes wins.

isaacg

Posted 2015-12-26T10:21:17.700

Reputation: 39 268

Is there an n for which the program must be guaranteed to work? (i.e. after which it may break) – quintopia – 2015-12-26T19:42:45.627

@quintopia It should work for all n, up to limitations of datatype, hardware, etc. – isaacg – 2015-12-26T19:47:57.213

Answers

3

Python, 57 bytes

f=lambda n,i=0:sum(f(n-j,j)for j in range(1,i+2)[:n])or 1

As observed on OEIS, if you shift each row half a step relative to the row below it, the column sizes form a sequence of positive integers with a maximum upward step of 1.

The function f(n,i) counts the sequences with sum n and last number i. These can be recursively summed for each choice of the next column size from 1 to i+1, which is range(1,i+2). Truncating to range(1,i+2)[:n] prevents columns from using more coins than remain, avoiding needing to say that negative n's give 0. Moreover, it avoids an explicit base case, since the empty sum is 0 and doesn't recurse, but f(0) needs to be set to 1 instead, for which or 1 suffices (as would +0**n).

xnor

Posted 2015-12-26T10:21:17.700

Reputation: 115 687

17 bytes in Pyth: M|sgL-Gd<ShHG1gQ0 – isaacg – 2015-12-27T07:09:12.047

5

Mathematica, 59 bytes

SeriesCoefficient[1-Fold[1-x^#2/#&,Range[#,0,-1]],{x,0,#}]&

Based on the Mathematica program on OEIS by Jean-François Alcover.

alephalpha

Posted 2015-12-26T10:21:17.700

Reputation: 23 988

Can you rewrite this as a formula (I just want to compare with the formula I found)? I just cannot read Mathematica=) – flawr – 2015-12-26T11:32:17.847

@flawr The generating function of the sequence is 1/(1-x/(1-x^2/(1-x^3/(1-x^4/(1-x^5/(...)))))). – alephalpha – 2015-12-26T11:35:35.793

Thanks for the explanation, that is indeed a nice approach if you have such a powerfull CAS=) – flawr – 2015-12-26T11:37:22.210

3

Haskell, 60 48 bytes

Thanks to @nimi for providing a way shorter solution!

n#p|p>n=0|p<n=sum$map((n-p)#)[1..p+1]|1<2=1
(#1)

Old version.

t n p|p>n=0|p==n=1|p<n=sum[t (n-q) q|q<-[1..p+1]]
s n=t n 1

The function calculating the value is s, implementation of the recursive formula found here: https://oeis.org/A005169

flawr

Posted 2015-12-26T10:21:17.700

Reputation: 40 560

A bug: the recursive call is t (n-p) q. Golfing tips: use an infix operator for t, swap the guards and use map instead of the list comprehension: n#p|p>n=0|p<n=sum$map((n-p)#)[1..p+1]|1<2=1. s becomes s=(#1), but you don't have to give the main function a name at all, so (#1) is enough. 48 bytes. – nimi – 2015-12-26T21:04:08.333

Thanks you very much for the hints! I just started learning the basics of Haskell. I'm going to have to learn about that how the usage of # and $ here first=) – flawr – 2015-12-26T21:09:42.930

A little bit of explanation: # is a user defined infix function just like +, *, etc. are predefined infix functions. $ is another way to adjust precedence (besides parentheses) f (g (h x))-> f$g$h x or in our case sum(map(...)[...]) -> sum$map(...)[...]. – nimi – 2015-12-26T21:17:01.270

Thank you, that is quite useful to know, I appreciate your explanation! – flawr – 2015-12-26T21:27:17.853

3

Pyth, 21 20 bytes

Ms?>GHgL-GHShHqGHgQ1

Try it online. Test suite.

This is a direct implementation of the recursive formula on the OEIS page, like the Matlab answer.

PurkkaKoodari

Posted 2015-12-26T10:21:17.700

Reputation: 16 699

3

Haskell, 43 bytes

n%i=sum[(n-j)%j|j<-take n[1..i+1]]+0^n
(%0)

See Python answer for explanation.

Same length with min rather than take:

n%i=sum[(n-j)%j|j<-[1..min(i+1)n]]+0^n
(%0)

xnor

Posted 2015-12-26T10:21:17.700

Reputation: 115 687

1

Matlab, 115 105 bytes

function F=t(n,varargin);p=1;if nargin>1;p=varargin{1};end;F=p==n;if p<n;for q=1:p+1;F=F+t(n-p,q);end;end

Implementation of the recursive formula found here: https://oeis.org/A005169

function F=t(n,varargin);
p=1;
if nargin>1
    p=varargin{1};
end;
F=p==n;
if p<n;
    for q=1:p+1;
        F=F+t(n-p,q);
    end;
end;

flawr

Posted 2015-12-26T10:21:17.700

Reputation: 40 560

1

Julia, 44 43 bytes

f(a,b=1)=a>b?sum(i->f(a-b,i),1:b+1):1(a==b)

This uses recursive formula on OEIS.

Explanation

function f(a, b=1)
    if a > b
        # Sum of recursing
        sum(i -> f(a-b, i), 1:b+1)
    else
        # Convert bool to integer
        1 * (a == b)
    end
end

Has anyone else noticed that strike through 44 is regular 44??

Fax Machine

Posted 2015-12-26T10:21:17.700

Reputation: 221

0

Python 3, 88 bytes

f=lambda n,p:sum([f(n-p,q)for q in range(1,p+2)])if p<n else int(p==n)
t=lambda n:f(n,1)

monopole

Posted 2015-12-26T10:21:17.700

Reputation: 1 559

0

JavaScript (ES6), 63

Implementing the recursive formula at OEIS page

F=(n,p=1,t=0,q=0)=>p<n?eval("for(;q++<=p;)t+=F(n-p,q)"):p>n?0:1

edc65

Posted 2015-12-26T10:21:17.700

Reputation: 31 086