-5
def partitions(n):
    # base case of recursion: zero is the sum of the empty list
    if n == 0:
        yield []
        return

    # modify partitions of n-1 to form partitions of n
    for p in partitions(n-1):
        yield [1] + p
        if p and (len(p) < 2 or p[1] > p[0]):
            yield [p[0] + 1] + p[1:]

Explanation: If you have a partition of n, you can reduce it to a partition of n-1 in a canonical way by subtracting one from the smallest item in the partition. E.g. 1+2+3 => 2+3, 2+4 => 1+4. This algorithm reverses the process: for each partition p of n-1, it finds the partitions of n that would be reduced to p by this process. Therefore, each partition of n is output exactly once, at the step when the partition of n-1 to which it reduces is considered.

This is code for getting all possible partitions of a number in Python. I am not good at Python. I would really appreciate if someone could just get it transformed into pseudocode(or detailed description) or in PHP. The explanation above creates a doubt in my mind about "subtracting one from the smallest item in the partition". I can also subtract one from second smallest or some other element. So, why only smallest? If someone could explain me the whole idea, it would be really grateful. Thanks.

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Sushant
  • 66
  • 1
  • 9
  • 2
    I don't think you can just get people to code things for you around here. You have to put in some effort yourself first. – jamylak Apr 06 '12 at 08:50
  • @jamylak I am not asking to code into PHP. I have also written for pseudocode. Just wanted to get the code. That's it! So what's it in that you rated it -1? If I have got less reputation, it doesn't mean that whatever I ask or do is useless or silly. – Sushant Apr 06 '12 at 08:56
  • `partitions(n)` does not return/yield anything for values of `n` other than `0` … – knittl Apr 06 '12 at 09:02
  • @knittl As I said before, I am not familiar with Python. But the algorithm must be fine. I got this code from a website. If you get the idea behind the algorithm, please explain it to me. Thanks. – Sushant Apr 06 '12 at 09:07
  • 1
    I fixed the indentation, now it will actually compile. – knittl Apr 06 '12 at 09:13
  • @knittl: That's fine. But will you just explain me the whole idea behind the algorithm so that I could write it in PHP for myself. – Sushant Apr 06 '12 at 09:28
  • See it as a chance and learn python. It seems (apart from the idea behind the algorithm), the only tricky parts are recursion and yield. And only yield is python-specific and does not exist in php. – knittl Apr 06 '12 at 09:43
  • This does rather sound like a code-this-for-me ('if someone could just get it transformed into pseudocode ... or PHP'). @knittl has been _very_ kind to help you out, and to edit your question - but you will learn more if you give things a go yourself, I should think. (Don't take criticism of questions on S/O personally, btw - for the most part they are there to help you). – halfer Apr 06 '12 at 09:54
  • I am sorry for the bothering post. – Sushant Apr 06 '12 at 11:00

1 Answers1

2
def partitions(n):
    # base case of recursion: zero is the sum of the empty list
    if n == 0:
        yield [] # yield empty array
        return # exit function

    # modify partitions of n-1 to form partitions of n
    for p in partitions(n-1): # recursive call, get n-1 partitions
        yield [1] + p # yield array [1, p...]
        if p and (len(p) < 2 or p[1] > p[0]): # p not empty, and length < 2 or p[1] > p[0]
            yield [p[0] + 1] + p[1:] # increment first item of p and yield p

Here's my try (afaik PHP does not have yield, so it might perform worse):

function partitions($n) {
   # base case of recursion: zero is the sum of the empty list
   if(!$n) return array(array()); # return/"yield" empty array

   # modify partitions of n-1 to form partitions of n
   $a = array(); # will hold "yielded" values
   foreach(partitions($n-1) as $p) { # recursive call
     $a[] = array_merge(array(1), $p); # "yield" array [1, p...]
     if($p && (count($p) < 2 || $p[1] > $p[0])) { # p not empty, and length < 2 or p[1] > p[0]
       ++$p[0]; # increment first item of p
       $a[] = $p; # "yield" p
     }
   }
   return $a; # return all "yielded" values at once
}

(I don't guarantee anything)

knittl
  • 246,190
  • 53
  • 318
  • 364
  • The code doesn't work actually. But I am really thankful to you for trying this. – Sushant Apr 06 '12 at 11:02
  • The edit that has to be done is this ----> if($n==1) return array(array(1));// base case – Sushant Apr 06 '12 at 11:41
  • You are quite right, yield returns elements from an array, so `yield []` returns an empty array from an array. `if(!$n) return array(array())` should work as well and should work for all cases of `n>=0`. I have edited my answer to reflect this. – knittl Apr 06 '12 at 12:34