You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
127 lines
3.5 KiB
127 lines
3.5 KiB
#include <stdio.h>
|
|
|
|
#include <glib.h>
|
|
|
|
struct action {
|
|
int id;
|
|
GPtrArray *depends;
|
|
GPtrArray *required_by;
|
|
};
|
|
|
|
void free_action(gpointer data)
|
|
{
|
|
struct action *action = (struct action *)data;
|
|
g_ptr_array_free(action->depends, TRUE);
|
|
g_ptr_array_free(action->required_by, TRUE);
|
|
g_free(action);
|
|
}
|
|
|
|
struct action *get_action(GHashTable *table, int id)
|
|
{
|
|
struct action *action = g_hash_table_lookup(table, GINT_TO_POINTER(id));
|
|
if (action) return action;
|
|
|
|
action = g_malloc(sizeof(struct action));
|
|
action->depends = g_ptr_array_new();
|
|
action->required_by = g_ptr_array_new();
|
|
action->id = id;
|
|
g_hash_table_insert(table, GINT_TO_POINTER(id), action);
|
|
return action;
|
|
}
|
|
|
|
gint compare_action(gconstpointer _a, gconstpointer _b)
|
|
{
|
|
struct action *a = *(struct action **)_a;
|
|
struct action *b = *(struct action **)_b;
|
|
return a->id - b->id;
|
|
}
|
|
|
|
GHashTable *parse_tree(const char *fname)
|
|
{
|
|
FILE *f = fopen(fname, "r");
|
|
if (!f) {
|
|
perror(fname);
|
|
return NULL;
|
|
}
|
|
|
|
GHashTable *table = g_hash_table_new_full(NULL, NULL, NULL, free_action);
|
|
|
|
char *line = NULL;
|
|
size_t line_len = 0;
|
|
while (getline(&line, &line_len, f) != -1) {
|
|
char depends = 0;
|
|
char required_by = 0;
|
|
sscanf(line, "Step %c must be finished before step %c can begin.",
|
|
&depends, &required_by);
|
|
|
|
struct action *dependent = get_action(table, depends);
|
|
struct action *required = get_action(table, required_by);
|
|
|
|
g_ptr_array_add(dependent->required_by, required);
|
|
g_ptr_array_add(required->depends, dependent);
|
|
}
|
|
|
|
free(line);
|
|
fclose(f);
|
|
return table;
|
|
}
|
|
|
|
int main()
|
|
{
|
|
GHashTable *table = parse_tree("input");
|
|
if (!table) return 1;
|
|
|
|
GPtrArray *queue = g_ptr_array_new();
|
|
GString *result = g_string_new(NULL);
|
|
|
|
// Find items without dependencies
|
|
GHashTableIter iter;
|
|
gpointer key, value;
|
|
g_hash_table_iter_init(&iter, table);
|
|
while (g_hash_table_iter_next(&iter, &key, &value)) {
|
|
struct action *action = (struct action *)value;
|
|
if (action->depends->len == 0) {
|
|
g_ptr_array_add(queue, action);
|
|
}
|
|
}
|
|
|
|
struct action *workers[5] = {0};
|
|
unsigned workers_time[5] = {0};
|
|
unsigned working = 0;
|
|
unsigned time = 0;
|
|
|
|
do {
|
|
g_ptr_array_sort(queue, compare_action);
|
|
while (queue->len && working < 5) {
|
|
struct action *action = g_ptr_array_remove_index(queue, 0);
|
|
workers[working] = action;
|
|
workers_time[working++] = action->id - 'A' + 1 + 60;
|
|
}
|
|
|
|
for (unsigned i = 0; i < working; i++) {
|
|
if (--workers_time[i] != 0) continue;
|
|
|
|
struct action *action = workers[i];
|
|
memmove(workers + i, workers + i + 1, sizeof(struct action *) * (5 - i - 1));
|
|
memmove(workers_time + i, workers_time + i + 1, sizeof(unsigned) * (5 - i - 1));
|
|
working--;
|
|
i--;
|
|
|
|
g_string_append_c(result, action->id);
|
|
for (unsigned i = 0; i < action->required_by->len; i++) {
|
|
struct action *next = g_ptr_array_index(action->required_by, i);
|
|
g_ptr_array_remove_fast(next->depends, action);
|
|
if (next->depends->len == 0) g_ptr_array_add(queue, next);
|
|
}
|
|
}
|
|
time++;
|
|
} while (queue->len || working);
|
|
|
|
puts(result->str);
|
|
printf("%u\n", time);
|
|
|
|
g_string_free(result, TRUE);
|
|
g_ptr_array_free(queue, TRUE);
|
|
g_hash_table_destroy(table);
|
|
return 0;
|
|
}
|
|
|