Math 102

Programming Project #1

A Visual C++ Program to Multiply Permutations


These instructions assume that you have never used Visual C++ before and that you may have only limited experience with programming in C or C++.

You will create a Visual C++ program that lets you specify two permutations like a = (123) and b= (14)(35), form the products a*b and b*a, and compute and display all the powers of a, b and the two products.  For the user-interface parts of the program, you need only follow instructions, but you will have to implement the "real mathematics" yourself.

In building this program you will learn the following features of Visual C++:
Dialog-based applications -- the simplest type, but all you are likely to need.
Buttons -- the simplest way to control a program interactively.
Edit controls (also known as edit boxes or as edit-box controls) -- the easiest way to display single numbers or strings of  text.
Static text controls and group boxes -- for identifying what your edit controls are displaying.
List boxes -- a convenient way to display many steps of a calculation.
int type variables -- useful for holding positive or negative integers up to about 2 billion in magnitude.
CString variables -- the simple way to hold text.

There are three stages in building the application.
Stage 1. Create a dialog-based application and lay out the controls you want.  This does not require you to write any code.  You just use a program-writing tool called an AppWizard and a graphical dialog editor.  At the end of this stage you will have a working C++ program and will be able to see what your finished application looks like.

Stage 2. Associate C++ variables with the graphical objects in your dialog.  You still don't need to write any code, since everything is done by a tool called ClassWizard.  At the end of this stage you will have C++ functions that will get called when your buttons are pressed, but they will contain no code.

Stage 3. Write the definitions of the C++ functions in your program.  This is where the mathematics comes in.  As you do this, you will probably want to add a few more functions of your own that are not connected with buttons and a few more variables that are not connected with edit controls.

To get started you will need to have a PC with Windows 95, 98, 2000, or  NT and Visual C++ version 6.  Visual C++ version 5 will also suffice,  but be warned that if you move a project from version 5 to version 6 it will  get upgraded and you cannot go back to version 5!

In the "Bamberg terminal room" (Science Center 101e) are two computers (the ones farthest from the door, in the little enclosures) with Visual C++ 6. To get into the room, press (35 together) (24 together) 1.   The two Dell computers have Visual C++ 5, which is also adequate for anything except modifying existing version 6 projects.

You can create a top-level folder on the hard drive of one of these computers for yourself, but when you are done with a session, please delete the Debug and/or Release folders under your project.  They are enormous, and they are easily rebuilt.  Once you have deleted these folders (on used the "Clean" command from the Visual C++ build menu) your project will easily fit on a floppy disc, and that is how you should hand it in.  Be sure to put your name on the floppy!

If you have a Windows computer, you should be able to buy a copy of Visual C++ for the educational price of $45.00.  Try the Harvard Technology Product Center on Dunster St, the Harvard Coop, or Microsoft's Web Site.  This is one of the great software bargains of all times.  

1. Click the "Microsoft Visual C++ 6.0" icon on the desktop, or go to Start...Programs...Microsoft Visual C++ 6.0...Microsoft Visual C++ 6.0 if there is no icon on the desktop.  From the menu select File...New.  Click on the Projects tab, then click on MFC AppWizard(exe).  In the location box, choose a folder in which to keep your MathS15 projects.  If your name is Smith, a reasonable choice would be C:\Smith\MathS15\.
As the project name, type in Permute..  Notice that the project name also becomes a new subfolder under "Location."  Now click OK to start the AppWizard.

2. In Step 1, select Dialog Based, then click Next.
   In Step 2, uncheck About Box and ActiveX Controls. Change the title to "Multiplying Permutations."  Click Next.
    In Step 3, just click Next.
   In Step 4, just click Finish.  (Actually, you could have clicked Finish back in Step 2).  Then click OK.
    Congratulations!  You have just created your first working Visual C++ program.  To build and run it, press Control-F5.  Click OK to exit from the program.

3. Go to "Resource View" by clicking on the middle tab in the left-hand pane of the display.  (If you ever lose this, pressing Alt-0 will bring it back).  Click on the + next to Dialog, then double-click on IDD_PERMUTE_DIALOG.  Click on the text that starts "TODO:...", then press the Delete key to get rid of it.  Do the same for the Cancel button.  With the OK button highlighted, press the Enter key.  Under the General tab, edit the caption to change it to "Done."  Click the little "x" to finish, then drag the button down to the lower right-hand corner of the dialog.

4. Now we will change some properties of the entire dialog.  Click anywhere in empty space on the dialog, then press Enter.
    Under the General tab, click Font...and select Courier New, Size 10.
    Under the Styles tab, check Minimize box.
    Click the little x to close Dialog Properties.

5. From the toolbar of controls, select a group box (the one with XYZ at the top) and drag it to the upper left of the dialog.  Grab the lower-right corner and expand the group box until it is about 2 inches wide and 3 inches high.  Press Enter and under the General tab edit the caption to read "Permutations."  Drag a static text control (with italic Aa ) to the upper left of the group box and change the caption to read "a."  To the right of this label, drag an edit control (with ab|) and edit its ID to be IDC_PERMA.  In a similar manner, directly under these two controls, place a text label with caption "b" and an edit control IDC_PERMB.  Then do two more: label "a*b" with ID IDC_PERMAB and label "b*a" with ID IDC_PERMBA.  For these two, under the Styles tab check Read-only.

6. To the bottom of the group box, drag a pushbutton.  Make it about 2 inches wide.  Press Enter to edit its properties.  Under the General tab, change its ID to IDC_CALCULATE and its caption to "Calculate,"  

7. In the top center of the dialog, drag a group box. Make it about 2 inches wide and 2 inches high.  Change its caption to "Powers of a". Inside this group box drag a list box (this has an icon with horizontal lines on the left and scroll-bar arrows on the right.  Press Enter to edit the properties.  Under General, change the caption to IDC_POWERSOFA, and under Styles, uncheck "Sort" and "No integral height."

8. In a similar manner, under this group box, place a group box with caption "Powers of b" containing a list box  IDC_POWERSOFA. Then at the top right corner of the dialog place a group box with caption "Powers of a*b" containing a list box  IDC_POWERSOFAB, and under this place a group box with caption "Powers of b*a" containing a list box  IDC_POWERSOFBA. Be sure to uncheck "Sort" for all the list boxes.
Press Control-F5 to build and run the project.  Check that the minimize button works.  If you don't like the layout, go back to the dialog editor to resize and move controls.

9. Now we can move to Stage 2.  Click the left tab in the right pane  to switch to Class View.  Click the + next to Permute classes, then the + next to CPermuteDlg.  This is the C++ class in which all the interesting  action of our program occurs.  You can see that it already has a few  functions written by the AppWizard.  The only ones of interest are the  constructor CPermuteDlg, which is called when an object of the class is created  and is a good place to initialize variables, and OnInitDialog, which is called  when the dialog is first displayed and is a good place to do any initialization  that involves graphical objects.  There is also one variable, m_hIcon.   We are about to add more functions and variables to the class.

Press Control-W to bring up ClassWizard.  Under the Message Maps and Member Variables tabs you will see a list of the Control IDs that you have assigned to controls on the dialog.  If any of these are still of the form IDC_EDIT2 or IDC_BUTTON1, press Cancel and go back to Resource View to edit the dialog and fix them.
Now we will add a "handler function" for the button.  Under the Message Maps tab, click on IDC_CALCULATE, then on BN_CLICKED, then on AddFunction, then on OK.    Exit ClassWizard by clicking on OK (so your change will not be lost!) and go back to Class View.  You will see a new function.  Double-click on it, and you will see that you still need to "add your control notification handler code."  Right-click on it, select "go to declaration," and you will see that the function now appears in a special section of the class CPermuteDialog.

10.  Press Control-W to go back to ClassWizard, and click the MemberVariables tab.  Click IDC_PERMA, then "AddVariable..."
Change the member variable name to m_permA, leaving its category as Value and its type as CString.  In a similar manner add three more variables:
ID IDC_PERMB,    name m_permB,   category Value, type CString
ID IDC_PERMAB,    name m_permAB,  category Value, type CString
ID IDC_PERMBA,    name m_permBA,  category Value,   type CString
Exit ClassWizard by clicking OK, and again look at the class CPermuteDlg.  You should see your four new variables.  Double-click on the constructor CPermuteDlg, and observe that Class Wizard has initialized them all to the null string ("").  If this is inappropriate, we can change it.  For m_permA and m_permB, a better initial value is "I", which represents the identity permutation.

11. To complete Stage 2, go back to ClassWizard.  Under Member Variables. associate with IDC_POWERSOFA a member variable m_listPowersOfA.  Change the category to Control, and observe that the variable type becomes CListBox.  Unlike the previous "category Value" variables, which represent the contents of controls, this variable represents the control itself.
Do the same for the other three list boxes:
ID IDC_POWERSOFB, name m_listPowersOfB, category Control, type CListBox
ID IDC_POWERSOFAB, name m_listPowersOfAB, category Control, type CListBox
ID IDC_POWERSOFBA, name m_listPowersOfBA, category Control, type CListBox
Exit ClassWizard by clicking OK.

12. Now we are ready to proceed to Stage 3.   In ClassView, right-click  on the class CPermuteDlg and click on Add Member Function.  The type  is "CString," which means that the function returns a string value.  The declaration  is Multiply(CString secondP, CString firstP).  This function will calculate  the result of carrying out two successive permutations, and you will have  to write it yourself.  But to check that everything is mechanically sound, type in the following C++ code, which works correctly for permutations of two elements so that your function looks like this:

CString CPermuteDlg::Multiply(CString secondP, CString firstP)
{
   if (firstP == "I")
        return secondP;
   if (secondP == "I")
        return firstP;
   if (firstP == "(12)" && secondP == "(12)")

        return "I";
   ASSERT(FALSE);
   return "I";
}

ASSERT(FALSE) causes an error.  It is a good statement to place before any line in your code that should never be reached if the input is correct.
Be sure that you have typed "==" (double equals - test for equality) rather than "=" (assignment).

13.  Again click on Add Member Function to create a function that will display powers of a permutation.  This time the type is "void," since the function returns no value, and the declaration is DisplayPowers(CString perm, CListBox& listBox).  This function will display the powers of  the permutation "perm" in the specified list box, stopping once it finds a power that equals the identity permutation.  Here is a version of this function that is correct for permutations of two elements:

void CPermuteDlg::DisplayPowers(CString perm, CListBox& listBox)
{
      listBox.ResetContent();    //clear out the box
      if (perm == "I")
            listBox.AddString("I");
      else if (perm == "(12)") {
            listBox.AddString("(12)");
            listBox.AddString("I");
      }
      else
            ASSERT(FALSE);
}

Of course, you will need to replace this with a function that calls the function Multiply() inside a while loop.

14. Now, in ClassView, double click on the function OnCalculate() that will be called when you press the Calculate button.  This should read the permuations a nd b, multiply them in both orders, display the results, and display all the powers.  Here is a version of the function that will work, and you may not even need to change it in your final version.

void CPermuteDlg::OnCalculate()
{
     UpdateData(TRUE);  //read from the edit controls to the member variables;
     m_permAB = Multiply(m_permA, m_permB); 
     m_permBA = Multiply(m_permB, m_permA);
     UpdateData(FALSE);  //write from the member variables to the edit controls;
     DisplayPowers(m_permA, m_listPowersOfA);
     DisplayPowers(m_permB, m_listPowersOfB);
     DisplayPowers(m_permAB, m_listPowersOfAB);
     DisplayPowers(m_permBA, m_listPowersOfBA);
}

Press Ctrl-F5 to build and run your program.  If you get build errors, press F4 to see them, and fix them.  Once the program runs, it should do the right thing if you type in "I" or "(12)" for permutations a and b.  It is your job to make it work for any permutations of the symbols "1" through "9"

Grading guidelines:

7 points if the program works correctly as specified above.
1 point extra if you add calculation and display of the inverses of a and b.
1 point extra if you add calculate and display of b conjugated by a: a*b*a -1
1 point extra if you add error checking that reports, in an edit control IDC_ERROR, when the permutation a or b was not syntactically valid.  It would be nice to allow the user to put spaces in the input, so that "(1 2 3)   (45)" is treated the same as "(123)(45)",but this is not a requirement.
1 or 2 points off for minor bugs.
Up to 4 points off for major bugs (e.g. powers work, but products are wrong, or permutations with more than one cycle come out wrong)
We will grade your executable program, not your source code.  Good formatting, meaningful variable names, comments, and other elements of good programming style are left to your conscience. 

The algorithm for Multiply() will be presented in class, but here is a summary of it.
Start with the integers 1 through 9 in order in an array: i.e. u[1] = 1. u[2] = 2. Create a second array v that is the same as u.

Read through the first permutation, cycle by cycle, and change array v to show the effect of the permutation.  For example, if the permutation is (123),
then v[1] = u[2], v[2] = u[3], and v[3] = u[1].
Create an array w that is the same as v.
Read through the second permutation, cycle by cycle, and change array w to show the effect of the permutation.  For example, if the permutation is (123),
then w[1] = v[2], w[2] = v[3], and w[3] = v[1].
In array w, change every entry that was not modified to zero.
Find the first nonzero element of w. This gives you the start of a cycle.  For example, if w[2] = 5, w[5] = 3, and w[3] = 2, you have found the cycle (253).
Set all the elements in the cycle just found to zero, and repeat the preceding step to find more cycles.  If there is no first nonzero element, you are done.

There is a very slight gain in efficiency if you first find the largest number that appears in permutation a or b and use that, instead of 9, as the highest index in your arrays. You would have to run the programs many thousands of times to break even on the extra programming effort.  I wouldn't bother.

If you have a variable
CString s;
its nth character (starting at index 0) is s[n]
you can append a character like '(' with the statement
s += '('