Restricted Integer Partitions

8

Pk(n) means the amount of partitions of n into exactly k parts. Given n and k, calculate Pk(n).

Tip: Pk(n) = Pk(n−k) + Pk−1(n−1), with initial values p0(0) = 1 and pk(n) = 0 if n ≤ 0 or k ≤ 0. [Wiki]

Examples

n    k    Ans
1    1    1
2    2    1
4    2    2
6    2    3
10   3    8

Rules

Matthew Roh

Posted 2017-07-26T13:59:58.740

Reputation: 5 043

1You should clearly state that this is [tag:code-golf], even though it's tagged. – Mr. Xcoder – 2017-07-26T14:01:00.250

2Can someone link to the OEIS for this (I assume there is one with the number of partition sequences we've been running into on the CnR OEIS post) – Stephen – 2017-07-26T14:03:41.297

3I think the last test case should be 8 – H.PWiz – 2017-07-26T14:12:27.513

@H.PWiz Uhm let me calculate again – Matthew Roh – 2017-07-26T14:13:59.360

Related – miles – 2017-07-26T14:14:36.070

2I agree with H.PWiz that the last testcase should be 8 instead of 7. – Erik the Outgolfer – 2017-07-26T14:19:07.297

Looks like It was 8. Sorry for your inconvenience. – Matthew Roh – 2017-07-26T14:22:21.863

2A008284 – miles – 2017-07-26T14:26:28.990

Is restricting the second input, k, to non-negative integers is acceptable? Also should the solution work for negative n? Zero n? (my guesses are yes, yes, and yes) – Jonathan Allan – 2017-07-26T15:29:59.777

If k is fixed the generating function for this is x^k/((1-x)*(1-x^2)*...*(1-x^k)). – orlp – 2017-07-26T15:32:51.260

@JonathanAllan I don't see how k can be negative, given it's the length of a partition. – Erik the Outgolfer – 2017-07-26T15:37:03.403

This needs more detail. Can 0 be a partition element? Can a partition contain duplicates? Do we count only increasing partitions? – Zgarb – 2017-07-26T15:37:46.900

@EriktheOutgolfer there are, by the very definition provided in the OP, 0 partitions for k<=0. (and my guess to the answer to my question was "yes" too) – Jonathan Allan – 2017-07-26T15:56:52.983

@Zgarb it could help to add such information to the post, yes. But to address these questions "an integer partition is a way of writing n as a sum of positive integers. Two sums that differ only in the order of their summands are considered the same partition.", so: no zeros inside; duplicates are acceptable; disregard order for counting. (Note that P(0,0) is 1 however - one way to have the empty set). – Jonathan Allan – 2017-07-26T16:10:26.443

In the tip, if P0(0)=1, shouldn't the condition in the other case be <0 instead of ≤ 0? – JAD – 2017-07-27T06:56:38.090

Answers

3

Swift, 76 73 bytes

func P(_ n:Int,_ k:Int)->Int{return n*k>0 ?P(n-k,k)+P(n-1,k-1):n==k ?1:0}

Try it online!


Explanation

How does the code structurally work?

First of all, we define our function P, with two integer parameters n and k, and give it a return type of Int, with this piece of code: func P(_ n:Int,_ k:Int)->Int{...}. The cool trick here is that we tell the compiler to ignore the names of the parameters, with _ followed by a space, which saves us two bytes when we call the function. return is obviously used to return the result of our nested ternary described below.

Another trick I used was n*k>0, which saves us a couple of bytes over n>0&&k>0. If the condition is true (both the integers are still higher than 0), then we recursively call our function with n decremented by k as our new n and k stays the same, and we add the result of P() with n and k decremented by 1. If the condition is not true, we return either 1 or 0 depending on whether n is equal to k.

How does the recursive algorithm work?

We know that the first element of the sequence is p0(0), and so we check that both integers are positive (n*k>0). If they are not higher than 0, we check if they are equal (n==l ?1:0), here being two cases:

  • There is exactly 1 possible partition, and thus we return 1, if the integers are equal.

  • There are no partitions if one of them is already 0 and the other is not.

However, if both are positive, we recursively call P twice, adding the results of P(n-k,k) and P(n-1,k-1). And we loop again until n has reached 0.


* Note: The spaces cannot be removed.

Mr. Xcoder

Posted 2017-07-26T13:59:58.740

Reputation: 39 774

3

Pyth, 9 7 6 bytes

-1 byte thanks to Erik the Outgolfer!

/lM./E

Try it online!

Inputs to the program are reversed (i.e. k, n).

notjagan

Posted 2017-07-26T13:59:58.740

Reputation: 4 011

2

Jelly, 6 bytes

œċS€ċ⁸

Try it online!

Erik the Outgolfer

Posted 2017-07-26T13:59:58.740

Reputation: 38 134

Ah ha, of course! – Jonathan Allan – 2017-07-26T14:31:58.967

2

Python 2, 61 55 51 50 bytes

-10 bytes thanks to Erik the Outgolfer. -1 byte thanks to Mr. Xcoder.

I will say, I did copy the hint from OP and translate it to Python. :P

P=lambda n,k:n*k>0and P(n-k,k)+P(n-1,k-1)or+(n==k)

Try it online!

totallyhuman

Posted 2017-07-26T13:59:58.740

Reputation: 15 378

1This breaks on the last test case of 10, 3. Too much recursion – jkelm – 2017-07-26T14:18:12.900

@jkelm Fixed. - – totallyhuman – 2017-07-26T14:19:01.540

1(n>0and k>0) -> n>0<k – Erik the Outgolfer – 2017-07-26T14:19:48.300

Heh, nice abuse of Python's comparison operators. I wish there was a way to have the 0 at the end though, so I could get rid of that space... – totallyhuman – 2017-07-26T14:21:32.480

1Also you can do +(n==k) instead of [0,1][n==k]. – Erik the Outgolfer – 2017-07-26T14:23:53.317

1You don't need the space in or +. – Erik the Outgolfer – 2017-07-26T14:26:28.563

"I will say, I did copy the hint from OP and translate it to Python" - I don't feel so bad that my solution ended up being so similar to yours, now! – Shaggy – 2017-07-26T14:36:56.967

150 bytes, replace n>0<k and with n*k>0and – Mr. Xcoder – 2017-07-26T14:46:11.723

(also @EriktheOutgolfer) What is the + in +(n==k) for exactly? This seems to work for 48.

– Jonathan Allan – 2017-07-26T15:11:34.720

To cast n==k to an integer. Technically, True instead of 1 and False instead of 0 is allowed but it shaves off 3 bytes and is just... meh. – totallyhuman – 2017-07-26T15:12:15.147

@JonathanAllan + converts True/False to 0/1 – Erik the Outgolfer – 2017-07-26T15:13:34.457

Does it ever need to be cast though, wont the addition in the pre-tail call always exist, hence casting any boolean results to integers? – Jonathan Allan – 2017-07-26T15:13:40.237

@JonathanAllan Not always. – Erik the Outgolfer – 2017-07-26T15:15:28.280

@EriktheOutgolfer right - if numbers less than 1 are required to be handled I suppose. – Jonathan Allan – 2017-07-26T15:17:10.187

@totallyhuman nothing is "just ...meh" when it comes to shaving off bytes ;p – Jonathan Allan – 2017-07-26T15:19:00.893

2

Mathematica, 33 bytes

Length@IntegerPartitions[#,{#2}]&

here is n x k table

 \k->
 n1  0  0   0   0   0   0   0   0   0  
 |1  1  0   0   0   0   0   0   0   0  
 v1  1  1   0   0   0   0   0   0   0  
  1  2  1   1   0   0   0   0   0   0  
  1  2  2   1   1   0   0   0   0   0  
  1  3  3   2   1   1   0   0   0   0  
  1  3  4   3   2   1   1   0   0   0  
  1  4  5   5   3   2   1   1   0   0  
  1  4  7   6   5   3   2   1   1   0  
  1  5  8   9   7   5   3   2   1   1  

J42161217

Posted 2017-07-26T13:59:58.740

Reputation: 15 931

1Of course. I knew there was a builtin. – Matthew Roh – 2017-07-26T14:17:51.120

A Mathematica Simplified port would save a 13 bytes here I believe (Length->Len`1 and IntegerPartitions -> Int`7

– Jonathan Allan – 2017-07-26T14:44:04.840

@JonathanAllan I'm actually making a super-short version of this. Hopefully I can finish it by the end of the month – JungHwan Min – 2017-07-26T16:50:32.857

2

MATL, 14 bytes

y:Z^!S!Xu!Xs=s

Try it online!

Explanation

Consider inputs 6, 2.

y     % Implicitly take the two inputs. Duplicate from below
      % STACK: 6, 2, 6
:     % Range
      % STACK: 6, 2, [1 2 3 4 5 6]
Z^    % Cartesian power
      % STACK: 6, [1 1; 1 2; ... 1 5; 1 6; 2 1; 2 2; ...; 6 6]
!S!   % Sort each row
      % STACK: 6, [1 1; 1 2; ... 1 5; 1 6; 1 2; 2 2; ...; 6 6]
Xu    % Unique rows
      % STACK: 6, [1 1; 1 2; ... 1 5; 1 6; 2 2; ...; 6 6]
!Xs   % Sum of each row, as a row vector
      % STACK: 6, [2 3 ... 6 7 4 ... 12]
=     % Equals, element-wise
      % STACK: [0 0 ... 1  0 0 ... 0]
s     % Sum. Implicitly display
      % STACK: 3

Luis Mendo

Posted 2017-07-26T13:59:58.740

Reputation: 87 464

Honestly I'm surprised MATL doesn't have an "integer partition" builtin or something. – Erik the Outgolfer – 2017-07-26T14:25:36.790

@Sanchises It should be working now. Thanks for telling me! – Luis Mendo – 2017-07-26T19:14:44.113

No problem. I was just playing with it to understand your method (which is generally easier for small cases) when I ran into the error. – Sanchises – 2017-07-26T20:22:18.957

2

JavaScript (ES6), 42 40 39 bytes

I think this works.

f=(x,y)=>x*y>0?f(x-y,y)+f(--x,--y):x==y

Try it

k.value=(
f=(x,y)=>x*y>0?f(x-y,y)+f(--x,--y):x==y
)(i.value=10,j.value=3)
onchange=_=>k.value=f(+i.value,+j.value)
*{font-family:sans-serif}input{margin:0 5px 0 0;width:100px;}#j,#k{width:50px;}
<label for=i>n: </label><input id=i type=number><label for=j>k: </label><input id=j type=number><label for=k>P<sub>k</sub>(n): </label><input id=k readonly>

Shaggy

Posted 2017-07-26T13:59:58.740

Reputation: 24 623

1

Haskell, 41 bytes

0#0=1
n#k|n*k>0=(n-k)#k+(n-1)#(k-1)
_#_=0

Try it online!

nimi

Posted 2017-07-26T13:59:58.740

Reputation: 34 639

1

alephalpha

Posted 2017-07-26T13:59:58.740

Reputation: 23 988

1

Haskell, 41 bytes

n&0=0^n
n&k=sum$map(&(k-1))[n-1,n-k-1..0]

Try it online!

An alternate recurrence.

Anders Kaseorg

Posted 2017-07-26T13:59:58.740

Reputation: 29 242

0

Jelly, 13 bytes

I have a feeling know this basic approach won't be the golfiest!

RŒṖL€€Ṣ€QṀ€=S

Try it online!

Jonathan Allan

Posted 2017-07-26T13:59:58.740

Reputation: 67 804

Yeah it isn't (see my Jelly answer at the far bottom). – Erik the Outgolfer – 2017-07-26T14:29:22.140

Oh no Code bowling – Matthew Roh – 2017-07-26T14:30:35.880

@EriktheOutgolfer If it works why is it deleted? – Jonathan Allan – 2017-07-26T14:30:36.643

@Jonathan refresh – Matthew Roh – 2017-07-26T14:31:05.773

@JonathanAllan It was deleted before a test case was fixed. – Erik the Outgolfer – 2017-07-26T14:32:28.807

0

05AB1E, 9 bytes

L²ã€{ÙO¹¢

Try it online!

Erik the Outgolfer

Posted 2017-07-26T13:59:58.740

Reputation: 38 134

0

CJam, 18 bytes

{_,:)@m*:$_&::+e=}

Try it online!

Expects inputs in reverse, i.e. k n instead of n k.

Erik the Outgolfer

Posted 2017-07-26T13:59:58.740

Reputation: 38 134

0

Scala, 73 bytes

Well this is some easy unreworked use of OP's tip.

k and n are the parameters of my recursive function f. See TIO link for context.

Since this is recursive, should I include function def in byte count?

(k,n)match{case(0,0)=>1
case _ if k<1|n<1=>0
case _=>f(n-k,k)+f(n-1,k-1)}

Try it online!

V. Courtois

Posted 2017-07-26T13:59:58.740

Reputation: 868

0

C (gcc), 41 bytes

f(n,k){n=n*k>0?f(n-k,k)+f(--n,--k):n==k;}

Try it online!

cleblanc

Posted 2017-07-26T13:59:58.740

Reputation: 3 360

0

R (+ pryr), 49 bytes

f=pryr::f(`if`(k<1|n<1,!n+k,f(n-k,k)+f(n-1,k-1)))

Which evaluates to the recursive function

function (k, n) 
if (k < 1 | n < 1) !n + k else f(n - k, k) + f(n - 1, k - 1)

(k < 1 | n < 1) checks if any of the initial states are met. !n + k evaluates to TRUE (1) if both n and k are 0, and FALSE (0) otherwise. f(n - k, k) + f(n - 1, k - 1) handles the recursion.

JAD

Posted 2017-07-26T13:59:58.740

Reputation: 2 898