Automated Grading Log for CS113 -- HW6 userid: kcochran Name: Cochran, Keith Log created: Mon Nov 18 21:00:25 EST 1996 SUBMISSIONS =========== kcochran Submitted hw6-queue.h at Wed Nov 13 23:23:28 1996 kcochran Submitted hw6-queue.c at Wed Nov 13 23:23:27 1996 kcochran Submitted hw6-types.h at Wed Nov 13 23:23:30 1996 kcochran Submitted hw6-toll.c at Wed Nov 13 23:23:31 1996 COMPILATION =========== gccx -Wall -c hw6-toll.c gccx -Wall -c hw6-queue.c gccx -Wall -o hw6-toll hw6-toll.o hw6-queue.o \mv hw6-types.h hw6-types.H \cp ../qtest.c ./ \cp ../hw6-types.h ./ gccx -Wall -c hw6-queue.c gccx -Wall -c qtest.c gccx -Wall -o qtest qtest.o hw6-queue.o \mv hw6-types.H hw6-types.h EXECUTION TESTS ========= ===== ============================================================ qtest After initializing the Queue has 6 elements: >Q Test< After removing 'Q' the Queue has 5 elements: > Test< After removing ' ' the Queue has 4 elements: >Test< After removing 'T' the Queue has 3 elements: >est< After removing 'e' the Queue has 2 elements: >st< After removing 's' the Queue has 1 elements: >t< After removing 't' the Queue has 0 elements: >< ============================================================ hw6-toll /home/course/cs113/GradesF96/HW6/input/hw6-data.1 Number Average Long Long Number Of Of Average In Wait Wait Customers Queues Wait Queues Length Time At End ------ ------- ------- ------ ---- --------- 1 21.44 4.85 35 13 7 2 9.33 3.69 22 10 4 3 6.00 3.31 14 5 3 4 5.22 3.08 10 3 3 5 5.22 3.08 10 3 3 6 5.22 3.08 10 3 3 ============================================================ hw6-toll /home/course/cs113/GradesF96/HW6/input/hw6-data.2 Number Average Long Long Number Of Of Average In Wait Wait Customers Queues Wait Queues Length Time At End ------ ------- ------- ------ ---- --------- 1 33.00 7.00 61 15 13 2 14.80 6.13 26 15 11 3 9.00 5.40 15 11 9 4 6.40 4.80 10 6 7 5 5.00 4.33 5 1 5 6 5.00 4.33 5 1 5 ============================================================ hw6-toll /home/course/cs113/GradesF96/HW6/input/hw6-data.3 Number Average Long Long Number Of Of Average In Wait Wait Customers Queues Wait Queues Length Time At End ------ ------- ------- ------ ---- --------- 1 188.19 11.45 386 87 25 2 76.32 9.01 153 87 20 3 40.58 7.15 87 87 16 4 24.23 5.66 45 87 12 5 19.58 5.20 33 41 9 6 16.35 4.49 35 84 8 Data files: ========== ==> /home/course/cs113/GradesF96/HW6/input/hw6-data.1 <== 1, 5; 2, 3; 3, 10; 3, 2; 5, 4; 5, 10; 8, 2; 10, 6; 13, 5; ==> /home/course/cs113/GradesF96/HW6/input/hw6-data.2 <== 1, 5; 2, 5; 3, 5; 4, 5; 5, 5; 6, 5; 7, 5; 8, 5; 9, 5; 10, 5; 11, 5; 12, 5; 13, 5; 14, 5; 15, 5; ==> /home/course/cs113/GradesF96/HW6/input/hw6-data.3 <== 3, 11; 4, 15; 9, 11; 13, 12; 15, 11; 15, 14; 16, 14; 21, 15; 25, 17; 29, 18; 33, 11; 36, 13; 38, 20; 41, 14; 44, 18; 49, 19; 54, 17; 58, 16; 60, 13; 61, 19; 63, 15; 68, 11; 69, 20; 73, 14; 77, 18; 82, 10; 83, 18; 84, 16; 84, 20; 85, 10; 87, 20; ============================================================ SOURCE FILES ====== ===== /* Header File * --------------------------------------------------------------------------- * File: hw6-queue.h * * This is the interface for a general queue. It contains the queue type as * as well as some general functions to work with the queue. */ #ifndef _queue_h #define _queue_h /* * Types: queueElemenT element; * queueADT queue; * * Functions: queue = NewQueue(); * FreeQueue(queue); * QueueEnter(queue, element); * element = QueueDelete(queue); * QueueIsEmpty(queue); * n = QueueLength(queue); * element = QueuePeek(queue); */ /* Type: queueElementT * ------------------- * This is the type of the objects entered in the queue. * Edit queue.h to define queueElementT to be type * of things to be placed in queue. */ #include "genlib.h" /* Need bool typedef. */ #include "hw6-types.h" /* Need queueElementT typedef. */ /* Type: queueADT * -------------- * The actual implementation of a queue is completely * hidden. Client will work with queueADT which is a * pointer to underlying queueCDT. * * NOTE: need word struct below so that the compiler * knows at least that a queueCDT will be some sort * of struct. */ typedef struct queueCDT *queueADT; /* Function: NewQueue * Usage: queue = NewQueue(); * ------------------------- * A new empty queue is allocated, created and returned. */ queueADT NewQueue(void); /* Function: FreeQueue * Usage: FreeQueue(queue); * ----------------------- * This function frees all memory associated with * the queue. "queue" may not be used again unless * queue = NewQueue() is called first. */ void FreeQueue(queueADT queue); /* Functions: QueueEnter, QueueDelete * Usage: QueueEnter(queue, element); * element = QueueDelete(queue); * ----------------------------------- * These are the fundamental queue operations that * enter elements in and delete elements from the queue. * A call to QueueDelete on an empty queue is an error. * Make use of QueueIsEmpty() (see below) to avoid this * error. */ void QueueEnter(queueADT queue, queueElementT element); queueElementT QueueDelete(queueADT queue); /* Functions: QueueIsEmpty * Usage: if (QueueIsEmpty(queue)) ... * ----------------------------------- * This returns TRUE if the queue is empty. */ bool QueueIsEmpty(queueADT queue); /* Function: QueueLength * Usage: n = QueueLength(queue); * ----------------------------- * This returns the number of elements currently in * the queue. */ int QueueLength(queueADT queue); /* Function: QueuePeek * Usage: element = QueuePeek(queue, n); * ------------------------------------ * This function returns the nth element in the queue. The first is n = 0. * Calling this function on an enpty queue is an error. Also if n is outside * the queue this also an error. */ queueElementT QueuePeek(queueADT queue, int nthElement); #endif /* ------------< end-of-file "hw6-queue.h" >------------ */ /* Implemetation File * --------------------------------------------------------------------------- * File: hw6-queue.c * * Created By: Keith Cochran * ID#: 209-62-9355 * Course: CS113 * Date: 11/12/96 * * This is a linked-list implementation of a queue. This library uses dynamic * memory allocation to expand the queue. */ #include #include #include "genlib.h" #include "simpio.h" #include "hw6-queue.h" /* Constants * --------- * ERROR_ These are for returning error * conditions from queue functions. */ #define ERROR_QUEUE 2 #define ERROR_MEMORY 3 /* Prototype declaration for function used only by implemetation fil */ static void RemoveAllNodes(queueADT queue); /****************************************************************************/ /* QueueNodeT gives the implementation of a node in * the linked list used to implement the queue. It * holds an element and a pointer to the next node * in the linked list. * * NOTE that this structure is given a type name * via typedef and is why we will be able to use * it by just queueNodeT. */ typedef struct queueNodeT{ queueElementT element; struct queueNodeT *next; }queueNodeT; /***************************************************************************/ /* Struct queueCDT gives the implementation of a queue. * It holds the information that we need for each queue. * It holds the pointer to the front and the rear of the queue. It * also holds the pointer to the last node peeked at by the function * QueuePeek() as well as the last element peeked at. Also it holds * the number of nodes in the queue. */ struct queueCDT{ queueNodeT *front, *rear, *lastPeekPtr; int count, lastPeek; }; /*****************************************************************************/ /* This function creates a new queue by allocating memory space for the * queueCDT and intializing the counters and pointers. */ queueADT NewQueue(void){ queueADT queue; queue = malloc(sizeof(struct queueCDT)); /* Allocate memory for queue. */ if (queue == NULL){ fprintf(stderr, "Insufficient Memory for new Queue\n"); exit(ERROR_MEMORY); } queue->count = 0; /* Initialization. */ queue->lastPeek = 0; queue->front = queue->rear = queue->lastPeekPtr = NULL; return queue; } /****************************************************************************/ /* This function frees the queue from memory by deleting each node in the * queue and then freeing the queueCDT. */ void FreeQueue(queueADT queue){ /* Wrapper. */ RemoveAllNodes(queue); /* Removes all the nodes from the queue. */ free(queue); /* Frees queueCDT from memeory. */ return; } /****************************************************************************/ /* This function removes each node from the queue until all the nodes are * free from memory. It does this through a recursion call of the function. */ static void RemoveAllNodes(queueADT queue){ if (QueueIsEmpty(queue)){/* Basis of recursion - If queue is empty, remove */ return; /* queue from memory. */ } QueueDelete(queue); /* Delete each node of the queue until there are */ RemoveAllNodes(queue); /* zero nodes. */ return; } /***************************************************************************/ /* This function enters an element in the queue by adding a node at the end * of the queue. After the node is entered it adjust the front and rear * pointers. */ void QueueEnter(queueADT queue, queueElementT element){ queueNodeT *newNodePtr; /* Temparary pointer to the node. */ /* Allocate space for a node in the linked list. */ newNodePtr = malloc(sizeof(queueNodeT)); if (newNodePtr == NULL){ fprintf(stderr, "Insufficient Memory for new Queue element\n"); exit(ERROR_MEMORY); } /* Place information in the node. */ newNodePtr->element = element; newNodePtr->next = NULL; /* Link the element into the right place in * the linked list. At the end the end of the queue. */ if (queue->count == 0){ /* Queue is empty */ queue->front = queue->rear = newNodePtr; }else{ /* Queue has one or more nodes. */ queue->rear->next = newNodePtr; queue->rear = newNodePtr; } queue->count++; return; } /*****************************************************************************/ /* This function deletes the first node from the queue and returns the element * in that node. It will also adjust the front, rear, and lastPeek pointers. */ queueElementT QueueDelete(queueADT queue){ queueNodeT *newNodePtr; /* Temparary pointer to front node. */ queueElementT element; if (QueueIsEmpty (queue)){ /* Returns an error if queue is empty. */ fprintf(stderr, "Error - Cannot call QueueDelete on an empty queue.\n"); exit(ERROR_QUEUE); }else{ newNodePtr = queue->front; /* Deletes first node from queue and */ element = newNodePtr->element; /* deallocates it from memory. */ queue->front = newNodePtr->next; queue->count--; if (queue->count == 0){ queue->front = queue->rear = NULL; } if (queue->lastPeek == 0){ queue->lastPeekPtr = queue->front; }else{ /* lastPeek > 0. */ queue->lastPeek--; } free(newNodePtr); /* Free node from memory. */ } return element; } /***************************************************************************/ /* This function returns TRUE if the queue passed as an argument is empty. */ bool QueueIsEmpty(queueADT queue){ return queue->count < 1; } /***************************************************************************/ /* This function returns an integer that qives the number of nodes or length * of the queue. */ int QueueLength(queueADT queue){ return queue->count; } /***************************************************************************/ /* This function returns the nth element in the queue where n = 0 for the * first element. This function updates the pointer to the node last * peeked at which is stored in queueCDT. It also stores the last nth element * in queueCDT. Since a loop inside QueuePeek is used to find the nth * element starting from the last node/element the function peeked at, * calling the function QueuePeek n number of times for consecutive nth * elements will be done in linear time O(n). Each call to QueuePeek is O(1). */ queueElementT QueuePeek(queueADT queue, int nthElement){ int i; /* For loop variable. */ /* Returns an error if queue is empty. */ if (QueueIsEmpty(queue) || nthElement >= QueueLength(queue) || nthElement<0){ fprintf(stderr,"Error - Called QueuePeek on an empty queue or the\n" "element you are searching for is outside the queue's\n" "limits.\n"); exit(ERROR_QUEUE); } if (nthElement >= queue->lastPeek){ if (queue->lastPeek == 0){ queue->lastPeekPtr = queue->front; } for(i = queue->lastPeek; i < nthElement; i++){ /* This will be O(1) if */ queue->lastPeekPtr = queue->lastPeekPtr->next;/* the function is called*/ queue->lastPeek++; /* for the nth+1 element */ } /* where it last peeked */ /* at the nth element. */ }else{ /* nthElement < queue->lastPeek. */ queue->lastPeek = 0; queue->lastPeekPtr = queue->front; for(i = queue->lastPeek; i < nthElement; i++){ queue->lastPeekPtr = queue->lastPeekPtr->next; queue->lastPeek++; } } return queue->lastPeekPtr->element; } /* ------------< end-of-file "hw6-queue.c" >------------ */ /* File: hw6-types.h * --------------------------------------------------------------------------- * * Created by: Keith Cochran * ID#: 209-62-9355 * Course: CS113 * Date: 11/12/96 * * This file exist for the client to change the element type stored in * in the queue without having to edit hw6-queue.h. */ #ifndef _queueTypes_h #define _queueTypes_h typedef struct queueElement{ int arrivalTime; int serviceTime; }queueElementT; #endif /* --------------------< end_of_file "hw6-types.h" >----------------- */ /* File: hw6-toll.c * --------------------------------------------------------------------------- * Created by: Keith Cochran * ID#: 209-62-9355 * Course: CS113 * Date: 11/12/96 * * This program runs a simulation of customers waiting in queues. The * program reads data from a file which contains information on each customer * such as their arrival time at the queues and the service time when * the customer reaches the beginning of one of the queues. The simulation * reads the data from all the customers in a file and records informaton * such as the number of queues and information on how those queues handle the * customers. The program calculates the average wait of the customers, * average number of customers waiting in the queues, longest wait by a * customer and when that customer arrived at a queue, and the number of * customers in queues when the last customer enters a queue. */ #include #include #include "genlib.h" #include "simpio.h" #include "hw6-queue.h" #define MAX_NUM_QUEUES 6 #define ERROR 1 /* Prototype declaration. */ void Simulate(string dataFile, int numOfQueues); int main(int argc, string argv[]){ int numOfQueues; if (argc < 2){ fprintf(stderr,"Missing argument(s).\n"); /* An error is returned if */ exit(ERROR); /* there is more than one */ } /* data file to simulate. */ if (argc > 2){ fprintf(stderr,"Too many arguments.\n"); exit(ERROR); } /* Print header for table. */ printf("\n\n\n"); printf("%-18s %-9s %-8s %-6s %-9s\n", "Number", "Average", "Long", "Long", "Number Of"); printf("%-8s %-9s %-9s %-8s %-6s %-9s\n", "Of", "Average", "In", "Wait", "Wait", "Customers"); printf("%-8s %-9s %-9s %-8s %-6s %-9s\n", "Queues", "Wait", "Queues", "Length", "Time", "At End"); printf("%-8s %-9s %-9s %-8s %-6s %-9s\n", "------", "-------", "-------", "------", "----", "---------"); printf("\n"); /* Do a simulation for one queue up to the maximum number of queues. */ for(numOfQueues = 1; numOfQueues <= MAX_NUM_QUEUES; numOfQueues++){ Simulate(argv[1], numOfQueues); } printf ("\n\n\n"); exit (0); } /****************************************************************************/ /* This function does a simulation for a specified number of queues from * a particular data file containing customers. Each customer contains * information on their arrival time to the queues and their service time * when at the beginning of a queue. Each customer is added at the end * of the shortest queue or the first of equally short queues. The customers * at the beginning of the queues are served first. After a customer has * been served they are removed from the queue. The simulation runs until all * customers in the data file have entered the queues. The function calculates * the average wait of the customers, the average number of customers in the * queues up to the time when the last customer arrives, the logest wait by * a customer and when that customer arrived at the queues, and the number * of customers waiting in queues at the time when the last customer arrives. */ void Simulate(string dataFile, int numOfQueues){ int nscan, /* Number of data for each customer. */ n, i, /* Array index variable - loop variable. */ lengthQueue, /* Queue with shortest length. */ lastDelTime[MAX_NUM_QUEUES], /* Last time a customer left the queue. */ time = 1, lastTime = 0, /* Time last customer arrived. */ arrTime = 0, /* Customer arrival time. */ serTime = 0, /* Customer service time. */ sumWaitTime = 0, /* Sum of the wait for all the customers. */ numElemQueues = 0, /* Number of customers (except lastTime). */ numElemEnd = 0, /* Number of customers at lastTime. */ longWaitLength = 0, /* Longest wait. */ longWaitArrival = 0, /* Arrival time for the longest wait. */ totalElemEntered = 0; /* Total number of customers. */ double aveInQueues = 0, /* Average number in queues. */ aveWait = 0; /* Average wait in queues. */ queueElementT customer; queueADT queue[MAX_NUM_QUEUES]; FILE *sourceFile; sourceFile = fopen(dataFile, "r"); /* Open customer data file. */ if (sourceFile == NULL){ fprintf (stderr,"Unable to open file: %s.\n", dataFile); exit(ERROR); } for(i = 0; i < numOfQueues; i++){ /* Create empty queues. */ queue[i] = NewQueue(); lastDelTime[i] = 0; } while(TRUE){ nscan = fscanf(sourceFile, "%d, %d; ",&arrTime, &serTime); if (nscan == EOF){break;} if (nscan != 2){ /* Get customer from file. */ fprintf(stderr,"Bad imput file.\n"); exit(ERROR); } while(time != arrTime){ /* Service customers in queues. */ for(i = 0; i < numOfQueues; i++){ if (!QueueIsEmpty(queue[i])){ customer = QueuePeek(queue[i], 0); /* Look at first customer. */ if (time == lastDelTime[i] + customer.serviceTime){ /* Remove */ sumWaitTime += (time - customer.arrivalTime); /* customer */ /* and */ if (longWaitLength < time - customer.arrivalTime){ /* determine */ longWaitLength = time - customer.arrivalTime; /* their wait */ longWaitArrival = customer.arrivalTime; /* time. */ } QueueDelete(queue[i]); lastDelTime[i] = time; /* Set last delete time to time. */ } } numElemQueues += QueueLength(queue[i]); } time++; } lengthQueue = QueueLength(queue[0]); /* Determines which queue */ n = 0; /* contains the least number of */ /* customers. */ for(i = 0; i < numOfQueues; i++){ if (!QueueIsEmpty(queue[i])){ customer = QueuePeek(queue[i], 0); if (time == lastDelTime[i] + customer.serviceTime){ if (QueueLength(queue[i]) - 1 < lengthQueue){ lengthQueue = QueueLength(queue[i]) - 1; n = i; } } } if (QueueLength(queue[i]) < lengthQueue){ lengthQueue = QueueLength(queue[i]); n = i; } } customer.arrivalTime = arrTime; /* Add customer to shortest queue. */ customer.serviceTime = serTime; if (QueueIsEmpty(queue[n])){ lastDelTime[n] = time; } QueueEnter(queue[n], customer); totalElemEntered++; lastTime = time; } for(i = 0; i < numOfQueues; i++){ /* Continue serving customers after */ time = lastTime; /* last customer has arrived. */ while(!QueueIsEmpty(queue[i])){ customer = QueuePeek(queue[i], 0); if (time == lastDelTime[i] + customer.serviceTime){ sumWaitTime += (time - customer.arrivalTime); if (longWaitLength < time - customer.arrivalTime){ longWaitLength = time - customer.arrivalTime; longWaitArrival = customer.arrivalTime; } QueueDelete(queue[i]); lastDelTime[i] = time; } if (time == lastTime){ numElemEnd += QueueLength(queue[i]); } time++; } } numElemQueues += numElemEnd; aveInQueues = (double) numElemQueues / lastTime; /* Calculate averages */ aveWait = (double) sumWaitTime / totalElemEntered; /* from counters. */ printf("%4d %10.2f %9.2f %7d %7d %9d\n", numOfQueues, aveWait, /* Print */ aveInQueues, longWaitLength, longWaitArrival, numElemEnd); /*results*/ fclose(sourceFile); /* Close customer data file. */ for(i = 0; i < numOfQueues; i++){ /* Empty all queues. */ FreeQueue(queue[i]); } return; } /* ------------------< end_of_file "hw6-toll.c" >----------------- */ -- END OF LOG FILE FOR kcochran --