/*
repe.c 重複組合せに対応する整数への変換とその逆変換の簡略版
   programmed by Isaku WADA 2009 isaku@pb4.so-net.ne.jp
 */
#include <stdio.h>

#define MAX_N 50
#define MAX_R 50

int n,r;
unsigned a[MAX_R][MAX_N];
unsigned b[MAX_R][MAX_N];

unsigned InitRepe(int nn,int rr) {
    int i,j;
    n=nn; r=rr;
    if (r<0||n<=0||r>MAX_R||n>MAX_N) return 0;
    if (r==0) return 1;
    for (i=0;i<r;i++) a[i][n-1]=1;
    for (j=1;j<n;j++) a[r-1][j]=1;
    for (i=r-2;i>=0;i--) for (j=n-2;j>0;j--) a[i][j]=a[i][j+1]+a[i+1][j];
    for (i=0;i<r;i++) a[i][0]=0;
    for (i=0;i<r;i++) for (j=1;j<n;j++) b[i][j-1]=a[i][j]+=a[i][j-1];
    for (i=r-2;i>=0;i--) for (j=0;j<n-1;j++) b[i][j]+=b[i+1][j];
    if (n==1) for (i=0;i<r;i++) b[i][0]=1;
    else for (i=0;i<r;i++) b[i][n-1]=b[i][n-2]+1;
    for (i=0;i<r;i++) for (j=1;j<n;j++) if (b[i][j]<=b[i][j-1])
        return 0;
    return b[0][n-1];
}

unsigned RepeToNum(int*vec) {
    int i; unsigned num=0;
    for (i=0;i<r;i++) num+=a[i][vec[i]];
    return num;
}

void NumToRepe(int*vec,unsigned num) {
    int i,j=0;
    for (i=0;i<r;i++) {
        while (b[i][j]<=num) j++;
        num-=a[i][j]; vec[i]=j;
    }
}

int main(void) {
    unsigned i,s; int vec[3];
    s=InitRepe(3,3);
    for (i=0;i<s;i++) {
        printf(" %u -> ", i);
        NumToRepe(vec,i);
        printf("(%d,%d,%d)",vec[0],vec[1],vec[2]);
        printf(" -> %u\n", RepeToNum(vec));
    }
    return 0;
}