2023-11-28 13:19:22 -04:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
// Data structures and helper functions
|
|
|
|
typedef struct DiskRequest {
|
|
|
|
int position;
|
|
|
|
int time;
|
|
|
|
} DiskRequest;
|
|
|
|
|
|
|
|
typedef struct DiskQueue {
|
|
|
|
DiskRequest *requests;
|
|
|
|
int size;
|
|
|
|
} DiskQueue;
|
|
|
|
|
|
|
|
DiskQueue *createDiskQueue() {
|
|
|
|
DiskQueue *queue = malloc(sizeof(DiskQueue));
|
|
|
|
if (queue == NULL) {
|
|
|
|
printf("Error allocating memory for queue\n");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
queue->requests = malloc(sizeof(DiskRequest));
|
|
|
|
if (queue->requests == NULL) {
|
|
|
|
printf("Error allocating memory for queue requests\n");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
queue->size = 0;
|
|
|
|
return queue;
|
|
|
|
}
|
|
|
|
|
|
|
|
DiskRequest diskRequest(int position, int time) {
|
|
|
|
DiskRequest request;
|
|
|
|
request.position = position;
|
|
|
|
request.time = time;
|
|
|
|
return request;
|
|
|
|
}
|
|
|
|
|
|
|
|
void enqueue(DiskQueue *queue, DiskRequest request) {
|
|
|
|
queue->requests = realloc(queue->requests, sizeof(DiskRequest) * (queue->size + 1));
|
2023-11-28 20:12:47 -04:00
|
|
|
if (queue->requests == NULL) {
|
|
|
|
printf("Error reallocating memory for queue requests\n");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2023-11-28 13:19:22 -04:00
|
|
|
queue->requests[queue->size] = request;
|
|
|
|
queue->size++;
|
|
|
|
}
|
|
|
|
|
2023-11-28 20:12:47 -04:00
|
|
|
|
|
|
|
|
|
|
|
DiskRequest delete(DiskQueue *queue, DiskRequest request) {
|
|
|
|
// Find the index of the request
|
|
|
|
int index = -1;
|
|
|
|
for (int i = 0; i < queue->size; i++) {
|
|
|
|
if (queue->requests[i].position == request.position && queue->requests[i].time == request.time) {
|
|
|
|
index = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (index == -1) {
|
|
|
|
printf("Error: Request not found in queue\n");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
// Shift all the elements after the index down one
|
|
|
|
for (int i = index; i < queue->size - 1; i++) {
|
|
|
|
queue->requests[i] = queue->requests[i + 1];
|
|
|
|
}
|
|
|
|
// Resize the queue
|
|
|
|
queue->requests = realloc(queue->requests, sizeof(DiskRequest) * (queue->size - 1));
|
|
|
|
if (queue->requests == NULL) {
|
|
|
|
printf("Error reallocating memory for queue requests\n");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
queue->size--;
|
2023-11-28 13:19:22 -04:00
|
|
|
return request;
|
|
|
|
}
|
|
|
|
|
2023-11-28 20:12:47 -04:00
|
|
|
|
|
|
|
|
|
|
|
DiskQueue* clone(DiskQueue *queue) {
|
|
|
|
DiskQueue *clone = createDiskQueue();
|
|
|
|
for (int i = 0; i < queue->size; i++) {
|
|
|
|
enqueue(clone, queue->requests[i]);
|
|
|
|
}
|
|
|
|
return clone;
|
|
|
|
}
|
|
|
|
|
|
|
|
DiskRequest peek(DiskQueue *queue) {
|
|
|
|
return queue->requests[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
DiskRequest dequeue(DiskQueue *queue) {
|
|
|
|
return delete(queue, peek(queue));
|
|
|
|
}
|
|
|
|
|
|
|
|
DiskQueue *queueOfLesserTime(DiskQueue *queue, double time) {
|
2023-11-28 13:19:22 -04:00
|
|
|
DiskQueue *sameTimeQueue = createDiskQueue();
|
2023-11-28 20:12:47 -04:00
|
|
|
for (int i = 0; i < queue->size; i++) {
|
|
|
|
if (queue->requests[i].time <= time) {
|
2023-11-28 13:19:22 -04:00
|
|
|
enqueue(sameTimeQueue, queue->requests[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return sameTimeQueue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compare function for disk requests by position
|
|
|
|
int compareDiskRequestsByPosition(const void *a, const void *b) {
|
|
|
|
DiskRequest *requestA = (DiskRequest *) a;
|
|
|
|
DiskRequest *requestB = (DiskRequest *) b;
|
|
|
|
return requestA->position - requestB->position;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sorts the queue by position, in place
|
2023-11-28 17:21:49 -04:00
|
|
|
DiskQueue *sortQueueByPosition(DiskQueue *queue) {
|
2023-11-28 13:19:22 -04:00
|
|
|
qsort(queue->requests, queue->size, sizeof(DiskRequest), compareDiskRequestsByPosition);
|
|
|
|
return queue;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void destroyDiskQueue(DiskQueue *queue) {
|
|
|
|
free(queue->requests);
|
|
|
|
free(queue);
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef enum DiskDirection {
|
|
|
|
UP, DOWN
|
|
|
|
} DiskDirection;
|
|
|
|
|
|
|
|
|
|
|
|
// Global tracking variables
|
|
|
|
DiskDirection currentDirection = UP;
|
|
|
|
int movement = 0;
|
|
|
|
double seekTime = 0;
|
|
|
|
|
|
|
|
// Array for storing the requests
|
|
|
|
DiskQueue *queue;
|
|
|
|
|
|
|
|
double timeToProcessRequest(int position, int destination) {
|
2023-11-28 17:21:49 -04:00
|
|
|
//The time (a floating point number) required to process a request is computed by distance the head travels divided by 5
|
|
|
|
//Plus additional 15 milliseconds penalty if the direction has to change (for FCFS)
|
2023-11-28 13:19:22 -04:00
|
|
|
double time = 0;
|
2023-11-28 17:21:49 -04:00
|
|
|
// Calculated this way so that positive means up and negative means down
|
|
|
|
int distance = destination - position;
|
|
|
|
DiskDirection direction = (distance > 0) ? UP : DOWN;
|
|
|
|
time += abs(distance) / 5.0;
|
|
|
|
if (direction != currentDirection) {
|
2023-11-28 13:19:22 -04:00
|
|
|
time += 15;
|
|
|
|
currentDirection = direction;
|
|
|
|
}
|
|
|
|
return time;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Your simulated disk is of size 10000, numbered from 0 to 9999.
|
|
|
|
|
|
|
|
// In first come first the time the request comes in is irrelevant
|
|
|
|
void fcfs(int start) {
|
|
|
|
int position = start;
|
2023-11-28 20:12:47 -04:00
|
|
|
int size = queue->size;
|
|
|
|
|
|
|
|
for (int i = 0; i < size; i++) {
|
2023-11-28 13:19:22 -04:00
|
|
|
DiskRequest request = dequeue(queue);
|
2023-11-28 19:44:53 -04:00
|
|
|
while (seekTime < request.time) { seekTime++; }
|
2023-11-28 13:19:22 -04:00
|
|
|
seekTime += timeToProcessRequest(position, request.position);
|
|
|
|
movement += abs(position - request.position);
|
|
|
|
position = request.position;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cscan(int start) {
|
|
|
|
int position = start;
|
2023-11-28 20:12:47 -04:00
|
|
|
|
|
|
|
DiskQueue *workingQueue = clone(queue);
|
|
|
|
|
|
|
|
while (workingQueue->size > 0) {
|
|
|
|
DiskQueue *candidates = queueOfLesserTime(workingQueue, seekTime);
|
|
|
|
|
|
|
|
if (candidates->size == 0) {
|
|
|
|
while (seekTime < peek(workingQueue).time) { seekTime++; }
|
|
|
|
continue;
|
2023-11-28 13:19:22 -04:00
|
|
|
}
|
2023-11-28 20:12:47 -04:00
|
|
|
sortQueueByPosition(candidates);
|
|
|
|
DiskRequest request = dequeue(candidates);
|
|
|
|
|
|
|
|
if (request.position < position) {
|
|
|
|
// Go to end of disk and back to 0
|
|
|
|
seekTime += timeToProcessRequest(position, 9999);
|
|
|
|
seekTime += timeToProcessRequest(9999, 0);
|
|
|
|
movement += abs(position - 9999);
|
|
|
|
movement += abs(9999 - 0);
|
|
|
|
position = 0;
|
|
|
|
}
|
|
|
|
seekTime += timeToProcessRequest(position, request.position);
|
|
|
|
movement += abs(position - request.position);
|
|
|
|
position = request.position;
|
|
|
|
delete(workingQueue, request);
|
|
|
|
destroyDiskQueue(candidates);
|
2023-11-28 13:19:22 -04:00
|
|
|
}
|
2023-11-28 20:12:47 -04:00
|
|
|
destroyDiskQueue(workingQueue);
|
2023-11-28 13:19:22 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int main(int argc, char **argv) {
|
|
|
|
int position, time;
|
|
|
|
char algorithm = argv[1][0];
|
|
|
|
int start = 0;
|
|
|
|
|
|
|
|
queue = createDiskQueue();
|
|
|
|
|
|
|
|
while (EOF != (scanf("%i %i\n", &position, &time))) {
|
|
|
|
enqueue(queue, diskRequest(position, time));
|
|
|
|
// printf("Delete me: position %i, Delete me: time %i\n", position, time);
|
|
|
|
}
|
|
|
|
if (algorithm == 'F') {
|
|
|
|
fcfs(start);
|
2023-11-28 17:21:49 -04:00
|
|
|
printf("Movement:%i Time:%.1lf\n", movement, seekTime);
|
2023-11-28 13:19:22 -04:00
|
|
|
} else if (algorithm == 'C') {
|
|
|
|
cscan(start);
|
2023-11-28 17:21:49 -04:00
|
|
|
// Stupid printf difference to pass tests, could call once after if statement
|
|
|
|
printf("Movement: %i Time:%.1lf\n", movement, seekTime);
|
2023-11-28 13:19:22 -04:00
|
|
|
}
|
|
|
|
destroyDiskQueue(queue);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|