// The writeData function converts x to a string so you can write
// it to a text (.txt) file

void writeData(int x) {
 
  // write value to file asa string
   dbWriteString(OUTPUT_FILE, dbStr(x));
}

Physics 5  DarkGDK002: Guy Sequences and Beyond   

In this project you will develop a program to help analyze Guy sequences.  Guy sequences are a variation on Collatz sequences, as described in the chapter,  Historic Conjectures: More Sequence Mysteries in the book, Tracking the Automatic Ant, and Other Mathematical Explorations, by David Gale.  A Guy sequence here is defined as a sequence which uses the iterative function

                 

Where Guy[0] could be any positive integer.    In his book, Gale notes that (1) is a 1-cylce,
(2, 3) is a 2-cyle, (4,6,9,7,5) is a 5-cycle and (44, 66, 99, 74, 111, 83, 62, 93, 70, 105, 75, 59) is a 12-cycle.  Gale notes that the smallest positive integer not in any of these cycles is 8 and that the sequence including 8 is not known to cycle, though it gets tantalizingly close.

In class we developed some code to visualize this sequence as a line graph.  That code has been modified below so that the type of elements in the sequence are float types instead of int types.  This allows the code to easily scale the values plotted in the window to fit within the height of the window, which is computed as a float using the declaration/initialization:

float height = dbScreenHeight();

Another modification of the code developed in class is that the bool variable, keepGoing is introduced to imbed the body of the algorithm in a while loop the user is allowed to repeat or exit by setting its value to either 1 or 0, respectively.  At the end of this while loop the Dark GDK functions

dbClear(0,0,0);

dbSetCursor(0,0);

 

are invoked to clear the screen to black and reset the dbPrint() cursor to the upper left corner.

 

Also the for loop used to draw the sequence of line segment in the plot:

 

for(int i = 0; i < 64; i++)
      dbLine(10.0*i,height - Guy[i]*height/MaxGuy,
             10.0*(i+1),height - Guy[i+1]*height/MaxGuy);

 

was  modified by the scaling factor,  height/MaxGuy, which is why we want to use  the float type for these variables: if they were integers then we’d have unwanted truncation errors. The trouble with this is that the modulus operator (%) doesn’t take a float type operand.  Thus in the nextGuy function below, we have

if((int)x%2 == 0) return(3*x/2);

which casts x as an integer before taking the remainder modulo 2.  It’s also possible to cast the int types as float in the dbLine() function. Think about the tradeoffs in memory and performance when doing casts.




Here’s the modified code from lecture:

// GH_DarkGDK0002 - Geoff Hagopian  2/22/11 - This is program designed to

// visualize Guy sequences.

 

#include "DarkGDK.h"

 

float nextGuy(float);  // function prototype

 

void DarkGDK() {

      float Guy[64], MaxGuy=0;  //The Guy sequence and its max

      float height = dbScreenHeight();  //See page 108 of GGC++

      bool keepGoing = 1;

      while(keepGoing) {

            MaxGuy=0;

            dbPrint("Enter an intitial value for the Guy sequence: ");

            Guy[0] = atoi(dbInput());     // get the seed after prompt

            dbPrint("You entered "); dbPrint(dbStr(Guy[0]));

            for(int i = 1; i < 64; i++)     // build the sequnce

                  Guy[i] = nextGuy(Guy[i-1]);

            for(int i = 0; i < 64; i++)    // find the max value of Guy

                  if(Guy[i] > MaxGuy) MaxGuy = Guy[i];

            dbPrint("MaxGuy = ");

            dbPrint(dbStr(MaxGuy));

            dbPrint("The last Guy value is ");

            dbPrint(dbStr(Guy[63]));

            for(int i = 0; i < 64; i++)   // draw the graph
                dbLine(10.0*i,height - Guy[i]*height/MaxGuy,
                       10.0*(i+1),height - Guy[i+1]*height/MaxGuy);

            dbPrint("More? (0 to quit, 1 to repeat)");

            keepGoing = atoi(dbInput());

            //dbWaitKey();

            dbClear(0,0,0);

            dbSetCursor(0,0);

      }

}

 

float nextGuy(float x) {

      if((int)x%2 == 0) return(3*x/2);

      else if((int)x%4 == 1) return((3*x+1)/4);

      else return((3*x-1)/4);

}

 

With the input 44, this produces this picture:
P5_DGDK002_Guy01.jpg

Your assignment is to modify this code to experiment with a sequence that branches up or down depending on the remainder after division by another number greater than 4, say 5 or more.  Design your iterative function like so:

 

So that the probability of increasing by 80% in the first case is balanced by the probability of decreasing by approximately 20% in the other 4 cases.  Write a paragraph or two describing what you find.  Are there any cycles? 


Research until you find something you think is interesting and write about it.  For instance, by rejiggering the weights on these conditionals I came up with the following output:

cycle'

 

Write code that checks for a cycle in your data.

  Submit your .cpp file with the name <your initials>_GDK002.cpp  and include your discussion as a separate file named <your initials>_GDK002essay.txt or <your initials>_GDK002essay.docx, if it’s a MSWord file.

Afterthought #1: Rather than writing numbers on the graphics screen in Dark GDK, we could write the numbers to a file, and so not clutter of the graphic with the writing.  The method is described in section 11.2 of GGC++.   

You'll need create a file, name it and open it for output. The OUTPUT_FILE identifier is actually a const int which should be declared as a global varialbe.

// The openFile function gets a file name from the user and
// opens that file for output. The file is not opened if it
// already exists.

void openFile() {

 
  // character array to hold the file name
   char filename[STRING_SIZE];
   // get afile name from the user.
   dbPrint("Enter the name of the file to save this data:");
   strcpy( filename, dbInput()) ;

   // If the file already exists, display an error message,
   // otherwise, open the file.
   if ( dbFileExist(filename) ) {
      dbPrint("Error: That file already exists.");
   }
   else {
      dbOpenToWrite( OUTPUT_FILE, filename );
   }
}

Now a function to write the data to the file. This one is very simple, but you can imagine it being more complex.

// writeData is just a direct call to the Dark GDK library function
// dbWriteString which converts x to a string with dbStr so that
// it can be written to a text (.txt) file.

void writeData(int x) {
 
 dbWriteString( OUTPUT_FILE, dbStr)) // if the file is open
}

Include code in the main DarkGDK() function for printing the sequence to the file, such as the following loop:

   // dbFileOpen is a Dark GDK library function and writeData is defined
 
  // below - calls the Dark GSK

 
  for(int i = 0; i < aSize; i++)
 
     if (dbFileOpen( OUTPUT_FILE )) // if the file is open
 
        writeData(x[i]));

Then the use will be prompted openFile to enter a name such as "seqdat.txt" which will be saved to the same directory your .cpp file is in.