-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlhs-3.c
177 lines (149 loc) · 5.44 KB
/
lhs-3.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
/*
file: lhs-3.c
author: David De Potter
email: [email protected]
license: MIT, see LICENSE file in repository root folder
description: lecture hall scheduling (LHS)
using greedy algorithm and a stack
time complexity: O(n log n) where n is the number of activities
note: this version uses a stack to keep track of available halls,
which will schedule activities differently than the lhs-4.c
version, which uses a binary heap, but the schedules are,
of course, still optimal, using the minimum number of halls
*/
#include "../../../lib/clib.h"
#include "../../../datastructures/stacks/stack.h"
//===================================================================
// Defines an activity
typedef struct activity {
size_t id; // activity id based on input order
size_t start; // start time
size_t end; // end time
size_t hallId; // hall where the activity is scheduled
} activity;
//===================================================================
// Defines an event: the start or end of an activity
typedef struct event {
activity *act; // activity associated with the event
size_t time; // time of the event
enum { START, END } type; // start or end event
} event;
//===================================================================
// Defines a lecture hall
typedef struct hall {
size_t id; // hall id
activity *sch; // schedule of activities
size_t schSize; // number of activities in the schedules
} hall;
//===================================================================
// Compares two events by their time in ascending order: if a start
// event and an end event have the same time, the end event comes
// first in the sorted order so that the hall is freed up first
int cmpEvents(void const *a, void const *b) {
event *e1 = (event *)a;
event *e2 = (event *)b;
if (e1->type == START && e2->type == END && e1->time == e2->time)
return 1;
return e1->time - e2->time;
}
//===================================================================
// Shows an activity
void showActivity(activity act) {
printf("Act %zu: [ %zu, %zu )\n", act.id, act.start, act.end);
}
//===================================================================
// Creates events from activities
event *createEvents(activity *acts, size_t nActs) {
event *events = safeCalloc(nActs * 2, sizeof(event));
for (size_t i = 0; i < nActs; i++) {
events[i * 2].act = &acts[i];
events[i * 2].time = acts[i].start;
events[i * 2].type = START;
events[i * 2 + 1].act = &acts[i];
events[i * 2 + 1].time = acts[i].end;
events[i * 2 + 1].type = END;
}
return events;
}
//===================================================================
// Reads activities from stdin
activity *readActivities(size_t *nActs) {
size_t cap = 50, n = 0;
activity *acts = safeCalloc(cap, sizeof(activity));
while (scanf(" [ %zu , %zu ) , ",
&acts[n].start, &acts[n].end) == 2) {
acts[n].id = n + 1;
if (++n == cap) {
cap *= 2;
acts = safeRealloc(acts, cap * sizeof(activity));
}
}
*nActs = n;
return acts;
}
//===================================================================
// Creates a new lecture hall
hall *newHall(size_t id, size_t schSize) {
hall *h = safeCalloc(1, sizeof(hall));
h->sch = safeCalloc(schSize, sizeof(event));
h->id = id;
return h;
}
//===================================================================
// Schedules activities in lecture halls by scanning the events as
// they appear in the time line
size_t scheduleActivities(activity *acts, size_t nActs, hall **halls,
event *events) {
size_t nHalls = 0;
qsort(events, nActs * 2, sizeof(event), cmpEvents);
// create a stack of available halls
stack *availHalls = newStack(nActs);
// scan the events
for (size_t i = 0; i < nActs * 2; i++) {
event e = events[i];
if (e.type == START) {
if (isEmptyStack(availHalls)) {
// create a new hall if no halls are available
halls[nHalls] = newHall(nHalls + 1, nActs);
stackPush(availHalls, halls[nHalls++]);
}
// assign activity to the last hall that became available
hall *h = stackPop(availHalls);
h->sch[h->schSize++] = *e.act;
e.act->hallId = h->id;
} else
// if an activity ends, its hall becomes available again
stackPush(availHalls, halls[e.act->hallId - 1]);
}
freeStack(availHalls);
return nHalls;
}
//===================================================================
// Shows the number of halls and their schedules
void showSchedules(hall **halls, size_t nHalls) {
printf("Number of halls: %zu\n\n"
"SCHEDULES\n", nHalls);
for (size_t i = 0; i < nHalls; i++) {
printf("\n---------\n"
" Hall %zu"
"\n---------\n", halls[i]->id);
for (size_t j = 0; j < halls[i]->schSize; j++)
showActivity(halls[i]->sch[j]);
free(halls[i]->sch);
free(halls[i]);
}
printf("\n");
}
//===================================================================
int main() {
size_t nActs = 0;
activity *acts = readActivities(&nActs);
event *events = createEvents(acts, nActs);
hall **halls = safeCalloc(nActs, sizeof(hall*));
size_t nHalls = scheduleActivities(acts, nActs, halls, events);
showSchedules(halls, nHalls);
free(events);
free(acts);
free(halls);
return 0;
}