
/*
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.*;
import java.util.stream.*;

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
{
    /*
    // Creating an integer array 
        int arr[] = { 1, 2, 3, 4, 5 }; 
  
        // Using Arrays.stream() to convert 
        // array into Stream 
        
    */
    
    int possibleNumbers[] = new int[]{1,2,3,4,5,6,7,8,9};
    //List<int> lst = new ArrayList<>(Arrays.asList(possibleNumbers));
    
    List<Integer> lst = new ArrayList<Integer>();
    
    long permutations;
    
    int threeBythree[][] = new int[3][3];    //0,0 0,1, 0,2  
                                             //1,0, 1,1, 1,2
                                             //2,0, 2,1, 2,2
    Set <int[][]> s = new HashSet<>();
    int currentSize;
    
    List<Integer> copy = new ArrayList<>(lst);
    boolean processedDivisibleTwo=false;
    
    
    public Sudoku(long permutations)
    {
        this.permutations =permutations;
       
       /* 
        
       
        for (int i=0; i<possibleNumbers.length; i++)
    {
        System.out.println("fucking here");
        lst.add(possibleNumbers[i]);
    }
    
    */
   
    fill3x3();
        
    }
    
    public void fill3x3()
    {
        //PSEUDO CODE
       
       //might be worth using stream in future
      
      int row=0;
      int col=0;
      int numbersProcessed;
      System.out.println("There are : " + permutations + " permutations of arranging  3 x 3 grid" );
      
      do
      {
          //lst=copy;  //restore the original list;
          
          
          IntStream stream = Arrays.stream(possibleNumbers); 
  
        // Displaying elements in Stream 
        stream.forEach(str -> lst.add(str));
        
        
          
          //fucking mistake here
          //why reset this at start of new set entry...
          
          //for a new attempt to add into the set, row continues from next row
          col=0;  //column will start again from 0 index, however it has already also done this below in modulus check
          numbersProcessed=0;
          
          System.out.println("This is the list size------: " + lst.size());
          
         
         
         // this is fucking wrong loop..
         //since the loop gets smaller in size... i will process what is left!!!
         //fucking!
         
         //for (int i=0; i<lst.size();i++)  // this will ensure process of random selection from lst
         
         do
         
         {
             processedDivisibleTwo=false;
             
             System.out.println("numbers processed:" + numbersProcessed);
           Random rand = new Random();
           
           int randomNumber = rand.nextInt(lst.size());   //this will get 0-9
      
      System.out.println("HERE!!!!");
      System.out.println(row);
      System.out.println(col);
      
      threeBythree[row][col]= lst.get(randomNumber);
      lst.remove(randomNumber);
      System.out.println("This is new list size: " + lst.size());
      System.out.println("CRASH");
            
      if (col%2==0 && col!=0)    // at this point it has populated row of 3 x 3 grid...
      {
          System.out.println("divisible");
          row++;  //it has to start a new row
          col=0;  //the column is reset back to 0
          processedDivisibleTwo = true;
      }
      
      if (!processedDivisibleTwo)   // it will only do this condition if it hasn't already been reset to 0 as part of new column above...
      {
      col++;  //otherwise it will increase the column in the given row by 1 until above condition is met...
      System.out.println("new column: " + col);
      }
      
      numbersProcessed++;
         }while(!lst.isEmpty());
      
      currentSize=s.size();
      System.out.println("This is the current set size: " + currentSize);
      
      s.add(threeBythree);
      
      }while (s.size()<permutations);
      
      
       
/*
numbers can be generated via random. and stored in int[row][col] array   (0-2 for rows and col)
get current set size
add int[row][col]  into the set
get new set size
continue until below condition....
}while (set.size()<P(9,9);  // can not do this... since these are permutations if sudoku not met...
// but at same time, it has to explore every single one.....


3 x 3 grids (9 total) filled into   9 x 9 grid    int[this will go from 0-8][value from  0-8]  (need to think about this!!)
                                                                                [between 0-2,  3-5,  6-8] [between 0-2,  3-5,  6-8]

//This will be the natural partitions of the set entries....
0-2
3-5
6-8

Checking at each time that the rows and columns do not contain duplicate numbers.....

Print out the grid to end user......

// this showing that it has placed all small 9 grids inside....
} while (!gridFull)
}  end for


*/

        
        
    }
    
    
    public void fill9x9()
    {
        
    }
    
    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) }
}
}
