//*** 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;
    int triangleNumber;
    long permutations;
    StringJoiner sj;
    
    StringJoiner valuesTriangle = new StringJoiner(",");
    StringJoiner indexesTriangle = new StringJoiner(",");
    boolean processedMax=false;
    int numberTriangles;
    int [][][] triangle;
    int rowsTriangle;
    int[] stepStore;
    int num;
    String [][] outcomes;
    int[] max;
    int count=0;
    int subsetEntry=1;
    int[] S;
    int p;
    int cycles=0;
    int totalcycles=0;
    int difference = 0;
    int i=0;
    String outcome;
    List <String> backupValuesSet = new ArrayList<>();
    String temp;
    int temp1;
    Set<String> st;
    Random rand = new Random();
    String[] valuesSet; 
    String []backupValuesSetBeforeModification;
    
    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(",");
        boolean invalidIndex=false;
        
        int currentSetSize=0;
        int newSetSize;
        int stepsCounter=0;
        int subsetNumber=1;
        int steps;
        String subsetIntToString="";
        int pos=0;
        int n=0;
       
        System.out.println("*************INITIAL VALUE OF  CYCLES: " + cycles);
        
        do
        {
            stepStore = new int[rowsTriangle];
            
            for (int q=0; q<r;q++)
            {
                if (invalidIndex)
                {
                    sj=new StringJoiner(",");
                    invalidIndex=false;
                    stepsCounter=0;
                    num=0;
                }
                temp1 = rand.nextInt(X.length);
                
                if (temp1<=q)
                {
                    p=temp1;
                    stepsCounter++;
                }
                else
                {
                    invalidIndex=true;
                    break;
                }
                
                steps = X[p];
                sj.add(Integer.toString(X[p]));
                stepStore[num]=steps;
                num++;
                currentSetSize=st.size();
                
                if (q==r-1)
                {
                    for (int h=1; h<(rowsTriangle-1); h++)
                    {
                        if ((Math.abs(stepStore[h+1]-stepStore[h])>1))
                        {
                            invalidIndex=true;
                            break;
                        }
                        
                        if (stepStore[h+1]<stepStore[h])
                        {
                            invalidIndex=true;
                            break;
                        }
                    }
                    if (!invalidIndex)
                    {
                        num=0;
                        stepStore=new int[rowsTriangle];
                        stepsCounter=0;
                        
                        st.add(sj.toString());
                        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();
            cycles++;
            totalcycles++;
        }while (cycles<permutations*400);

        valuesSet = st.toArray(new String[st.size()]);
        backupValuesSetBeforeModification = st.toArray(new String[st.size()]);
        
        System.out.println("******************Contents of the backup set");
        System.out.println("******************Contents of the valuesSet");
        
        for (String g: valuesSet)
        {
            System.out.println("Subset " + subsetNumber+": " + g);
            subsetNumber++;
        }
        
        subsetNumber=1;
        
        for (String m: backupValuesSet)
        {
            n=0;
            do
            {
                if (m==valuesSet[n])
                {
                }
                
                n++;
                
            }while (n<valuesSet.length);
            
        }  //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");
        
        backupValuesSet= new ArrayList<>(Arrays.asList(backupValuesSetBeforeModification)); 
        
        for (int entry=0; entry<valuesSet.length; entry++)
        {
            if (valuesSet[entry]!="ALREADY PROCESSED")
            {
                System.out.println(valuesSet[entry] + "    Subset: " + subsetEntry  + "  at cycle number: " + totalcycles);
                subsetEntry++;
            
                //MAIN LOGIC OF THE NEW CODE OFFICIALLY STARTS HERE.
                obtainMoves(valuesSet[entry]);
            }
        }
        difference = newSetSize;
    }  //end of constructor...
        
    public void obtainMoves(String moves)
    {
        int[] nMoves = new int [r];
        int i=0;
        StringTokenizer sTok = new StringTokenizer(moves,",");
        
        while (sTok.hasMoreTokens())
        {
            temp=sTok.nextToken();
            nMoves[i]= Integer.valueOf(temp);
            i++;
        }
        performMoves(nMoves);
    }
        
    public void performMoves(int[] nMoves)
    {
        int total=0;
        
        for (int j=0; j<triangle[0].length; j++)
        {
            System.out.println("TRIANGLE " + (j));
            
            for (int k: nMoves)
            {
                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);
                }
                
                if ((triangle[i][j].length)>i+1)
                {
                    System.out.println("Ensure correct triangle configuration.");
                    System.exit(0);
                }
                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);
                }
                total=triangle[i][j][k] + total;
                indexesTriangle.add("["+ Integer.toString(i)+"]" + "["+ Integer.toString(j)+"]" + "["+ Integer.toString(k)+"]" );
                valuesTriangle.add(Integer.toString(triangle[i][j][k]));
                
                i++;  //increments the row
            }//end for nMoves
            
            i=0;
            System.out.println("*******TOTAL: " + total +"\n");
            processedMax=false;
            outcome = "Triangle: " + j +  " | Subset:" + (subsetEntry-1) + " " +"(" + valuesTriangle + ")" + " (Indexes: " + indexesTriangle +")" +" | " +  "Max value: " + total;
            valuesTriangle = new StringJoiner(",");
            indexesTriangle= new StringJoiner(",");
            
            if (total>max[j])
            {
                max[j]=total;
                int index=0;
                
                do
                {
                    outcomes[j][index]=null;
                    index++;
                    
                }while (index<permutations);
                
                index=0;
                outcomes[j][0]=outcome;
                count++;
                processedMax=true;
            }  //end of (total>max[j])
            
            if (total==max[j] && !processedMax)
            {
                outcomes[j][count] = outcome;
                max[j]=total;
                count++;
            }
            valuesTriangle=new StringJoiner(",");
            total=0;
            
            }//end for  (processing triangles)
            
            for (int c: max)
            {
                System.out.println("Highest total " + "triangle(" + triangleNumber+")" + "is: " + max[triangleNumber]);
                triangleNumber++;
            }
            System.out.println("-----------------------------------\n");
            
            triangleNumber=0;
    }  //end of method
} //end of class.

public class Permutation
{
    static int triangleNumber=0;
    static Staircase sc; //object of type Staircase
    static int numberTriangles;
    static int[] max;
    
    public static void main(String[] args) 
    {
        System.out.println("Welcome to Online IDE!! Happy Coding :)");
        Set <String> s = new HashSet<>();
        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}     },
                                        
                                                  };
    numberTriangles=triangle[0].length;
    int rowsTriangle = triangle.length;
    int [] X = new int [rowsTriangle];  
    
    for (int q=0; q<rowsTriangle; q++)
    {
        X[q]=q;
    }
    
    max = new int[numberTriangles];
    int counter=0;
    Map <Integer, Long> m;
    n=X.length;
    m= new HashMap<>();
    r=n;
    long perms = Permutations(n,r);
    String [][] outcomes = new String[numberTriangles][(int)(perms)];
    
    System.out.println("***PERMUTATIONS***(WITH REPLACEMENT)");
    System.out.println("PR(n,r) = nr");
    System.out.println("**********THE TRIANGLE COUNT CHALLENGE***********");
    sc = new Staircase (Permutations (n,r), X, r,s, triangle, numberTriangles, outcomes, max, rowsTriangle);
    
    System.out.println("\n\n*************SUMMARY HIGHEST RESULTS*************");
    System.out.println("*******TRIANGLES*********");
    System.out.println("***There are triangles configured*** : " + numberTriangles +"\n");
    
    for (int q=0;q<triangle.length;q++)
    {
      System.out.println(Arrays.deepToString(triangle[q]));
      triangleNumber++;
    }
    System.out.println("****************\n");
    
    triangleNumber=0;
    
    do
    {
        for (String str: sc.outcomes[triangleNumber])
        {
            if (str!=null)
            {
                System.out.println(str);
            }
        }
        triangleNumber++;
        
        }while(triangleNumber<triangle[0].length);
    }
    
    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);
    }
}//end permutation class 