// IOI '97 Stack // Simulation Module Definition File - simmod.cpp // Dennis Burford // #include "stacklib.h" void stackprimopen(char *filename, int *handle, int *error); void stackprimclose(int handle, int *error); void stackprimread(int *bytes, char *buffer, int handle, int *error); void stackprimcreate(char *filename, int *error); void stackprimappend(int handle, int *error); void stackprimwrite(int *bytes, char *buffer, int handle, int *error); void stackprimprint(char *string); void stacklog (int *data, int bytes); #define idGetX 100 // int (); // width of storage space #define idGetY 101 // int (); // breadth of storage space #define idGetZ 102 // int (); // depth of storage space #define idGetNextContainer 103 // int (); // ID of next container #define idGetNextAction 104 // int (); // 1: store container 2: retrieve container #define idGetNextStorageTime 105 // int (); // Number of hours expected #define idRefuseContainer 106 // void (); // refuse incoming container #define idStoreArrivingContainer 107 // void (int x, int y); // store container on stack at (x,y) #define idRemoveContainer 108 // void (int x, int y); // removes the container at (x,y) #define idMoveContainer 109 // int (int x1, int y1, int x2, int y2); // move container from (x1,y1) to (x2,y2) 1: succes 0: failure #define idInvalidDataFile 200 // Type Definitions #define numtolog 6 typedef int logtype; logtype stacklogged[numtolog]; #define bytestolog 12 #define LOGFILENAME "stack.out" #define DATFILENAME "stack.dat" typedef char boolean; #define false 0 #define true 1 boolean stackinitialized = false; int filefound = 0; typedef struct ccontainer { int id; int expected_time; }; #ifdef __cplusplus #define container ccontainer #else #define container struct ccontainer #endif container NULLcontainer; /* { int id; refused_container *next; }; */ // Data int moves; // for book-keeping int refused; int max_count, actions; // file counters // ifstream dataFile; // files for input/output // ofstream logFile; int dataFilehandle; int logFilehandle; #define maxarea 100 #define maxrefusedcontainers 300 #define maxdepth 10 int _width,_breadth,_depth; // dimensions of storage int current_action; // container properties container next; //Stack *space; // storage space //container *space; // 2Darray of containers... container space[maxarea][maxdepth]; void setspace(int x, int y, container val) { if (x >= maxarea) return; if (y >= maxdepth) return; space[x][y] = val; }; void clearspace(int x, int y) { if (x >= maxarea) return; if (y >= maxdepth) return; space[x][y] = NULLcontainer; }; container getspace(int x, int y) { if (x >= maxarea) return NULLcontainer; if (y >= maxdepth) return NULLcontainer; return space[x][y]; }; int _heights[maxarea]; // height map of storage int refusedlist[maxrefusedcontainers]; // keeping track of refusals int refusedlistlength = 0; // // Refused-Container-List Routines // void NewRefused(int id) // cont id. was refused { /* refused_container *r; r = new refused_container; r->id = id; r->next = NULL; if (FirstRefused==NULL) FirstRefused = r; if (LastRefused != NULL) LastRefused->next = r; LastRefused = r; */ if (refusedlistlength < maxrefusedcontainers) refusedlist[refusedlistlength++] = id; } int WasRefused(int id) // was cont id. refused ? { int i; // for (r=FirstRefused; (r != NULL)&&(r->id != id); r = r->next); for (i = 0; i < refusedlistlength; i++) if (refusedlist[i]==id) return 1; return 0; // return (r->id == id); } // // 'Private' functions // void bye() { int error; // logFile.close(); // stackprimclose(logFilehandle,&error); // should be closed anyway // dataFile.close(); stackprimclose(dataFilehandle,&error); stacklogged[0] = idInvalidDataFile; stacklogged[1] = error; stacklog(stacklogged,bytestolog); stackprimprint("Invalid Data File....\n\r$"); // exit(1); } void NextContainer() { int bytes,error; bytes = 2; // stackprimprint("NextContainer:\n\r$"); if (actions < max_count) // still more actions to do { // stackprimprint(" actions < max_count:\n\r$"); do { // dataFile >> current_action; // read new action details // dataFile >> next.id; // dataFile >> next.expected_time; // stackprimprint(" do:\n\r$"); if (filefound) { // stackprimprint(" file found:\n\r$"); stackprimread(&bytes,(char *)¤t_action,dataFilehandle,&error); stackprimread(&bytes,(char *)&next.id,dataFilehandle,&error); stackprimread(&bytes,(char *)&next.expected_time,dataFilehandle,&error); } else { // stackprimprint(" !filefound:\n\r$"); switch(actions+1) // actions counted from 0 upwards... { case 1 : current_action = 1; next.id = 1; next.expected_time = 7; break; case 2 : current_action = 1; next.id = 2; next.expected_time = 7; break; case 3 : current_action = 1; next.id = 3; next.expected_time = 7; break; case 4 : current_action = 1; next.id = 4; next.expected_time = 7; break; case 5 : current_action = 1; next.id = 5; next.expected_time = 7; break; case 6 : current_action = 1; next.id = 6; next.expected_time = 8; break; case 7 : current_action = 1; next.id = 7; next.expected_time = 9; break; case 8 : current_action = 2; next.id = 1; next.expected_time = 0; break; case 9 : current_action = 1; next.id = 8; next.expected_time = 8; // Check that equal times are allowed: time = 8 break; case 10: current_action = 2; next.id = 2; next.expected_time = 0; break; case 11: current_action = 2; next.id = 3; next.expected_time = 0; break; case 12: current_action = 2; next.id = 4; next.expected_time = 0; break; case 13: current_action = 2; next.id = 5; next.expected_time = 0; break; case 14: current_action = 2; next.id = 6; next.expected_time = 0; break; case 15: current_action = 2; next.id = 8; next.expected_time = 0; break; case 16: current_action = 2; next.id = 7; next.expected_time = 0; break; } } actions++; // stackprimprint(" got action:\n\r$"); // can't retrieve refused container } while ((current_action == 2) && WasRefused(next.id) && actions < max_count); } else if (actions == max_count) { // stackprimprint(" actions==max_count:\n\r$"); // logFile << "Total moves: " << moves<< "-> " << -moves << endl; // logFile << "Total refusals: " << refused<< "-> " << -5*refused << endl; // logFile << "Total points: " << -moves + -5*refused << endl; // stackprimwrite(&bytes,(char *)&moves,logFilehandle,&error); // logFile.close(); // should be closed already // stackprimclose(logFilehandle,&error); // dataFile.close(); if (filefound) stackprimclose(dataFilehandle,&error); next.id = 0; next.expected_time = 0; actions++; // Don't do this section more than once } // stackprimprint("returning from NextContainer:\n\r$"); } void initialize() { int i,area,error,bytes; // stackprimprint("hello\n\r$"); NULLcontainer.id = 0; NULLcontainer.expected_time = 0; bytes = 2; // logFile.open("stack.out"); // create log file #ifndef NOLOG // stackprimprint("create logfile:\n\r$"); stackprimcreate(LOGFILENAME,&error); // stackprimprint("open logfile:\n\r$"); stackprimopen(LOGFILENAME,&logFilehandle,&error); // stackprimprint("close log file:\n\r$"); stackprimclose(logFilehandle,&error); #endif // dataFile.open("stack.dat"); // open data file // stackprimprint("open dat file:\n\r$"); stackprimopen(DATFILENAME,&dataFilehandle,&error); if (error) // an error occurred opening file, so make up data { // stackprimprint("error occured:\n\r$"); filefound = 0; _width = 3; _breadth = 2; _depth = 3; max_count = 16; } else { // stackprimprint("no error occured\n\r$"); filefound = 1; // dataFile >> _width >> _breadth >> _depth;// read in dimensions stackprimread(&bytes,(char *)&_width,dataFilehandle,&error); stackprimread(&bytes,(char *)&_breadth,dataFilehandle,&error); stackprimread(&bytes,(char *)&_depth,dataFilehandle,&error); if (_width+_breadth+_depth <= 0) bye(); // Invalid Data File // dataFile >> max_count; // number of actions stackprimread(&bytes,(char *)&max_count,dataFilehandle,&error); }; area = _width*_breadth; // area of storage space if (area > maxarea) { stackprimprint("Area too large..\n\r$"); bye(); }; if (_depth > maxdepth) { stackprimprint("Depth too large..\n\r$"); bye(); }; // space = new Stack[area]; // create stack space // space = new container[area*_depth]; // space = (container *)malloc(sizeof(container)*area*_depth); // _heights = new int[area]; // create height map // _heights = (int *)malloc(sizeof(int)*area); // stackprimprint("setting up:\n\r$"); for (i=0; i< area; i++) // clear height map _heights[i] = 0; moves = 0; // book-keeping refused = 0; current_action = 0; // undefined action actions = 0; // zero action counter // stackprimprint("calling nextcontainer:\n\r$"); NextContainer(); // read first container stackinitialized = 1; // stackprimprint("returning from initialize:\n\r$"); } // // 'Public' functions // int GetX() // _width of storage space { // stackprimprint("GetX\n\r$"); if (!stackinitialized) // If this is the 1st call initialize(); // stackprimprint("(initialized)\n\r$"); // stacklogged[0] = idGetX; // stacklogged[1] = _width; // stacklog(stacklogged,bytestolog); return _width; } int GetY() // _breadth of storage space { if (!stackinitialized) initialize(); // stacklogged[0] = idGetY; // stacklogged[1] = _breadth; // stacklog(stacklogged,bytestolog); return _breadth; } int GetZ() // _depth of storage space { if (!stackinitialized) initialize(); // stacklogged[0] = idGetZ; // stacklogged[1] = _depth; // stacklog(stacklogged,bytestolog); return _depth; } // ID of next container int GetNextContainer() { if (!stackinitialized) initialize(); stacklogged[0] = idGetNextContainer; stacklogged[1] = next.id; stacklog(stacklogged,bytestolog); return next.id; } // 1: store container 2: retrieve container int GetNextAction() { if (!stackinitialized) initialize(); stacklogged[0] = idGetNextAction; stacklogged[1] = current_action; stacklog(stacklogged,bytestolog); return current_action; } // Number of hours expected int GetNextStorageTime() { if (!stackinitialized) initialize(); stacklogged[0] = idGetNextStorageTime; stacklogged[1] = next.expected_time; stacklog(stacklogged,bytestolog); return next.expected_time; } // refuse incoming container void RefuseContainer() { if (!stackinitialized) initialize(); if (current_action == 1) // refuse to *STORE* container { // logFile << "Refusal: -5" << endl; refused++; stacklogged[0] = idRefuseContainer; stacklogged[1] = next.id; stacklogged[2] = refused; stacklog(stacklogged,bytestolog); NewRefused(next.id); NextContainer(); } } // store container on stack at (x,y) void StoreArrivingContainer(int x, int y) { if (!stackinitialized) initialize(); stacklogged[0] = idStoreArrivingContainer; stacklogged[1] = x; stacklogged[2] = y; stacklog(stacklogged,bytestolog); if (x>0 && y>0 && x<=_width && y<=_breadth) if ((next.id > 0) && (_heights[x + y*_width] < _depth)) { // space[x + y*_width].Push(next); setspace(x+y*_width,_heights[x+y*_width]++,next); // _heights[x + y*_width]++; NextContainer(); } } // romoves the container at (x,y) void RemoveContainer(int x, int y) { if (!stackinitialized) initialize(); stacklogged[0] = idRemoveContainer; stacklogged[1] = x; stacklogged[2] = y; // even if logging we must do this for evaluation... if (x>0 && y>0 && x<=_width && y<=_breadth) if ((next.id > 0) && (_heights[x + y*_width] > 0)) { // space[x + y*_width].Pop(); if (getspace(x+y*_width,_heights[x+y*_width]-1).id != next.id) return; // only log if the removal is actually going to take place... stacklog(stacklogged,bytestolog); clearspace(x+y*_width,_heights[x + y*_width]--); NextContainer(); } } // move container from (x1,y1) to (x2,y2) 1: succes 0: failure int MoveContainer(int x1, int y1, int x2, int y2) { if (!stackinitialized) initialize(); stacklogged[0] = idMoveContainer; stacklogged[1] = x1; stacklogged[2] = y1; stacklogged[3] = x2; stacklogged[4] = y2; if (x1>0 && y1>0 && x1<=_width && y1<=_breadth) if (x2>0 && y2>0 && x2<=_width && y2<=_breadth) if ((_heights[x1 + y1*_width] > 0) && (_heights[x2 + y2*_width] < _depth)) { // space[x2 + y2*_width].Push( space[x1 + y1*_width].Pop_And_Top()); container tomove; tomove = getspace(x1+y1*_width,_heights[x1 + y1*_width]-1); // top of 1 clearspace(x1+y1*_width,_heights[x1+y1*_width]--); // pop from 1 setspace(x2+y2*_width,_heights[x2 + y2*_width]++,tomove); // push to 2 // logFile << "Move: -1" << endl; moves++; stacklogged[5] = 1; stacklog(stacklogged,bytestolog); return 1; } stacklogged[5] = 0; stacklog(stacklogged,bytestolog); return 0; } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- // stackprimopen: opens file... // error codes: 1 = invalid function // 2 = file not found // 3 = path not found // 4 = no handles available // 5 = access denied // 12= invalid access code //-------------------------------------------------------------------------- void stackprimopen(char *filename, int *handle, int *error) { int localhandle; int localerror; asm { mov ah, 3Dh // open file mov al, 2 // 2 = read and write access mov dx, word ptr [filename] // ds:dx = name - zero terminated string int 21h jc open_error mov localhandle,ax mov word ptr localerror,0 jmp proc_end } open_error: asm { mov localerror,ax } proc_end: *handle = localhandle; *error = localerror; } //-------------------------------------------------------------------------- // stackprimcreate: creates a file // truncates it if it exists already //-------------------------------------------------------------------------- void stackprimcreate(char *filename, int *error) { int localerror; asm { mov ah, 3Ch // create file mov cx, 0 // file attribute is normal mov dx, word ptr [filename] // ds:dx = name - zero terminated string int 21h jc create_error mov word ptr localerror,0 jmp proc_end } create_error: asm { mov localerror,ax } proc_end: *error = localerror; } //------------------------------------------------------------------------- // close (int handle, int *error) // error code: 6 = invalid handle //------------------------------------------------------------------------- void stackprimclose(int handle, int *error) { int localerror; asm { mov ah, 3Eh // close file mov bx, handle int 21h jnc close_successful mov localerror,ax } close_successful: asm { mov word ptr localerror,0 } *error = localerror; } //------------------------------------------------------------------------- // stackprimwrite (int *bytes, char *buffer, int handle, int *error) // error codes: 5 = access denied // 6 = invalid handle //------------------------------------------------------------------------- void stackprimwrite(int *bytes, char *buffer, int handle, int *error) { int localbytes; int localerror; localbytes = *bytes; localerror = *error; asm { mov ah, 40h // read file or device mov cx, localbytes mov dx, word ptr [buffer] // ds:dx = pointer to buffer mov bx, handle int 21h jc write_error mov ax, localbytes // number of bytes successfully written mov word ptr localerror,0 jmp proc_end } write_error: asm { mov localerror,ax } proc_end: *bytes = localbytes; *error = localerror; } //------------------------------------------------------------------------- // stackprimappend (int handle, int *error) // error codes: 5 = access denied // 6 = invalid handle //------------------------------------------------------------------------- void stackprimappend(int handle, int *error) { int localerror; localerror = *error; asm { mov ah, 42h // move file pointer mov al, 2 // move relative to end of file mov cx, 0 // high order word of distance to move mov dx, 0 // low order word of distance to move mov bx, handle int 21h jc append_error mov word ptr localerror,0 jmp proc_end } append_error: asm { mov localerror,ax } proc_end: *error = localerror; } //------------------------------------------------------------------------- // read (int *bytes, char *buffer, int handle, int *error) // error codes: 5 = access denied // 6 = invalid handle //------------------------------------------------------------------------- void stackprimread(int *bytes, char *buffer, int handle, int *error) { int localbytes; int localerror; localbytes = *bytes; localerror = *error; asm { mov ah, 3Fh // read file or device mov cx, localbytes mov dx, word ptr [buffer] // ds:dx = pointer to buffer mov bx, handle int 21h jc read_error mov ax, localbytes // number of bytes successfully read mov word ptr localerror,0 jmp proc_end } read_error: asm { mov localerror,ax } proc_end: *bytes = localbytes; *error = localerror; } //------------------------------------------------------------------------- // print (char *string) // string is terminated by '$' //------------------------------------------------------------------------- void stackprimprint(char *string) { asm { mov ah, 9h // display string mov dx, word ptr [string] int 21h } } //-------------------------------------------------------------------------- void stacklog (int *data, int bytes) { #ifndef NOLOG int handle, error=0, i; stackprimopen (LOGFILENAME, &handle, &error); stackprimappend (handle, &error); if (!filefound) for (i=0; i