Advertisement
LucasAlfare

Permutacoes

Sep 4th, 2019
420
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 5 16.49 KB | None | 0 0
  1. /**
  2.  ****************************************************************************************************************
  3.  * Copyright 2015 Fred Pang fred@pnode.com
  4.  ****************************************************************************************************************
  5.  * A complete list of Permutation base on an index.
  6.  * Algorithm is invented and implemented by Fred Pang fred@pnode.com
  7.  * Created by Fred Pang on 18/11/2015.
  8.  ****************************************************************************************************************
  9.  * LOL this is my first Java project. Therefore, my code is very much like C/C++. The coding itself is not
  10.  * very professional. but...
  11.  *
  12.  * This Permutation Class can be use to generate a complete list of all different permutation of a set of symbols.
  13.  * nPr will be n!/(n-r)!
  14.  * the user can input       n = the number of items,
  15.  *                          r = the number of slots for the items,
  16.  *                          provided n >= r
  17.  *                          and a string of single character symbols
  18.  *
  19.  * the program will generate all possible permutation for the condition.
  20.  *
  21.  * Say if n = 5, r = 3, and the string is "12345", it will generate sll 60 different permutation of the set
  22.  * of 3 character strings.
  23.  *
  24.  * The algorithm I used is base on a bin slot.
  25.  * Just like a human or simply myself to generate a permutation.
  26.  *
  27.  * if there are 5 symbols to chose from, I'll have 5 bin slot to indicate which symbol is taken.
  28.  *
  29.  * Note that, once the Permutation object is initialized, or after the constructor is called, the permutation
  30.  * table and all entries are defined, including an index.
  31.  *
  32.  * eg. if pass in value is 5 chose 3, and say the symbol string is "12345"
  33.  * then all permutation table is logically defined (not physically to save memory).
  34.  * It will be a table as follows
  35.  *  index  output
  36.  *      0   123
  37.  *      1   124
  38.  *      2   125
  39.  *      3   132
  40.  *      4   134
  41.  *      5   135
  42.  *      6   143
  43.  *      7   145
  44.  *      :     :
  45.  *      58  542
  46.  *      59  543
  47.  *
  48.  * all you need to do is call the "String PermGetString(int iIndex)" or the "int[] PermGetIntArray(int iIndex)"
  49.  * function or method with an increasing iIndex, starting from 0 to getiMaxIndex() - 1. It will return the string
  50.  * or the integer array corresponding to the index.
  51.  *
  52.  * Also notice that in the input string is "12345" of  position 01234, and the output is always in accenting order
  53.  * this is how the permutation is generated.
  54.  *
  55.  * ***************************************************************************************************************
  56.  * ====  W a r n i n g  ====
  57.  * ***************************************************************************************************************
  58.  *
  59.  * There is very limited error checking in this class
  60.  *
  61.  * Especially the  int PermGetIndex(int[] iInputArray)  method
  62.  * if the input integer array contains invalid index, it WILL crash the system
  63.  *
  64.  * the other is the string of symbol pass in when the object is created, not sure what will happen if the
  65.  * string is invalid.
  66.  * ***************************************************************************************************************
  67.  *
  68.  */
  69. public class Permutation
  70. {
  71.     private boolean bGoodToGo = false;      // object status
  72.     private boolean bNoSymbol = true;
  73.     private BinSlot slot;                   // a bin slot of size n (input)
  74.     private int nTotal;                     // n number for permutation
  75.     private int rChose;                     // r position to chose
  76.     private String sSymbol;                 // character string for symbol of each choice
  77.     private String sOutStr;
  78.     private int iMaxIndex;                  // maximum index allowed in the Get index function
  79.     private int[] iOutPosition;             // output array
  80.     private int[] iDivisorArray;            // array to do calculation
  81.  
  82.     public Permutation(int inCount, int irCount, String symbol)
  83.     {
  84.         if (inCount >= irCount)
  85.         {
  86.             // save all input values passed in
  87.             this.nTotal = inCount;
  88.             this.rChose = irCount;
  89.             this.sSymbol = symbol;
  90.  
  91.             // some error checking
  92.             if (inCount < irCount || irCount <= 0)
  93.                 return;                                 // do nothing will not set the bGoodToGo flag
  94.  
  95.             if (this.sSymbol.length() >= inCount)
  96.             {
  97.                 bNoSymbol = false;
  98.             }
  99.  
  100.             // allocate output storage
  101.             this.iOutPosition = new int[this.rChose];
  102.  
  103.             // initialize the bin slot with the right size
  104.             this.slot = new BinSlot(this.nTotal);
  105.  
  106.             // allocate and initialize divid array
  107.             this.iDivisorArray = new int[this.rChose];
  108.  
  109.             // calculate default values base on n & r
  110.             this.iMaxIndex = CalPremFormula(this.nTotal, this.rChose);
  111.  
  112.             int i;
  113.             int j = this.nTotal - 1;
  114.             int k = this.rChose - 1;
  115.  
  116.             for (i = 0; i < this.rChose; i++)
  117.             {
  118.                 this.iDivisorArray[i] = CalPremFormula(j--, k--);
  119.             }
  120.             bGoodToGo = true;       // we are ready to go
  121.         }
  122.     }
  123.  
  124.     public String PermGetString(int iIndex)
  125.     {
  126.         if (!this.bGoodToGo) return "Error: Object not initialized Correctly";
  127.         if (this.bNoSymbol) return "Error: Invalid symbol string";
  128.         if (!this.PermEvaluate(iIndex)) return "Invalid Index";
  129.  
  130.         sOutStr = "";
  131.         // convert string back to String output
  132.         for (int i = 0; i < this.rChose; i++)
  133.         {
  134.             String sTempStr = this.sSymbol.substring(this.iOutPosition[i], iOutPosition[i] + 1);
  135.             this.sOutStr = this.sOutStr.concat(sTempStr);
  136.         }
  137.         return this.sOutStr;
  138.     }
  139.  
  140.     public int[] PermGetIntArray(int iIndex)
  141.     {
  142.         if (!this.bGoodToGo) return null;
  143.         if (!this.PermEvaluate(iIndex)) return null ;
  144.         return this.iOutPosition;
  145.     }
  146.  
  147.     // given an int array, and get the index back.
  148.     //
  149.     //  ====== W A R N I N G ======
  150.     //
  151.     // there is no error check in the array that pass in
  152.     // if any invalid value in the input array, it can cause system crash or other unexpected result
  153.     //
  154.     // function pass in an int array generated by the PermGetIntArray() method
  155.     // then return the index value.
  156.     //
  157.     // this is the reverse of the PermGetIntArray()
  158.     //
  159.     public int PermGetIndex(int[] iInputArray)
  160.     {
  161.         if (!this.bGoodToGo) return -1;
  162.         return PermDoReverse(iInputArray);
  163.     }
  164.  
  165.  
  166.     public int getiMaxIndex() {
  167.     return iMaxIndex;
  168. }
  169.  
  170.     // function to evaluate nPr = n!/(n-r)!
  171.     public int CalPremFormula(int n, int r)
  172.     {
  173.         int j = n;
  174.         int k = 1;
  175.         for (int i = 0; i < r; i++, j--)
  176.         {
  177.             k *= j;
  178.         }
  179.         return k;
  180.     }
  181.  
  182.  
  183. //  PermEvaluate function (method) base on an index input, evaluate the correspond permuted symbol location
  184. //  then output it to the iOutPosition array.
  185. //
  186. //  In the iOutPosition[], each array element corresponding to the symbol location in the input string symbol.
  187. //  from location 0 to length of string - 1.
  188.  
  189.     private boolean PermEvaluate(int iIndex)
  190.     {
  191.         int iCurrentIndex;
  192.         int iCurrentRemainder;
  193.         int iCurrentValue = iIndex;
  194.         int iCurrentOutSlot;
  195.         int iLoopCount;
  196.  
  197.         if (iIndex >= iMaxIndex)
  198.             return false;
  199.  
  200.         this.slot.binReset();               // clear bin content
  201.         iLoopCount = 0;
  202.         do {
  203.             // evaluate the table position
  204.             iCurrentIndex = iCurrentValue / this.iDivisorArray[iLoopCount];
  205.             iCurrentRemainder = iCurrentValue % this.iDivisorArray[iLoopCount];
  206.  
  207.             iCurrentOutSlot = this.slot.FindFreeBin(iCurrentIndex);     // find an available slot
  208.             if (iCurrentOutSlot >= 0)
  209.                 this.iOutPosition[iLoopCount] = iCurrentOutSlot;
  210.             else return false;                                          // fail to find a slot, quit now
  211.  
  212.             this.slot.setStatus(iCurrentOutSlot);                       // set the slot to be taken
  213.             iCurrentValue = iCurrentRemainder;                          // set new value for current value.
  214.             iLoopCount++;                                               // increase counter
  215.         } while (iLoopCount < this.rChose);
  216.  
  217.         // the output is ready in iOutPosition[]
  218.         return true;
  219.     }
  220.  
  221.     //
  222.     // this function is doing the reverse of the permutation
  223.     // the input is a permutation and will find the correspond index value for that entry
  224.     // which is doing the opposit of the PermEvaluate() method
  225.     //
  226.     private int PermDoReverse(int[] iInputArray)
  227.     {
  228.         int iReturnValue = 0;
  229.         int iLoopIndex;
  230.         int iCurrentValue;
  231.         int iBinLocation;
  232.  
  233.         this.slot.binReset();               // clear bin content
  234.  
  235.         for (iLoopIndex = 0; iLoopIndex < this.rChose; iLoopIndex++)
  236.         {
  237.             iCurrentValue = iInputArray[iLoopIndex];
  238.             iBinLocation = this.slot.BinCountFree(iCurrentValue);
  239.             this.slot.setStatus(iCurrentValue);                          // set the slot to be taken
  240.             iReturnValue = iReturnValue + iBinLocation * this.iDivisorArray[iLoopIndex];
  241.         }
  242.         return iReturnValue;
  243.     }
  244.  
  245.  
  246.     /*******************************************************************************************************************
  247.      *******************************************************************************************************************
  248.      * Created by Fred on 18/11/2015.   fred@pnode.com
  249.      *
  250.      * *****************************************************************************************************************
  251.      */
  252.     private static class BinSlot
  253.     {
  254.         private int iBinSize;       // size of array
  255.         private short[] eStatus;    // the status array must have length iBinSize
  256.  
  257.         private BinSlot(int iBinSize)
  258.         {
  259.             this.iBinSize = iBinSize;               // save bin size
  260.             this.eStatus = new short[iBinSize];     // llocate status array
  261.         }
  262.  
  263.         // reset the bin content. no symbol is in use
  264.         private void binReset()
  265.         {
  266.             // reset the bin's content
  267.             for (int i = 0; i < this.iBinSize; i++) this.eStatus[i] = 0;
  268.         }
  269.  
  270.         // set the bin position as taken or the number is already used, cannot be use again.
  271.         private void  setStatus(int iIndex) { this.eStatus[iIndex]= 1; }
  272.  
  273.         //
  274.         // to search for the iIndex th unused symbol
  275.         // this is important to search through the iindex th symbol
  276.         // because this is how the table is setup. (or the remainder means)
  277.         // note: iIndex is the remainder of the calculation
  278.         //
  279.         // for example:
  280.         // in a 5 choose 3 permutation symbols "12345",
  281.         // the index 7 item (count starting from 0) element is "1 4 3"
  282.         // then comes the index 8, 8/12 result 0 -> 0th symbol in symbol string = '1'
  283.         // remainder 8. then 8/3 = 2, now we need to scan the Bin and skip 2 unused bins
  284.         //              current the bin looks 0 1 2 3 4
  285.         //                                    x o o o o     x -> in use; o -> free only 0 is being used
  286.         //                                      s s ^       skipped 2 bins (bin 1 and 2), we get to bin 3
  287.         //                                                  and bin 3 is the bin needed. Thus symbol "4" is pick
  288.         // in 8/3, there is a remainder 2 comes in this function as 2/1 = 2, now we have to pick the empty slot
  289.         // for the new 2.
  290.         // the bin now looks 0 1 2 3 4
  291.         //                   x 0 0 x 0      as bin 3 was used by the last value
  292.         //                     s s   ^      we skip 2 free bins and the next free bin is bin 4
  293.         //                                  therefor the symbol "5" at the symbol array is pick.
  294.         //
  295.         // Thus, for index 8  "1 4 5" is the symbols.
  296.         //
  297.         //
  298.         private int FindFreeBin(int iIndex)
  299.         {
  300.             int j = iIndex;
  301.  
  302.             if (j < 0 || j > this.iBinSize) return -1;               // invalid index
  303.  
  304.             for (int i = 0; i < this.iBinSize; i++)
  305.             {
  306.                 if (this.eStatus[i] == 0)       // is it used
  307.                 {
  308.                     // found an empty slot
  309.                     if (j == 0)                 // this is a free one we want?
  310.                         return i;               // yes, found and return it.
  311.                     else                        // we have to skip this one
  312.                         j--;                    // else, keep looking and count the skipped one
  313.                 }
  314.             }
  315.             assert(true);           // something is wrong
  316.             return -1;              // fail to find the bin we wanted
  317.         }
  318.  
  319.         //
  320.         // this function is to help the PermDoReverse() to find out what is the corresponding
  321.         // value during should be added to the index value.
  322.         //
  323.         // it is doing the opposite of int FindFreeBin(int iIndex) method. You need to know how this
  324.         // FindFreeBin() works before looking into this function.
  325.         //
  326.         private int BinCountFree(int iIndex)
  327.         {
  328.             int iRetVal = 0;
  329.             for (int i = iIndex; i > 0; i--)
  330.             {
  331.                 if (this.eStatus[i-1] == 0)       // it is free
  332.                 {
  333.                     iRetVal++;
  334.                 }
  335.             }
  336.             return iRetVal;
  337.         }
  338.     }
  339. }
  340. // End of file - Permutation.java
  341.  
  342. /*
  343.  * copyright 2015 Fred Pang
  344.  *
  345.  * This is the main test program for testing the Permutation Class I created.
  346.  * It can be use to demonstrate how to use the Permutation Class and its methods to generate a complete
  347.  * list of a permutation. It also support function to get back the index value as pass in a permutation.
  348.  *
  349.  * As you can see my Java is not very good. :)
  350.  * This is my 1st Java project I created. As I am a C/C++ programmer for years.
  351.  *
  352.  * I still have problem with the Scanner class and the System class.
  353.  * Note that there is only very limited error checking
  354.  *
  355.  *
  356.  */
  357.  
  358. import java.util.Scanner;
  359.  
  360. public class Main
  361. {
  362.     private static Scanner scanner = new Scanner(System.in);
  363.  
  364.     public static void main(String[] args)
  365.     {
  366.         Permutation perm;       // declear the object
  367.         String sOutString = "";
  368.         int nCount;
  369.         int rCount;
  370.         int iMaxIndex;
  371.  
  372.         // Get user input
  373.         System.out.println("Enter n: ");
  374.         nCount = scanner.nextInt();
  375.  
  376.         System.out.println("Enter r: ");
  377.         rCount = scanner.nextInt();
  378.  
  379.         System.out.println("Enter Symbol: ");
  380.         sOutString = scanner.next();
  381.  
  382.         if (sOutString.length() < rCount)
  383.         {
  384.             System.out.println("String too short, default to numbers");
  385.             sOutString = "";
  386.         }
  387.  
  388.         // create object with user requirement
  389.         perm = new Permutation(nCount, rCount, sOutString);
  390.  
  391.         // and print the maximum count
  392.         iMaxIndex = perm.getiMaxIndex();
  393.         System.out.println("Max count is:" + iMaxIndex);
  394.  
  395.         if (!sOutString.isEmpty())
  396.         {
  397.             for (int i = 0; i < iMaxIndex; i++)
  398.             {   // print out the return permutation symbol string
  399.                 System.out.println(i + " " + perm.PermGetString(i));
  400.             }
  401.         }
  402.         else
  403.         {
  404.             for (int i = 0; i < iMaxIndex; i++)
  405.             {
  406.                 System.out.print(i + " ->");
  407.  
  408.                 // Get the permutation array
  409.                 int[] iTemp = perm.PermGetIntArray(i);
  410.  
  411.                 // print out the permutation
  412.                 for (int j = 0; j < rCount; j++)
  413.                 {
  414.                     System.out.print(' ');
  415.                     System.out.print(iTemp[j]);
  416.                 }
  417.  
  418.                 // to verify my PermGetIndex() works. :)
  419.                 if (perm.PermGetIndex(iTemp)== i)
  420.                 {
  421.                     System.out.println(" .");
  422.                 }
  423.                 else
  424.                 {   // oops something is wrong :(
  425.                     System.out.println(" ***************** F A I L E D *************************");
  426.                     assert(true);
  427.                     break;
  428.                 }
  429.             }
  430.         }
  431.     }
  432. }
  433. //
  434. // End of file - Main.java
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement