[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [sc-users] non random integer partition



I needed integer partitioning a few years ago, so implemented the z1 algorithm, for larger numbers it got pretty slow so I also implemented it in C, which I used to cache results to file, and then read, but you may also be able to call and parse it using .unixCmd

Paper available here: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.42.1287&rep=rep1&type=pdf

// SuperCollider
~zs1 ={|n=5|
    var x, m, h, r, t, ret;
    x=Array.fill(n, 1);
    x[0]=n;
    m=0;
    h=0;
    ret = List[n];

    while({x[0] != 1}, {
        if(x[h] == 2) {
            m = m+1;
            x[h] = 1;
            h = h-1;
        } {
            r = x[h]-1;
            t=(m-h+1);
            x[h] = r;
        
            while({t>=r},{            
                h=h+1;
                x[h]=r;
                t= t-r;
            });
        
            if(t==0) {
                m=h
            } {
                m=(h+1);
                if(t>1) {
                    h=(h+1);
                    x[h] = t;
                };
            };
        };
    
        ret.add(x[0..m]);
    });
    ret;
};

//C

#include <stdlib.h>
#include <stdio.h>

void zs1(size_t n, FILE *fd)
{
  size_t i, m, h, r, t;
  size_t *x;

  x = malloc(sizeof(*x)*(n+1));

  for (i = 1; i <= n; i++)
    x[i] = 1;

  x[1] = n;
  m = 1;
  h = 1;
  fprintf(fd,"%zd\n",x[1]);

  while (x[1] != 1) {
    if (x[h] == 2) {
      m = m + 1;
      x[h] = 1;
      h = h - 1;
    } else {
      r = x[h] - 1;
      t = m - h + 1;
      x[h] = r;

      while (t >= r) {
        h = h + 1;
        x[h] = r;
        t = t -r;
      }

      if (t == 0) {
        m = h;
      } else {
        m = h + 1;
        if (t > 1) {
          h = h + 1;
          x[h] = t;
        }
      }
    }

    for (i = 1; i <= m; i++)
      fprintf(fd,"%zd ",x[i]);
    fprintf(fd,"\n");
  }

  free(x);
}

int main(int argc, char**argv)
{

    int first_arg = 0;
    if(argc > 1) {
      first_arg = atoi(argv[1]);
    } else {
      printf("must pass integer as argument\n");
      return 0;
    }

    // printf("Partitioning: %d\n", first_arg);

    zs1(first_arg, stdout);
return 0;
}


On 20 December 2015 at 22:53, Daniel Mayer <daniel-mayer@xxxxxxxx> wrote:

Am 20.12.2015 um 13:42 schrieb simdax <simoncornaz@xxxxxxxxx>:

Hello,

nop MagicWindow, what I want is something like
5 => (1, 1, 1, 1, 1) , (2, 1, 1, 1),  (2, 2, 1), (3, 1, 1), (3, 2), (4, 1),
(5)

And as always, thank you Daniel, the enum tool is very useful :D !

But, in reality, my question stays : is it possible to "translate" the first
python func, which seems pretty similar to your function "g" in tutorial,
Daniel



The python code does something different from SC's built-in method 'partitions' !
The latter gives out *ordered partitions* in mathematical sense
wheras the python code only regards *unordered partitions* in mathematical sense -
simpler task, shorter code.

There might a confusion about this as in the implementation we have ordered collections (arrays)
in both cases and when results are additionally ascending (ordered numbers) they represent
the *unordered* partition in mathematical sense, where order doesn't count.

But of course you can also write this recursively in SC
(I take a recursion start of 1 instead of 0 here, as it's more comfortable):

~p = { |n|
var ps;
(n==1).if { [[1]] }{
ps = ~p.(n-1).copy;
ps.collect([1]++_) ++ (
ps.select { |p| (p.size<2) or: { p[1]>p[0] } }
.collect { |p| [p[0]+1] ++ p[1..] }
)
}
}


~p.(5)


The code in the miSCellaneous example with Functions g and h additionally regards 
ordering and size of the partition, which, when summing over all sizes
results in finding all ordered partitions.


Regards

Daniel


-----------------------------
www.daniel-mayer.at
-----------------------------