10-1100-cjeagleA1Code

From Drorbn
Jump to navigationJump to search

This is the C++ source code I used to solve the MegaMinx. Aside from (BigInteger by Matt McCutcheon), which is a class in the public domain, it uses only standard C++. The algorithm is not terribly efficient (took about 6 hours to run), but it got the job done.




#include <cstdlib>
#include <iostream>
#include <fstream>
#include <vector>
#include "BigIntegerLibrary.hh"             

using namespace std;

//sloppy code, but it made it easier to write
const int N = 132;
const int numGens = 12;

typedef vector<int> perm;

perm table[N][N];
perm ID;
perm blank;

/*to make it easier to input generating permutations
this algorithm takes in a list of an even number of numbers
and produces the permutation which sends a(i) to a(i+1) for each even i*/
perm permGen(vector<int> a){
     perm result(N);
     
     for(int i=0;i<N; i++){
             result[i] = i;
     }
     for(int i=0;i<a.size()-1;i+=2){
             result[a[i]]=a[i+1];
     }
     return result;
}

//an error-checking routine, making sure every element of the table is
//a valid permutation
bool isPerm(perm a){
     int checkr[N];
     for(int i=0;i<N;i++){
             for(int j=0;j<N;j++){
                     if(a[j] == i){checkr[i] = i;}
             }
     }
     
     for(int i=0; i<N;i++){
             if(checkr[i] != i){return false;}
     }
     return true;
}

//tests if two tables of permutations are the same
bool tableEqual(perm a[N][N], perm b[N][N]){
     for(int i=0; i<N; i++){
             for(int j=0; j<N; j++){
                     if(a[i][j] != b[i][j]){return false;}
             }
     }
     return true;
}

//Write one permutation to standard output
//Used for testing and error-checking
void permOutput(perm a){
     cout << "[";
     for(int i=0; i<N; i++){
             cout << a[i] << " ";
     }
     cout << "]";
}

//write the entire table to standard output
//this was useful in testing on small groups, but would not be suitable for
//groups as large as the MegaMinx
void tableOutput(){
     for(int i=0;i<N;i++){
             for(int j=0;j<N;j++){
                     permOutput(table[i][j]);
                     cout << "   ";
             }
             cout << endl;
     }
}

//find the pivot position of a permutation
int pivotPosition(perm s){
    for(int i=0; i<N; i++){
            if(s[i] != i) return i;
    }
    return -1;
}

//given permutations a and b, produce ab
perm mult(perm a, perm b){
     perm result(N);
     for(int i=0; i<N; i++){
        result[i] = a[b[i]];
     }

     return result;
}

//given a permutation a, produce a^{-1}
perm invert(perm a){
     perm result(N);
     for(int i=0;i<N;i++){
        for(int j=0;j<N;j++){
          if(a[j] == i){result[i] = j;}
        }
     }
     return result;
}

//the Feed algorithm from class
void Feed(perm s) {
     if(s == ID){return;}
     
     int pivot = pivotPosition(s);
     int value = s[pivot];
     if(table[pivot][value] == blank){
        table[pivot][value] = s;
        return;
     }
     
     Feed(mult(invert(table[pivot][value]), s));   
}

//compute the product of the sizes of the columns in the table
BigInteger groupOrder(){
     BigInteger result = 1;
     BigInteger colSize[N];
     for(int i=0; i<N; i++){
             colSize[i] = 0;
             for(int j=0;j<N;j++){
                     if(table[i][j] != blank){colSize[i] = colSize[i]+1;}
             }
     }
     
     for(int i=0; i<N; i++){
             result = result * colSize[i];
     }
     
     return result;
}
           
int main(int argc, char *argv[])
{
    ofstream outputFile;
    outputFile.open("megaminx.txt");
    
    outputFile << "MegaMinx" << endl << endl;
    //start by initializing the two constant permutations - blank and identity.
    //we make blank and invalid permutation for easier error-checking
    for(int i=0; i<N; i++){
            ID.push_back(i);
            blank.push_back(-1);
    }

    perm generators[numGens];

/*Generators come from rotating the marked face counterclockwise*/
  int gens[numGens][50] = {
      {3,1,10,3,0,10,7,0,1,7,6,2,9,6,8,9,4,8,2,4,17,55,14,56,11,57,55,46,56,49,57,53,46,101,49,104,53,108,101,110,104,111,108,112,110,17,111,14,112,11},                                         /*orange*/
      {20,13,21,20,17,21,11,17,13,11,19,16,18,19,14,18,12,14,16,12,112,72,115,69,119,66,72,28,69,25,66,22,28,61,25,58,22,55,61,3,58,6,55,10,3,112,6,115,10,119},                                 /*grey*/
      {31,24,32,31,28,32,22,28,24,22,27,23,30,27,29,30,25,29,23,25,66,77,67,78,68,79,77,39,78,36,79,33,39,65,36,62,33,61,65,13,62,16,61,20,13,66,16,67,20,68},                                   /*red*/
      {35,33,42,35,43,42,39,43,33,39,38,34,41,38,40,41,36,40,34,36,79,88,82,89,86,90,88,50,89,47,90,44,50,64,47,63,44,65,64,24,63,27,65,31,24,79,27,82,31,86},                                   /*light blue*/
      {46,44,53,46,54,53,50,54,44,50,49,45,52,49,51,52,47,51,45,47,90,99,93,100,97,101,99,7,100,4,101,1,7,57,4,60,1,64,57,35,60,38,64,42,35,90,38,93,42,97},                                     /*light brown*/
      {57,55,64,57,65,64,61,65,55,61,60,56,63,60,62,63,58,62,56,58,22,33,23,34,24,35,33,44,34,45,35,46,44,1,45,2,46,3,1,11,2,12,3,13,11,22,12,23,13,24},                                         /*purple*/
      {68,66,75,68,76,75,72,76,66,72,71,67,74,71,73,74,69,73,67,69,119,127,118,124,120,121,127,83,124,80,121,77,83,32,80,29,77,28,32,20,29,19,28,21,20,119,19,118,21,120},                       /*light green*/
      {86,79,87,86,83,87,77,83,79,77,82,78,85,82,84,85,80,84,78,80,121,94,122,91,123,88,94,43,91,40,88,39,43,31,40,30,39,32,31,68,30,71,32,75,68,121,71,122,75,123},                             /*dark brown*/
      {97,90,98,97,94,98,88,94,90,88,93,89,96,93,95,96,91,95,89,91,123,105,126,102,130,99,105,54,102,51,99,50,54,42,51,41,50,43,42,86,41,85,43,87,86,123,85,126,87,130},                         /*pink*/
      {108,101,109,108,105,109,99,105,101,99,104,100,107,104,106,107,102,106,100,102,130,116,129,113,131,110,116,0,113,8,110,7,0,53,8,52,7,54,53,97,52,96,54,98,97,130,96,129,98,131},           /*dark green*/
      {119,112,120,119,116,120,110,116,112,110,115,111,118,115,117,118,113,117,111,113,131,76,128,73,127,72,76,21,73,18,72,17,21,10,18,9,17,0,10,108,9,107,0,109,108,131,107,128,109,127},       /*dark blue*/
      {123,121,130,123,131,130,127,131,121,127,122,124,126,122,129,126,128,129,124,128,120,109,117,106,116,105,109,98,106,95,105,94,98,87,95,84,94,83,87,75,84,74,83,76,75,120,74,117,76,116}    /*magenta*/
  };
  
  //construct the actual generators from the above list
  for(int i=0;i<numGens; i++){
          generators[i] = permGen(vector<int>(gens[i], gens[i]+50));
  }
  
  //prepare a blank table
    for(int i=0; i<N; i++){
            for(int j=0; j<N; j++){
                    table[i][j] = blank;
            }
    }
            
    //set the diagonal of the table to be the identity permutation
    for(int i=0; i<N; i++){
             table[i][i] = ID;
    }
    
    //write out the complete list of generators
    outputFile << "The generating permutations are: " << endl;
    for(int i=0;i<numGens;i++){
            outputFile << "[";
            for(int j=0; j<N; j++){
                    outputFile << generators[i][j] << " ";
            }
            outputFile << "]" << endl;
    }
    
    //Feed the generators into the table
    for(int i=0; i<numGens; i++){
            Feed(generators[i]);
    }

    perm tableCopy[N][N];
    
    do{
       //put a copy of table in tableCopy, so we can check if anything changed
        for(int i=0; i<N; i++){
            for(int j=0;j<N;j++){
                    tableCopy[i][j] = perm(table[i][j]);
            }
        }
        
        //check each pair of indices.  Every time we find (i,j) and (k,l) such that
        //table[i][j] and table[k][l] have entries, we feed the product of those entries
        for(int i=0;i<N;i++){
                for(int j=0; j<N; j++){
                        if(table[i][j] != blank){
                                       for(int k=0;k<N;k++){
                                               for(int l=0;l<N;l++){
                                                       if(table[k][l] != blank){
                                                                      Feed(mult(table[i][j], table[k][l]));
                                                       }
                                               }
                                       }
                        }
                }
        }
        //keep on going until nothing changes
    }while(!tableEqual(tableCopy, table));    
    
    //now the size of G is the product of the sizes of the columns.
    BigInteger orderOfGroup = groupOrder();
    outputFile << endl << endl << "The order of the subgroup of S_132 generated by the above is: " << orderOfGroup;
    outputFile.close();
    return 0;
}