//BIG ISSUE WITH MAP IS THAT IT ALLOWS DUPLICATE VALUES!!!!

/*
/*
Online Java - IDE, Code Editor, Compiler

Online Java is a quick and easy tool that helps you to build, compile, test your programs online.
*/

//suduko challenge
//each  3 x 3   all numbers 1-9
//each row, each column must contain all numbers 1-9

// it is without replacement... but the order does matter to ensure grid is filled differently...
//P(n,r) = P(9,9) = 362880
// need do while loop while   set.size< 362800

//Now there are 9 positions for  each   3 x 3 grid
//Need to process again,  and check if   rows contain 1-9,  cols contain  1-9

// 



// in the currency example, 

/*

public class Main
{
    public static void main(String[] args) {
        System.out.println("Welcome to Online IDE!! Happy Coding :)");
    }
}
*/



/*
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 nPr permutation calculator.
// It has used techniques I learnt including recursion and also memoization to speed up execution.
// I will incorporate this into Java applications I created
//TEST CASES
//r=2 n=5 PASS
//r=5 n=5 PASS
//r=1 n=4 PASS
//r=0 n=3 PASS
//r=0 n=0 PASS
// now going to flip the above
//r=5 n=2 PASS
//r=5 n=5 PASS
//r=4 n=1 PASS
//r=3 n=0 PASS
//test to make numerator less than r
// n = 4 r=3 PASS
import java.math.*;
import java.util.*;

interface Fillable
{
    public void fill3x3();
    public void fill9x9();
    public boolean checkUniqueRows();
    public boolean checkUniqueColumns();
    public void place3X3Into9x9();
    public boolean SudokuComplete();
    public void get9x9Grid();
    public void get3x3Grid();
    
}


class Sudoku implements Fillable
{
    int numbers[] = new int[]{1,2,3,4,5,6,7,8,9};
    
    Random rnd = new Random();
    
    long permutations;
    
    Map <Integer, int[][]> threeByThree = new HashMap <>();
    
    
    
    public Sudoku(long permutations)
    {
        this.permutations =permutations;
        
    }
    
    public void fill3x3()
    {
        
        int[][] miniBoard=new int [][]{{0,0,0},{0,0,0},{0,0,0}};    // this will create 3 x 3 board with all zeros
        int totalMiniBoards=9;
        
        //since we need 9 miniBoards, best to create them in HashMap..
        // this seems like best way to access them uniquely with a key...
        
        //might want to try and use streams in future for better code....
        
        for (int k=0; k<totalMiniBoards; k++)
        {
            threeByThree.put(k, miniBoard);
        }
        
        
    }
    
    
    public void fill9x9()
    {
        int column=0;
        int row=0;
        int gridCount=0;
        
        // this will contain 3 x 3 of  9 miniBoards currently in Map
        
        //Can you add a map in a map.
        //This will now be issue, also it will require to be 3 x 3....
        
        
        //this is just to test if possible to put a map inside....
        
        Map <Integer, Map> nineByNine [][]  = new HashMap[2][2];
        
        
        //now need to add the threeByThree boards into nineByNine 
        for (Map.Entry<Integer, int[][]> ent: threeByThree.entrySet())
        {
            nineByNine[row][counter].put(gridCount,(Map)ent);
            
            column++;
            gridCount++;
            
            //if the row is filled up, need to start a new row...
            if (column==2)
            {
                row++;    // row increased
                column=0;  //
            }

            
        }
        
        
        
                    //}
        
        
        //int fullBoard[][] = new int [][] {Arrays.toInteger(miniBoard)
        
    }
    
    public boolean checkUniqueRows()
    {
        return false;
        
    }
    public boolean checkUniqueColumns()
    {
        return false;
        
    }
    public void place3X3Into9x9()
    {
        
    }
    public boolean SudokuComplete()
    {
        return false;
        
    }
    public void get9x9Grid()
    {
        
    }
    public void get3x3Grid()
    {
        
    }
}



public class Permutation
{
public static void main(String[] args) {
System.out.println("Welcome to Online IDE!! Happy Coding :)");
int originalNumber=9;
int n=originalNumber;
int r =9;
Map <Integer, Long> m = new HashMap<>();
System.out.println("***PERMUTATIONS***");
System.out.println("P(n,r) = n! / (n−r)!");
System.out.println("P(" + n+","+r+") = " + n+"!" + " / " + "("+n+"-"+r+")!");

Sudoku sud = new Sudoku (Permutations (n,r,originalNumber, m));


//System.out.println(Permutations (n,r,originalNumber, m));
}
public static long Permutations (int n, int r, int originalNumber, Map factorialResults)
{
// n are objects
// r is sample
/*
***CALCULATION***
P(n,r) = n! / (n−r)!
*/
long result=0;
int temp;
int denominator;
if (originalNumber<r || r<0)
{
System.out.println("please enter n ≥ r ≥ 0");
System.exit(0);
return 0;
}
if (n>=1)
{
// EXAMPLE
// P (5,6) = 5* 4 * 3 * 2 * 1 / (6-5)! = 24 / 2! = 24 / 2 * 1 = 24/2 = 12
result = (n* (Permutations (n-1, r,originalNumber, factorialResults))); // this completes factorial for numerator
factorialResults.put(n,result); //result stored in the Map
//System.out.println("getting result back out numerator " + n+": " + factorialResults.get(n));
if (n==originalNumber) // this will occur once
{
denominator = originalNumber-r; // originalNumber required since n has reduced as part of the recursive calls
//System.out.println("This is denominator: " + denominator);
// this is using the Java Memoization technique to ensure the factorial outcome is not calculated again, to save program execution cycles.
// since the returns are done in reverse order.... n = 1 is processed first and n=6 last...
//Hence in practice there will be entry in Map for all factorials, ready for the denominator..
if (factorialResults.containsKey(denominator))
{
//System.out.println("here");
//System.out.println("This is exact value of factorial denominator " + (denominator) + " : " + factorialResults.get(denominator));
return result / (long)factorialResults.get(denominator); // this is number permutations
}
}
return result; // this will be returning already calculating numerator part
}
return 1; // // it should reach here if this is false: (n>=1) }
}
}
