/****** Problem 2--Cycles, Period. ************************************ I thought this was the hardest problem of the bunch. Others may disagree with me. What made this problem hard was seeing all the checks that had to be made. In particular, the sample data given in the problem description did not test all of these cases. First of all, there is no limit given on the number of observations, so this had to be handled dynamically; I used a linked list. Then, when all the data had been read in (and there is no guarantee that this data will be sorted in any particular order), possible cycle lengths are found by seeing which observations recorded the same value. Since all values are unique within a period, the difference in observation times of the same value must be a multiple of the period. Thus, to find the greatest possible period, you need to compute the greatest common factor of all of these potential periods. Finally, it is very possible that there is no period at all in the data. Once you figure out what the period could be, you have to go through and make sure that all of the data does indeed abide by this period; if two observation times differ by a multiple of the cycle length, yet the values observed are different, there is no observable cycle, and this should be reported. Additionally, if there is no repetition in the data, there is also no observable cycle. The test data supplied gives an example of the latter problem, but not one of the former. **********************************************************************/ #include #include using namespace std; class pairlist; class pairlist { // linked list for pairs public: int t, v; pairlist *next; pairlist (int t, int v); ~pairlist (); }; int main (int argc, char **argv); pairlist * readlist (); int GCF (int a, int b); int maxcyclelength (pairlist *p); int verify (pairlist *p, int len); int cycle (pairlist *p); void freelist (pairlist *p); ifstream in ("prob2.in"); ofstream out ("prob2.out"); /**** pairlist constructor ********************************************/ pairlist::pairlist (int t, int v) { this->t = t; this->v = v; next = NULL; } /**** pairlist destructor *********************************************/ pairlist::~pairlist () { if (next != NULL) delete next; } /****** main ********************************************************** This program repeatedly reads in a list of observation times and values and determines if a cycle is present. If there is one, it prints the length of the greatest possible cycle. If not, it prints a message to that effect. The program ends when an empty list is provided. **********************************************************************/ int main (int argc, char **argv) { int c; // computed cycle length pairlist *p; // the list of observations for (int cs=0;(p=readlist())!=NULL;) { // read in a list // done if an empty list is read out << "Case " << ++cs << ": "; if ((c = cycle (p))>0) // print computed cycle time out << "cycle time = " << c << "." << endl; else out << "no cycle time can be determined." << endl; delete (p); // free up our linked list } return EXIT_SUCCESS; } /***** readlist ******************************************************* readlist reads in a linked list of ordered pairs. The routine is standard. Note that we are not guaranteed any specific order of the pairs in the listing, thus it won't make any difference that they appear in the linked list in the opposite order of entry. **********************************************************************/ pairlist * readlist () { pairlist *p, // The list of pairs (to be returned) *q; // temporary int t, v; // The input values to be added to the list for (p=NULL;;) { in >> t >> v; if (t==0 && v==0) break; // if both are 0, then the list is done q = new pairlist (t,v); q->next = p; p = q; } return p; } /****** GCF *********************************************************** GCF compute the greatest common factor of two integers. The algorithm below is Euclid's algorithm, the easiest method of computing it. **********************************************************************/ int GCF (int a, int b) { return b==0 ? a : GCF (b, a%b); } /********* maxcyclelength ********************************************* maxcyclelength accepts a list of pairs and returns the GCF of all potential cycles in the list. If there is no repetition of data in the list, this function returns 0. This function simply uses nested loops to try every pair of values in the list to see if there is a potential cycle. **********************************************************************/ int maxcyclelength (pairlist *p) { int len=0; // the cycle length (to be returned) for (pairlist *q=p;q!=NULL;q=q->next) // q loops from p to the end for (pairlist *r=q->next;r!=NULL;r=r->next) // r loops from one past q to the end if (q->v == r->v) // compute the GCF of this cycle with all len = GCF (len,abs(q->t-r->t)); // previously found cycles. return len; } /******* verify ******************************************************* verify accepts a list of pairs and a potential cycle length and determines whether that cycle length could possibly work. What it does is check whether there are any pairs that are a full number of cycles apart but still have a different value. verify returns true if the cycle length is valid, false otherwise. This function simply uses nested loops to check whether all pairs of observations are consistent with this cycle length. **********************************************************************/ int verify (pairlist *p, int len) { int b=1; // boolean value (to be returned) for (pairlist *q=p;q!=NULL && b;q=q->next) // q goes from p to the end, but the loop will abort // early if b ever becomes 0 for (pairlist *r=q->next;r!=NULL && b;r=r->next) // r goes from q to the end, but the loop will abort // early if b ever becomes 0 b = abs(q->t-r->t)%len != 0 || q->v == r->v; // check for validity of the pairs at q and r return b; } /******* cycle ******************************************************** cycle computes the maximum cycle length supported by input data in p. if no cycle is supported, this function returns 0. **********************************************************************/ int cycle (pairlist *p) { int c = maxcyclelength (p); // the max cycle length if (c > 0 && !verify (p,c)) // if this length is not borne out return 0; // by the data, we must assume there return c; // is no cycle. }