//*** 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 temp1;
    String mapping;
    Object possibleMappingFirst;
    Object possibleMappingSecond;
    long permutations;
    StringJoiner sj;
    int num;
    int r;
    
    int cycles=0;
    int totalcycles=0;
    int difference = 0;
    
    List <String> backupValuesSet = new ArrayList<>();
    
    String originalString;
    Map<Integer,String> possibleLetters;
    Map<Integer, String> mp;
    Set<String> st;
    Random rand = new Random();
    String[] valuesSet; 
    String []backupValuesSetBeforeModification;
    int subsetEntry=1;
    
    
    public Staircase(long permutations, Map<Integer,String> mp, Map<Integer,String> possibleLetters, int r, Object possibleMappingFirst, Object possibleMappingSecond, String originalString)
    {
        this.originalString=originalString;
        this.permutations=permutations;
        this.mp=mp;
        this.possibleLetters=possibleLetters;
        //this.rMin=rMin;
        //this.rMax=rMax;
        this.possibleMappingFirst=possibleMappingFirst;
        this.possibleMappingSecond=possibleMappingSecond;
        this.r=r;
        
        sj = new StringJoiner("");
        boolean invalidIndex=false;
        
        int currentSetSize=0;
        int newSetSize;
        int subsetNumber=1;
        int steps;
        String subsetIntToString="";
        int pos=0;
        int n=0;
        String secondScenarioMapping="";
        String firstScenarioMapping="";
       
        System.out.println("*************INITIAL VALUE OF  CYCLES: " + cycles);
        
        do
        {
            //need to understand the boundaries here a bit better
            //this recursive method will be called for r = rMin   to  r< rMax
            //P(n,r)
            
            //When it gets to here, it needs to focus on r
            
            
            for (int q=0; q<r;q++)
            {
                if (invalidIndex)
                {
                    sj=new StringJoiner("");
                    invalidIndex=false;
                    num=0;
                }
                
                temp1 = rand.nextInt(possibleLetters.size()) + 1;      //this should get random number between
                
                System.out.println("this is random number: " + temp1);
                //System.out.println("mapping: " + )
                
                
                if (q==0)
                {
                //using randon number to get value from possibleLetters of the Map
                firstScenarioMapping  = possibleLetters.get(temp1);
                System.out.println("Q is 0: " + firstScenarioMapping);
                }
                
                
                if (q==1)
                {
                secondScenarioMapping = firstScenarioMapping + possibleLetters.get(temp1);
                }
                
                
                if (q==1)
            {
                
                if (firstScenarioMapping.equals(possibleMappingFirst)  || secondScenarioMapping.equals(possibleMappingSecond))
                {
                    //here we need to really fill the mapping directly into
                    mapping = firstScenarioMapping;
                }
            }
                else
                {
                    invalidIndex=true;
                    break;
                }
                
                sj.add(mapping);
                currentSetSize=st.size();
                
                 if (!invalidIndex)
                    {
                        System.out.println("INCREASED SET");
                        st.add(sj.toString());
                        sj = new StringJoiner("");
                        
                    }  //end of if (!invalidIndex)
                
                
            }   //end of for (int q=0; q<r;q++)
            
            System.out.println("HERE");
            
            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.
                checkMappings(valuesSet[entry]);
            }
        }
        difference = newSetSize;
    }  //end of constructor...
    
    public void checkMappings (String storedEntry)
    {
        if (storedEntry.equals(originalString))
        {
            System.out.println("This is a valid translation: " + storedEntry + " for encoding: " + originalString);
        }
        
    }
   
} //end of class.

public class Permutation
{
    enum Keys
    {
        A(1),B(2),C(3),D(4),E(5),F(6),G(7),H(8),I(9),J(10),K(11),L(12),M(13),N(14),O(15),P(16),Q(17),R(18),S(19),T(20),U(21),V(22),W(23),X(24),Y(25),Z(26);
        
        int map;
        
        Keys(int map)
        {
            this.map=map;
        }
    }
    
    
    
    
    public static void main(String[] args) 
    {
        Keys k = Keys.A;
    int m = k.map;
    
        
        
        System.out.println("Welcome to Online IDE!! Happy Coding :)");
        
        Map <Integer,String> mp = new HashMap<Integer,String>();
        Map <Integer, String> possibleLetters = new HashMap <Integer, String>();  
        String possibleMappingFirst="";
        String possibleMappingSecond="";
        Staircase sc;
        String temp="";
            
        mp.put(1,"A");
        mp.put(2,"B");
        mp.put(3,"C");
        mp.put(4,"D");
        mp.put(5,"E");
        mp.put(6,"F");
        mp.put(7,"G");
        mp.put(8,"H");
        mp.put(9,"I");
        mp.put(10,"J");
        mp.put(11,"K");
        mp.put(12,"L");
        mp.put(13,"M");
        mp.put(14,"N");
        mp.put(15,"O");
        mp.put(16,"P");
        mp.put(17,"Q");
        mp.put(18,"R");
        mp.put(19,"S");
        mp.put(20,"T");
        mp.put(21,"U");
        mp.put(22,"V");
        mp.put(23,"W");
        mp.put(24,"X");
        mp.put(25,"Y");
        mp.put(26,"Z");
        
        int rMin;
        int r=0;
        String str = "121222";   //this is encoded message I have referenced in my logic documentation
        int rMax = str.length();
        int n=str.length();
        int rLimit = 64;  //taken to be 64 from past experience.
            
        for (int i=0; i<str.length();i++)
        {
            System.out.println("Value of i: " + i);
            
            //need to get the digits out, and search the map for the key  and get the value
            
            //ALSO NEED TO EXAMINE THIS AGAIN TO GET THE LETTERS
            
            
            int digitToInteger = Character.getNumericValue(str.charAt(i));
            
            
            if (mp.containsKey(digitToInteger))
            {
                temp = mp.get(digitToInteger);
                //tempString = Object.toString(temp);
                
                possibleLetters.put(i,temp);   //only need to store the String here since should not be indexing again?
                //System.out.println("Following " + i + " has been filled with temp: " + temp + possibleLetters.getKey());
                
            }
            
            if (i==0)
            {
                possibleMappingFirst = temp;
            }
            
            if (i==1)
            {
                possibleMappingSecond = possibleMappingFirst + temp;
            }
        }
        
        if (str.length()%2==1)
        {
            rMin=(str.length()+1)/2;
        }
        else
        {
            rMin=str.length()/2;
        }
        
        
        if (rMax>=rLimit)
        {
            System.out.println("rMax " + " will affect recursion");
        }
    
        System.out.println("***PERMUTATIONS***(WITH REPLACEMENT)");
        System.out.println("PR(n,r) = nr");
        System.out.println("**********THE ENCODED MESSAGE TRANSLATION***********");
        System.out.println("This is encoded message: " + str);
        
        for (int i=rMin; i<rMax; i++)
        {
        sc = new Staircase (Permutations (n,r), mp,possibleLetters, i, possibleMappingFirst,possibleMappingSecond, str);
        }
    }
        
        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 