//*** 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.
*/
// This has been created to ensure I can utilize any random functions more efficiently.
// It is a creation of the permutations (with replacement) calculator.

//TEST CASES
// All done, see documentation
//Since there are not multiple instantiations similar to combinations when r varied,
//I can safely reduce all variables without static

import java.math.*;
import java.util.*;

class Staircase
{
    int r;    //this will be equal to size of n since it needs to move through each row
    //of triangle.
    int triangleNumber;  // from 0 to (triangle[0].length - 1)
    long permutations;  //as per the calculator
    StringJoiner sj;  //used to add the moves into the Set
    
    //it mantains this so that it can present values from triangle as part of results.
    StringJoiner valuesTriangle = new StringJoiner(",");
    StringJoiner indexesTriangle = new StringJoiner(",");
    
    //this is to ensure no logical issues when storing maximum paths..
    boolean processedMax=false;
    
    //stores number of triangles..
    int numberTriangles;
    
    //these are defined triangles by end user
    int [][][] triangle;
    
    int rowsTriangle;  //number rows in triangle.
    //due to utilisation of zero index as much as possible in the code to avoid confusion,
    //first row will be row 0, so it will utilize <rowsTriangle in most areas.
    
    //this mantains the steps undertaken. It is required for analysis
    //before it can be saved into the set.
    int[] stepStore;
    int num;   //used to index stepStore
    
    //This will store detailed information on the triangle number, 
    //subset, subset number, values in triangle, and also if it is maximum value
    String [][] outcomes;
   
    int[] max; //it stores maximum values for each triangle
    
    //used to store the subsets into outcomes array, 
    //if it is the maximum or joint maximum across triangle.
    int count=0;
    
    int subsetEntry=1;   //this is required to output the subset entry
   
    int[] S; // this is the array containing the steps
    int p; // this is random number generated
    int cycles=0; // this is number of cycles completed for each c(n,r).. It is reset each time....
    
    int totalcycles=0;   // this is useful to know the total cycles... Its static, so will keep running..
    
    //it needs to mantain value to ensure the offset from which the successful subsets are returned are not repeated...
    //strictly speaking, it does not need to remain static since this class is only
    //instantiated once.
    int difference = 0;  //used to get difference in set size and offset to display results on screen...
   
    //it normally has to be static since every time the class is instantiated, it will lose its value otherwise....
    //this is now a good indicator to see the cycle on the screen and occurrence of subset totalling k.
    //since using permutations, static can be removed.
    int i=0;
    
    //this stores the outcome into the outcomes array.
    String outcome;
    
    List <String> backupValuesSet = new ArrayList<>();
    
    //used to hold token.. Tokens are needed to analyse moves (valuesSet[entry])
    String temp;
    
    int temp1;  //stores random index. It is required to perform analysis
    
    Set<String> st; // this will contain the combinations for achieving total k
    Random rand = new Random(); // object created of type Random.
    // there is no sense of X getting smaller since its with replacement....
    // r is the sample size... This can not exceed n.. And MUST be equal to n
    
    String[] valuesSet;   // this will be used to hold all values from the set... this will be modified..
    String []backupValuesSetBeforeModification;  // this will hold all values from set... (this will never be modified...)
    
    public Staircase(long permutations, int[] X, int r, Set<String> st, int[][][] triangle, int numberTriangles, String [][] outcomes, int[] max, int rowsTriangle)
    {
        this.max=max;
        this.outcomes=outcomes;
        this.permutations=permutations;
        this.numberTriangles=numberTriangles;
        this.r=r;
        this.triangle=triangle;
        this.S=S;
        this.st=st;
        this.rowsTriangle=rowsTriangle;
        
        System.out.println("Testing Permutations: " + permutations);
        System.out.println("***There are triangles configured*** : " + numberTriangles);
       
        sj = new StringJoiner(","); // creating StringJoiner for the final output
        
        //this is used to test if the generated number will exceed the numbers in row for the triangle.
        boolean invalidIndex=false;
        
        int currentSetSize=0; // holds size of set before entry added
        int newSetSize; // holds size of set after entry added
        //int count=0;
        
        //this is used to ensure that subsets contain q valid moves...
        //i.e where q is equal to triangle.length (number rows...)
        int stepsCounter=0;
        
        //used non-zero indexing is a bit better for this.
        int subsetNumber=1;
        
        int steps; // it will hold value of step generated randomly from r
       
        String subsetIntToString=""; //  since it needs to add number back into the StringJoiner, 
        //it has to be converted into a String first....
        
        int pos=0;  // used to index array X. Required so that it can check if previous number holds same value...
        //it will only increment at end of the loop to ensure correct validation check...
     
        int n=0;  // this is index used when comparing the valuesSet with backupValuesSet
       
        System.out.println("*************INITIAL VALUE OF  CYCLES: " + cycles);
        
        do
        {
            //it has to clear all entries, ready for execution of a cycle.
            stepStore = new int[rowsTriangle];
            
            for (int q=0; q<r;q++) // processing up to r only since this is the sample size
            {
                //it needs to perform steps.
                //it will enter this if item from the sample does not provide
                //a valid index on the triangle...
                //it has already set the flag as per code outside of the loop.
                // all it does here, is just get the conditions ready as if
                //it was starting again..
                //empties StringJoiner which contains existing selection.
                //sets stepsCounter=0 again
                //invalidIndex=false   since its a new start..
                if (invalidIndex)
                {
                    sj=new StringJoiner(",");
                    invalidIndex=false;
                    stepsCounter=0;
                    num=0;
                }
                
                //in ideal world, it would need something like this
                //do while loop since we know that ...
                //on a row 0:  [0][0][0]
                //on a row 1:  [1][0][0]  and [1][0][1]
                //the last index available is less than or equal to row number..
                //i.e  it will not attempt to perform moves such as (1,1,0)
                //since indexing  [0][0][1] is invalid.
                
                //we know that Set size is governed based on P(3,3) = 27
                //if we try to reduce number of entries.. the cycles will
                //be much larger than expectations.
                //since there are no longer permutations to fulfill 27.
                
                //we can perhaps examine this closer
                //since  (1,X,X) or  (2,X,X) are of no use whatsoever = 66% entries = 18 entries...
                //Also   (0,2,X) = 3 entries
                
                //I am examining this in my documentation..
                 
                 //holds random number
                 temp1 = rand.nextInt(X.length);
                  
                  //as per explanation above.
                  //this is valid selection..
                  if (temp1<=q)
                {
                    
                    p=temp1;
                    
                    //increase the counter
                    stepsCounter++;
                }
                else
                {
                    //it also needs to set a flag here...
                    //since the q=0 will only take effect once it has reached
                    //end of execution of the for loop..
                    //note performing a break is costing one cycle also in
                    //do while loop, this has to be considered if triangle formation become
                    //improbable.. for instance several rows...
                    //We know only 0 is applicable for first row..
                    
                    invalidIndex=true;
                    break;
                    
                }
                
                steps = X[p]; // index value
                //System.out.println("\nrandom number from original subset is : " + steps);
                sj.add(Integer.toString(X[p])); //adds the index into StringJoiner
                
                //it has to store individuals values so that it can perform the
                //analysis as described in if else statement
                stepStore[num]=steps;
                num++;
                
                //inline with failing test case 3 on my documentation, I need to create new code..
                //since (0,1,0)  and (0,0,2) will violate adjacent principles..
                
                currentSetSize=st.size(); //current size of set
                
                //System.out.println("This is performing: " + (q+1) +" of " + r + "(r)");

                if (q==r-1) // if its on the last loop..
                {
                    //critical for testing... can not proceed if stepsCounter != triangles.length (number rows)
                    //System.out.println("value of stepsCounter: " + stepsCounter);
                    
                    //it has to apply adjacent logic.
                    //it is only valid from row 1
                    //it would normally end less than rowsTriangle as part zero indexing
                    //however since it examines next row to make decision, it is rowsTriangle-1
                    for (int h=1; h<(rowsTriangle-1); h++)
                    {
                        //It can be seen above that the adjacent value on next row has index 
                        // either same or EXACTLY greater by 1… 
                        //AND Also not lower..
                        //This is translated into following logic to represent invalid
                        
                        //index on next row is greater than 1  to current row
                        if ((Math.abs(stepStore[h+1]-stepStore[h])>1))
                        {
                        invalidIndex=true;
                        break;
                        }
                        
                        //index on next row is less than index current row
                        if (stepStore[h+1]<stepStore[h])
                        {
                        invalidIndex=true;
                        break;
                        }
                        
                    }
                    
                    if (!invalidIndex)
                    {
                        //it is critical to reset these values..
                        //since it might have performed r=1 and r=2 already
                        //and failed on r=3..  so it would have populated these.
                        //it is preparing variables for next cycle
                        num=0;
                        stepStore=new int[rowsTriangle];
                        stepsCounter=0;
                        
                        st.add(sj.toString()); // it will only add it if the conditions are met above 
                        
                        //preparing for next execution. StringJoiner has not been modified yet,
                        //so just performing a cleanse incase...
                        sj = new StringJoiner(",");
                        
                    }  //end of if (!invalidIndex)
                
                }  //end of if  (q==r-1)
            }   //end of for (int q=0; q<r;q++)
            
            newSetSize = st.size(); // new set size
            
            cycles++; //increases cycles
            //it is increasing cycle every time its on the end of completing do while loop
            
            //grand total of cycles completed in the code....
            totalcycles++;
            
            //System.out.println("Number of cycles: " + cycles + "\n");
            
            //strictly speaking, if no modifications were completed above
            //in trying to reduce the subsets (please see documentation and calculator)
            //there were fixed permutations, hence could have set the do while condition to
            //set size < 28
            //However attempting this is no longer viable
            //trying this will cause code execution indefinitely since there are only
            //6 viable outcomes for triangle consisting of 3 rows with all extra implemented logic
            
            //Need to be careful with speculative amount:
            //Although it will over compensate since the permutations (27) expected is much
            //higher than the narrows subsets (6)
            //Also need to be aware that random number selection can void lots of cycles..
            //notably with larger triangles.
            //for instance if it selects a random number which is ArrayIndexOutOfBoundsException
            //for the triangle row.
            
        }while (cycles<permutations*400);

        //FOR NOW, ALL CODE BETWEEN THE %%%% could be simplified.
        //BUT IT IS BEING KEPT INTACT FOR FUTURE PURPOSE
        //FOR INSTANCE, IF I DO FIND A REASON IN FUTURE TO IMPLEMENT CODE FURTHER
        //WITH MULTIPLE CALLS TO PERMUTATION CALCULATOR, IT WOULD WRITE
        //TO THE SET IN DISORDERLY FASHION.
        //NOT APPLICABLE AT MOMENT, SINCE ONE CALL TO PERMUTATION CALCULATOR.
        //NO INFLUENCE ON backupValuesSet and valuesSet.
        //IT MIGHT BE USEFUL FOR INSTANCE IF HANDLING TEST CASE 13 IN DOCUMENTATION
        //System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
        
        // this is now getting the String in the set...
        //initially i will be 0 and it will output entire contents of the set..
        //once it has completed it first time, it will continue from its last position.
        //this is taken to be difference.... 
        
        //At this point in time, both are identical copies....
        valuesSet = st.toArray(new String[st.size()]);
        backupValuesSetBeforeModification = st.toArray(new String[st.size()]);
        
        // This next part was pivotal to ensure my technique was correct.
        //the backupValuesSet is populated below in following technique...
        //basically it is getting an untouched version of the String array above.
        //it is basically copy of the set which occurs several lines down....
        //backupValuesSet= new ArrayList<>(Arrays.asList(backupValuesSetBeforeModification));
        //So as expected when it hits hit and the set is empty, it will always show no content....
        //the reason why backupValuesSet is occuring after the valuesSet is since it can only make a backup once
        //valuesSet has been processed.
        //This also creates an effect of incremental backup in which backupValuesSet is one interation behind the valuesSet.
        //For this exercise it is purposeful since backupValuesSet can be searched against valuesSet
        //for duplicate values and eradicate them....
        
        System.out.println("******************Contents of the backup set");
        
        //commented out, but can be used troubleshooting
        /*
        for (String g: backupValuesSet)
        {
            System.out.println("Subset " + subsetNumber+": " + g);
            subsetNumber++;
        }
        subsetNumber=1;
        
        //System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
        */
        
        ///again this is copy of the set.... It can be expected that once it starts populating, the valuesSet
        //will always be larger than backupValuesSet
        
        System.out.println("******************Contents of the valuesSet");
        
        for (String g: valuesSet)
        {
            System.out.println("Subset " + subsetNumber+": " + g);
            subsetNumber++;
        }
        //since valuesSet array gets overwritten, its important to set this back.
        subsetNumber=1;
        
        //checking every value in the backupValuesSet and setting it to ALREADY PROCESSED in 
        //valuesSet if it appears....
        
        for (String m: backupValuesSet)
        {
            n=0;
            do
            {
                if (m==valuesSet[n])
                {
                    //System.out.println("Match found in backupValuesSet: " + m);
                    //System.out.println("Match found in valuesSet: " + valuesSet[n]);
                    
                    //valuesSet[n]="ALREADY PROCESSED";
                    //System.out.println("valuesSet[n]" + " set to " + valuesSet[n]+"\n");
                    
                }
                
                n++;
                
            }while (n<valuesSet.length);
            //keep processing for all items in valuesSet
            
        }  //end for processing backupValuesSet
        
        System.out.println("*************NEW VALUE CYCLES: " + cycles);
        System.out.println("*************RUNNING TOTAL CYCLES: " + totalcycles);
        
        System.out.println("***PROCESSING SET AT INDEX: " + (difference));
        System.out.println("**ENDING AT INDEX:***** " + st.size() +"\n");
        
        //need be careful with this code, since if there is "ALREADY PROCESSED IN THE VALUESSET"
        //it will copy it again into the backupValuesSet
        //backup has to be restored from backupValuesSetBeforeModification.
        
        backupValuesSet= new ArrayList<>(Arrays.asList(backupValuesSetBeforeModification)); 
        
        //System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
        
        //this now processes each String in the ValuesSet (which will be Strings not outputted yet)
        for (int entry=0; entry<valuesSet.length; entry++)
        {
            if (valuesSet[entry]!="ALREADY PROCESSED")    //as per above, it needs bypass these
            {
               
            System.out.println(valuesSet[entry] + "    Subset: " + subsetEntry  + "  at cycle number: " + totalcycles);
            subsetEntry++;    //static variable, it will keep track of combinations in the subset...
            
            //MAIN LOGIC OF THE NEW CODE OFFICIALLY STARTS HERE.
            
            //method to obtain moves from the String valuesSet[entry]
            obtainMoves(valuesSet[entry]);
            }
        }
        //on first time it reaches above,    currentSetSize will be 0....
        //next time, currentsetSize will be previously newSetSize....
        //so it will perform incremental difference...
        
        //Set is zero index,  so it would have completed 5 items at  s.get(4)
      
        difference = newSetSize;
        
        }  //end of constructor...
        
        public void obtainMoves(String moves)
        {
            //keeping this local variable, no particular reason..
            int[] nMoves = new int [r];
            //keep this local again, it increments with token found..
            //and provide reference to row in triangle it will be manipulating..
            int i=0;
            
            //performs tokens of valuesSet[entry]
            StringTokenizer sTok = new StringTokenizer(moves,",");
            
            //keeps checking tokens and stores it into temp
            while (sTok.hasMoreTokens())
            {
                temp=sTok.nextToken();
                
                //stores moves in array...
                nMoves[i]= Integer.valueOf(temp);
                i++;
            }
            
            //method call to transpose the moves onto respective rows..
            //sequentially from top to bottom of triangle..
            performMoves(nMoves);
    }
        
    public void performMoves(int[] nMoves)
    {
        //again used local variable for clarity and congested at class level.
        int total=0;
            
        //This is counting through triangles
        //note since if there are multiple triangles, it will store
        //maximum totals for the respective triangle seperately.
        //I introduced multiple triangles since its tidier than having
        //extensive code to initialise each seperately.
        //Also having several triangles has rendered slight adjustments to coding...
        for (int j=0; j<triangle[0].length; j++)
        {
            //Triangle it is processing.
            System.out.println("TRIANGLE " + (j));
            
            //this is processing the moves..
            for (int k: nMoves)
            {
                //critical to ensure that it follows triangle configuration.
                try
                {
                    System.out.println("Elements in: " +  "row " + i + " of triangle:  " + triangle[i][j].length);
                }
                catch (ArrayIndexOutOfBoundsException e)
                {
                    System.out.println("There are no elements in row: " + i + " on this triangle");
                    System.exit(0);
                }
                
                //we know the row number also has row+1 elements
                // row 0 has 1 element, row 1 has 2 elements
                //checks if it exceeds this.
                if ((triangle[i][j].length)>i+1)
                {
                    System.out.println("Ensure correct triangle configuration.");
                    System.exit(0);
                }
                
                //critical, the indexes should correspond to the value on the triangle...
                try
                {
                    System.out.println("Value at triangle: " + j + "  [" + i +  "]" + "[" +j + "]" + "[" +k + "]" + ":  "  + triangle[i][j][k]);
                }
                catch (ArrayIndexOutOfBoundsException e)
                {
                    System.out.println("Ensure correct triangle configuration.");
                    System.exit(0);
                }
                
              //keeps running total
              total=triangle[i][j][k] + total;
              
              //stores indexes in order present as solution
              indexesTriangle.add("["+ Integer.toString(i)+"]" + "["+ Integer.toString(j)+"]" + "["+ Integer.toString(k)+"]" );
              
              //at moment, this is first time values are extracted from triangles...
              //and stored in a StringJoiner
              valuesTriangle.add(Integer.toString(triangle[i][j][k]));
              
              i++;  //increments the row
            }  //end for nMoves
            
            i=0;   //resets variable for row number
            
            System.out.println("*******TOTAL: " + total +"\n");
            
            //inline with previous exercises this ensures that maximum value is not
            //applicable in two if scenarios.
            //prevents storing entry multiple times...
            processedMax=false;
            
            //this is critical output with all information...
            // it will be stored in outcomes array..
            
            outcome = "Triangle: " + j +  " | Subset:" + (subsetEntry-1) + " " +"(" + valuesTriangle + ")" + " (Indexes: " + indexesTriangle +")" +" | " +  "Max value: " + total;
            
            //critical to reset StringJoiners..
            valuesTriangle = new StringJoiner(",");
            indexesTriangle= new StringJoiner(",");
            
            //note the j index represents the triangle number..
            //it has to mantain separate value in the 2D array....
            //if total is greater than existing, it stores as new total.
            if (total>max[j])
            {
                max[j]=total;
                
                //in previous code, I followed this approach to remove all entries
                //in the repository.
                //It can not be completed for this exercise, since it will wipe
                //outcomes for all triangle configurations...
                //outcomes = new String[2][(int)permutations];
                
                //need to wipe max information for that given triangle ONLY
                //need to wipe value in all rows for that given triangle.
                
                //sets index to 0
                int index=0;
                
                //we know the outcome repository is facilitated to support
                //all permutations for each triangle... So do while will execute until
                //it reaches outcomes[j].length.. 
                //it ultimately erases all entries for maximum since there is a new maximum.
                
                do
                {
                    //used for testing..
                    //System.out.println("val j: " + j);
                    //System.out.println("val index: " + index);
                    //System.out.println("val perm: " + permutations);
                    //System.out.println("val length row: " + outcomes[j].length);
                        
                    //note it is a String, so null is applicable value.
                    outcomes[j][index]=null;
                    //increments index
                    index++;
                        
                }while (index<permutations);
                    
                //resets index
                index=0;
                
                //now the first index in outcomes will have the useful information in outcome.
                outcomes[j][0]=outcome;
                
                //System.out.println("IN HERE: " + outcomes[j][0]);
                
                //ensures information ready to store next location in outcomes repository
                count++;
                
                //setting this flag is critical.
                //since otherwise it would discover that the current total
                //is equal to max.. and store value again at next location
                //on outcomes array.
                //this variable is reset to default once it has performe
                //this execution of checking subset total against current maximum.
                processedMax=true;
            }  //end of (total>max[j])
            
            //if it has identical total to existing (excluding the current item)
            if (total==max[j] && !processedMax)
            {
                //it stores the outcome in next available location..
                outcomes[j][count] = outcome;
                
                //System.out.println("IN HERE1: " + outcomes[j][count]);
                max[j]=total;
                
                //prepares next location
                count++;
            }
            
            //resets the StringJoiner holding values in subset for triangle
            valuesTriangle=new StringJoiner(",");
            total=0;
            
            }  //end for  (processing triangles)
            
            //a very quick message informing end user of the highest triangle.
            //again this is not scope of the challenge, but easily to gather this information.
            for (int c: max)
            {
                System.out.println("Highest total " + "triangle(" + triangleNumber+")" + "is: " + max[triangleNumber]);
                triangleNumber++;
            }
            System.out.println("-----------------------------------\n");
            
            //it has to be reset back to initial since it is ready to process next subset
            //inline with do while loop
            triangleNumber=0;
            
    }  //end of method
} //end of class.

// I have performed several declarations here so that there is a balance
//in both classes.
//I also found that I was performing several illegal forward references if I tried
//to declare too much in the Staircase class.
//Example is trying to assign array dimensions using a variable which was declared
//a bit later in declarations..
//I also ran into several ArrayIndexOutOfBoundsException issues.. (some I could not resolve)
//Following this approach, eradicated several issues.
//unfortunately it has meant repeat variable names in BOTH classes.

public class Permutation
{
    //triangle number
    static int triangleNumber=0;
    
    static Staircase sc; //object of type Staircase
    
    //number triangles.
    static int numberTriangles;
    
    //array to hold maximum values for triangles..
    static int[] max;
    
    public static void main(String[] args) 
    {
        System.out.println("Welcome to Online IDE!! Happy Coding :)");
        Set <String> s = new HashSet<>(); // it will contain all combinations...
        int n;
        int r;
    
        //This is defining three triangles, it can be modified
        //highly suggested to format resembling triangles for easier analysis
        int [ ][ ][ ] triangle = new int[ ][ ][ ] { 
                                        {          {1},           {4},          {4}         }, 
                                        {         {2,3},         {6,8},        {5,6}        },
                                        {        {1,5,1},       {9,2,3},      {7,8,9}       },
                                        {      {15,7,9,12},   {5,9,15,8},   {2,7,11,8}      },
                                        {     {11,6,7,9, 3}, {9,5,3, 6,10},{1,5,6, 2,9}     },
                                        
                                                  };
    
    //this could equally be performed utilizing 1 and 2.
    //lengths expected to be identical if triangles loaded properly...
    numberTriangles=triangle[0].length;
    
    //as per test case 12, this can be explored for dealing mixed size triangles
    //in future
    int rowsTriangle = triangle.length;
    
    //it sets the X array size rowsTriangle
    //if two rows,  values 0 and 1 (2 indexes) will cover all instances
    int [] X = new int [rowsTriangle];  
    
    for (int q=0; q<rowsTriangle; q++)
    {
        X[q]=q;
    //int [] X = new int []{0,1,2};  
    // we know on top row of triangle 0 index will cover only 1 element
    //we know on 2nd row, indexes are 0 and 1  = 2 elements
    //we know on 3rd row, index is 0,1,2  = 3 elements.
    }
    
    
    //sets size to accomodate for numberTriangles
    max = new int[numberTriangles];
    
    int counter=0; // used in iterating set to keep count..
    
    //need to understand this example will use permutations with replacement
    //since 0 index for instance is applicable in each row.
    
    Map <Integer, Long> m; // this can stay outside loop since its not impacted by size of n and r
    
    n=X.length; //length of the array X of steps
    
    //System.out.println("Staircase size is:  " + Staircase.k);
    //System.out.println("Steps are: " + Arrays.toString(X));
    
    m= new HashMap<>(); //new instance is required to start process again...
    
     r=n;  // this is using all values 0,1,2  r=n  r=3
     
    //this is a slightly wasted execution..
    //but it is the only way to ascertain the dimension based on permutations.
    //NOTE: I tried to initialise this varaible on the staircase class, but 
    //ran into several ArrayIndexOutOfBoundsException during execution.
    long perms = Permutations(n,r);
    
    //sets dimensions to store outcomes.
    //it is 2D since can have multiple maximums per triangle
    String [][] outcomes = new String[numberTriangles][(int)(perms)];
     
     //it will select an index to represent each row...
     //to ensure that it fulfills, the challenge, it will try
     //a subset, extract values.. And try numbers in that order
     //and progress through the triangle..
    
    System.out.println("***PERMUTATIONS***(WITH REPLACEMENT)");
    System.out.println("PR(n,r) = nr");
    System.out.println("**********THE TRIANGLE COUNT CHALLENGE***********");
    
    //Important for testing to ensure correct variable values passed across
    //I had lots issues declaring in other class, so this was a massive area to ensure
    //if any values were changed inadverently in other class during execution.
    //System.out.println("PASSING THIS ACROSS: **********");
    //System.out.println(numberTriangles);
    //System.out.println(Permutations (n,r));
    //System.out.println(max.length);
    //System.out.println(rowsTriangle);

    //creates instance of Staircase and main execution of code...
    sc = new Staircase (Permutations (n,r), X, r,s, triangle, numberTriangles, outcomes, max, rowsTriangle);

   //Information to end user..
    System.out.println("\n\n*************SUMMARY HIGHEST RESULTS*************");
    
    System.out.println("*******TRIANGLES*********");
    System.out.println("***There are triangles configured*** : " + numberTriangles +"\n");
    
    //unfortunately there is no easy way to perform deepToString
    //on a section of the triangle row..
    //this in effect means full content of all rows shown (i.e all triangles)
    //NOTE: Caution when using this to evaluate and testing.. It can be misleading
    //to see triangles
    
    for (int q=0;q<triangle.length;q++)
    {
      System.out.println(Arrays.deepToString(triangle[q]));
      triangleNumber++;
    }
    
    System.out.println("****************\n");
    
    triangleNumber=0;
    
    //Providing there is an entry in the repository, it will display the outcome...
    //the outer do loops ensures it processes triangleNumber until all triangles procesed.
    //since triangle number starts at 0, it will finish 
    //for instance if two triangles:
    //triangleNumber(1) < triangle[0].length (2)
    
    do
    {
        for (String str: sc.outcomes[triangleNumber])
        {
            if (str!=null)
            {
                System.out.println(str);
                
            }
            
        }
        triangleNumber++;
        
        }while(triangleNumber<triangle[0].length);
        
    }
    
    //this is the simple technique of permutations with replacement.
    public static long Permutations (int n, int r)
    {
        System.out.println("P^R(" + n+","+r+") = " + "Math.pow(n,r)");
        return (long)Math.pow(n,r);
    }
}