//*** CODE ***
/*
Online Java - IDE, Code Editor, Compiler
Online Java is a quick and easy tool that helps you to build, compile, test your programs
online.
*/

import java.math.*;
import java.util.*;
class Staircase
{
    static int N = 25;
    int[] X;
    int p;
    int total;
    int cycles=0;
    Set<String> s;
    Random rand = new Random();
    
    public Staircase(long combinations, int[] X, int r, Set<String> s)
    {
        this.X=X;
        this.s=s;
        System.out.println("Combinations: " + combinations);
        StringJoiner sj = new StringJoiner(",");
        int currentSetSize=0;
        int newSetSize;
        int count;
        int q;
        int steps;
        
        do
        {
            count=1;
            
            for (q=0; q<r;q++)
            {
                p= rand.nextInt(X.length);
                steps = X[p];
                System.out.println("\nrandom step is: " + steps);
                sj.add(Integer.toString(X[p]));
                currentSetSize=s.size();
                total=total+steps;
                System.out.println("This is performing: " + (q+1) +" of " + r + "(r)");

                System.out.println("TOTAL HERE: " + total + "    N Value is: " + N);
                
                if (total==N)
                {
                    System.out.println("This is stringjoiner right now: " + sj.toString());
                    System.out.println("Count:" + count);
                    System.out.println("current:" + currentSetSize);
                    System.out.println("TOTAL: " + total);
                    System.out.println("VALUE OF N: " + N);
                    System.out.println("COUNT: " + count);
                    System.out.println("r: " + r);
                    s.add(sj.toString());
                    
                    count++;
                }
                
                if (q==r-1)
                {
                    sj = new StringJoiner(",");
                    total=0;
                }
            }
            
            if (total>N)
            {
                total=0;
                sj = new StringJoiner(",");
            }
            
            newSetSize = s.size();
            System.out.println("new size: "+ newSetSize);
            
            if (newSetSize>currentSetSize)
            {
                System.out.println("This has been added into the set:");
                
            }
            cycles++;
            System.out.println("Number of cycles: " + cycles + "\n");
            
        }while (cycles<combinations*10);
        
        for (String g: s)
        {
            System.out.println(g.toString());
        }
        
    }
}

public class Combination
{
    public static void main(String[] args)
    {
        System.out.println("Welcome to Online IDE!! Happy Coding :)");
        int originalNumber=0;
        int n=originalNumber;
        int r;
    
        Set <String> s = new HashSet<>();
    
        int [] X = new int []{5,6,7};
    
        int minimum;
        int maxRValue;
        Staircase sc;
        
        Map <Integer, Long> m;
    
        n=X.length;
        
        System.out.println("Staircase size is:  " + Staircase.N);
        System.out.println("Steps are: " + Arrays.toString(X));
    
        originalNumber=n;
    
        m= new HashMap<>();
        minimum=X[0];

        for (int i=0; i<X.length;i++)
        {
            if (X[i]<minimum && X[i]!=0)
            {
                minimum=X[i];
            }
        }
        maxRValue=(Staircase.N)/minimum;
        System.out.println("Maximum value of r: " + (maxRValue+ 1) + " has been set using minimum value in set: " + minimum + " , which should be in proximity to N(" + Staircase.N + ")");
    

        for (r=0; r<=maxRValue+1; r++)
        {
            System.out.println("\n***COMBINATIONS*** (WITH REPLACEMENT)");
        
            System.out.println("C^R(n + r) = " + "(n+r-1)! / r!(n-1)!");
        
            System.out.println("C^R(" + n+","+r+") = " + (n+r-1)+ "!" + " / " + r+"!"+"("+(n-1)+")!");
        
            sc = new Staircase (Combinations (n,r,originalNumber, m), X, r,s);
        }
    }

    public static long Combinations (int n, int r, int originalNumber, Map factorialResults)
    {
        long result=0;
        int denominator1; 
        int denominator2; 
        int Numerator=n+r-1;
        int zero=0;
        long zeroFactorial = 1;
    
        if (originalNumber==0 && r==0)
        {
            System.out.println("n and r can not both be equal to zero");
            
            return 0;
        }

        if (originalNumber==0 && originalNumber+r-1<r)
        {
            System.out.println("n+r-1 must be > or = to r");
            return 0;
        }
    
        if (Numerator>=1)
        {
            result = ((n+r-1)* (Combinations (n-1, r,originalNumber, factorialResults)));
        
            factorialResults.put(Numerator,result); 
        
            if (n==originalNumber)
            {
                denominator1 = r;
                denominator2 = originalNumber-1;
                factorialResults.put(zero,zeroFactorial);
            
                if (factorialResults.containsKey(denominator1) && factorialResults.containsKey(denominator2))
                {
                    long returnValue = result / ((long)factorialResults.get(denominator1) *(long)factorialResults.get(denominator2));
                    return returnValue;
                }
            }
            return result;
        }
        return 1;
    }
}