255 lines
8.6 KiB
C
255 lines
8.6 KiB
C
// header files
|
|
#include <string.h>
|
|
#include "StandardConstants.h"
|
|
#include "File_Input_Utility.h"
|
|
#include "BasicUtilities.h"
|
|
#include "CourseUtilities.h"
|
|
#include "RoomUtilities.h"
|
|
|
|
// local constants
|
|
const int MAX_NUM_ROOMS = 25;
|
|
const int MAX_NUM_COURSES = 25;
|
|
const int NO_CLASS = -1;
|
|
|
|
// local prototypes
|
|
bool fitClassRooms( CourseArrayType *courseData,
|
|
RoomArrayType *roomData, int initialRoomLevel, bool verboseFlag );
|
|
bool uploadData( const char *fileName,
|
|
CourseArrayType *courseData, RoomArrayType *roomData );
|
|
|
|
// main function
|
|
int main( int argc, char **argv )
|
|
{
|
|
int initialRoomLevel = 0;
|
|
RoomArrayType *rooms;
|
|
CourseArrayType *courses;
|
|
bool verboseSetting = true;
|
|
|
|
printf( "\nCourse/Classroom Fit Program\n" );
|
|
printf( "============================\n" );
|
|
|
|
rooms = createRoomArray( MAX_NUM_ROOMS );
|
|
courses = createCourseArray( MAX_NUM_COURSES );
|
|
|
|
if( uploadData( "InputFiles/in_6.txt", courses, rooms ) )
|
|
{
|
|
printf( "Start Solution Search\n" );
|
|
|
|
if( fitClassRooms( courses, rooms, initialRoomLevel, verboseSetting ) )
|
|
{
|
|
printf( "\nFit Classroom Success: Solution Found.\n");
|
|
|
|
displayList( courses, rooms );
|
|
}
|
|
|
|
else
|
|
{
|
|
printf( "\nFit Classroom Failure: Solution not found.\n");
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
printf( "Upload failure\n" );
|
|
}
|
|
|
|
// end program
|
|
|
|
// clear data
|
|
rooms = clearRoomArray( rooms );
|
|
courses = clearCourseArray( courses );
|
|
|
|
// show program end
|
|
printf( "\nEnd Course/Classroom Fit Program\n" );
|
|
|
|
// return success
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
Name: fitClassRooms
|
|
Process: implements brute force recursive backtracking strategy
|
|
to fit specified courses with their specified student size
|
|
into classrooms with their specified capacity
|
|
Function input/parameters: pointer to a courses array type (CourseArrayType *),
|
|
pointer to a room array type (RoomArrayType *),
|
|
room level shows which room is seeking a course
|
|
and indicates the recursion level (int),
|
|
verbose flag that specifies whether
|
|
to display the recursive backtracking process (bool)
|
|
Function output/parameters: updated courses file (CourseArrayType *),
|
|
updated rooms file (RoomArrayType *)
|
|
Function output/returned: Boolean result of the process (bool)
|
|
Device input/---: none
|
|
Device output/---: none
|
|
Dependencies: available tools as needed
|
|
*/
|
|
bool fitClassRooms( CourseArrayType *courses,
|
|
RoomArrayType *rooms, int roomLevel, bool verboseFlag )
|
|
{
|
|
int arrayIterator;
|
|
RoomDataType tempClassRoom;
|
|
CourseDataType tempCourse;
|
|
char buildingString[STD_STR_LEN];
|
|
char courseString[STD_STR_LEN];
|
|
// If all courses have been placed
|
|
// return true
|
|
if(roomLevel == rooms->size)
|
|
{
|
|
return true;
|
|
}
|
|
// setup for current classroom
|
|
deepCopyRoom(&tempClassRoom, rooms->array[roomLevel]);
|
|
deepCopyCourse(&tempCourse, courses->array[roomLevel]);
|
|
setRoomDataString(buildingString, tempClassRoom);
|
|
if(verboseFlag)
|
|
{
|
|
printf("\nRecursion Level %d: Seeking a fit for %s\n", roomLevel, buildingString);
|
|
}
|
|
for(arrayIterator = 0; arrayIterator < courses->size; arrayIterator++)
|
|
{
|
|
if(verboseFlag)
|
|
{
|
|
printSpaces(2);
|
|
}
|
|
// For Loop (Increments through courses)
|
|
if(courses->array[arrayIterator].available &&
|
|
tempClassRoom.roomCapacity > courses->array[arrayIterator].size)
|
|
{
|
|
// Test to find classroom
|
|
// If open and less than course size
|
|
// Set classroom associated index to course
|
|
rooms->array[roomLevel].associatedIndex = arrayIterator;
|
|
// Set course as unavailable
|
|
courses->array[arrayIterator].available = false;
|
|
setCourseDataString(courseString, courses->array[arrayIterator]);
|
|
if(verboseFlag)
|
|
{
|
|
printSpaces(2);
|
|
printf("Trying Course Name: %s, Course Size: %d - Success!\n", courses->array[arrayIterator].courseName, courses->array[arrayIterator].size);
|
|
printSpaces(6);
|
|
printf("Course Name: %s, Course Size: %d will fit in %s\n", tempCourse.courseName, tempCourse.size, buildingString);
|
|
}
|
|
// Call and check next recursion
|
|
if(fitClassRooms(courses, rooms, roomLevel + 1, verboseFlag))
|
|
{
|
|
return true;
|
|
}
|
|
// Unset classroom associated index to course
|
|
tempClassRoom.associatedIndex = NO_CLASS;
|
|
// Set course as available
|
|
courses->array[arrayIterator].available = true;
|
|
}
|
|
if(verboseFlag)
|
|
{
|
|
printf(" Trying Course Name: %s, Course Size: %d - Failed!\n", courses->array[arrayIterator].courseName, courses->array[arrayIterator].size);
|
|
}
|
|
// end for loop
|
|
}
|
|
if(verboseFlag)
|
|
{
|
|
printf("\nCourse Name: %s, Course Size: %d - recursion fell back to Recursion Level %d\n", tempCourse.courseName, tempCourse.size, roomLevel - 1);
|
|
printSpaces(2);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
Name: uploadData
|
|
Process: uploads data file containing rooms available and courses to be fitted,
|
|
has internal flag to show uploaded data or not
|
|
Function input/parameters: file name (const char *),
|
|
pointer to course array type (CourseArrayType*),
|
|
pointer to room array type (RoomArrayType *)
|
|
Function output/parameters: updated courses file (CourseArrayType *),
|
|
updated rooms file (RoomArrayType *)
|
|
Function output/returned: Boolean result of the process (bool)
|
|
Device input/---: none
|
|
Device output/---: none
|
|
Dependencies: as needed, including File Input Utilities, and strcmp
|
|
*/
|
|
bool uploadData( const char *fileName,
|
|
CourseArrayType *courseData, RoomArrayType *roomData )
|
|
{
|
|
char tempStr[ STD_STR_LEN ];
|
|
int tempRoomNum, tempRoomCapacity, tempRoomAssociation = NO_CLASS;
|
|
int tempClassSize, tempClassAvailable = true;
|
|
bool verboseFlag = true;
|
|
|
|
roomData->size = 0;
|
|
|
|
if( openInputFile( fileName ) )
|
|
{
|
|
if( verboseFlag )
|
|
{
|
|
printf( "\n==========Upload start\n" );
|
|
}
|
|
|
|
// ignore first line
|
|
readStringToLineEndFromFile( tempStr );
|
|
|
|
// capture first room line - prime loop
|
|
readStringToDelimiterFromFile( COMMA, tempStr );
|
|
|
|
// loop to end of room data
|
|
while( strcmp( tempStr, "End Room Data" ) != 0
|
|
&& roomData->size < roomData->capacity )
|
|
{
|
|
tempRoomNum = readIntegerFromFile();
|
|
|
|
readCharacterFromFile();
|
|
|
|
tempRoomCapacity = readIntegerFromFile();
|
|
|
|
if( verboseFlag )
|
|
{
|
|
printf( "Nm: %s, Num: %d, cap: %d\n",
|
|
tempStr, tempRoomNum, tempRoomCapacity );
|
|
}
|
|
|
|
addRoomWithData( roomData, tempStr,
|
|
tempRoomNum, tempRoomCapacity, tempRoomAssociation );
|
|
// reprime - capture next building name, or end of data string
|
|
readStringToDelimiterFromFile( COMMA, tempStr );
|
|
}
|
|
|
|
// initialize class size
|
|
courseData->size = 0;
|
|
|
|
// ignore first line
|
|
readStringToLineEndFromFile( tempStr );
|
|
|
|
// capture first course line - prime loop
|
|
readStringToDelimiterFromFile( COMMA, tempStr );
|
|
|
|
// loop to end of course data
|
|
while( strcmp( tempStr, "End Class Data" ) != 0
|
|
&& courseData->size < courseData->capacity )
|
|
{
|
|
// get class size
|
|
tempClassSize = readIntegerFromFile();
|
|
|
|
if( verboseFlag )
|
|
{
|
|
printf( "Nm: %s, sz: %d\n", tempStr, tempClassSize );
|
|
}
|
|
|
|
addCourseWithData( courseData,
|
|
tempStr, tempClassSize, tempClassAvailable );
|
|
|
|
// reprime - get next building name, or end of data string
|
|
readStringToDelimiterFromFile( COMMA, tempStr );
|
|
}
|
|
|
|
if( verboseFlag )
|
|
{
|
|
printf( "==========Upload end\n\n" );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|