// Jonas Altrock <ew20b126@technikum-wien.at>
/* compile with `clang -std=c99 -Wall -o wordnum wordnum.c` */

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

typedef struct exam {
    char **wordTable;
    int wordTableSize;
    int words;
    int **numTable;
    int numTableSize;
    int nums;
} exam_t;

void allocAndReadInput(exam_t *exam);
void sortNum(exam_t *exam);
void output(exam_t *exam);
void freeMemory(exam_t *exam);

int main() {
    exam_t exam = {
            .wordTable = calloc(16, sizeof(char *)),
            .wordTableSize = 16,
            .words = 0,
            .numTable = calloc(16, sizeof(int *)),
            .numTableSize = 16,
            .nums = 0
    };

    allocAndReadInput(&exam);
    sortNum(&exam);
    output(&exam);
    freeMemory(&exam);
    return 0;
}

void allocAndReadInput(exam_t *exam) {
    // read input, distinguish between word and number, check for
    // duplicated words, allocate memory + reallocate if necessary,
    // store in wordTable / numTable

    char buffer[64];

    do {
        scanf("%63s", (char *) &buffer);

        // end program if it is "."
        if (strcmp(".", buffer) == 0) {
            return;
        }

        char *rest;
        int num = strtol(buffer, &rest, 10);

        // no rest, this is a valid number
        if (*rest == '\0') {
            // make space if table capacity is too small
            if (exam->nums == exam->numTableSize) {
                exam->numTableSize *= 2;
                exam->numTable = realloc(exam->numTable,
                                        exam->numTableSize * sizeof(int *));
            }

            exam->numTable[exam->nums] = malloc(sizeof(int));
            *exam->numTable[exam->nums] = num;
            exam->nums += 1;
        } else {
            bool found = false;

            // search for word in table
            for (int i = 0; i < exam->words; i++) {
                if (strcmp(buffer, exam->wordTable[i]) == 0) {
                    found = true;
                    break;
                }
            }

            // skip duplicate word
            if (found) {
                continue;
            }

            // make space if table capacity is too small
            if (exam->words == exam->wordTableSize) {
                exam->wordTableSize *= 2;
                exam->wordTable = realloc(exam->wordTable,
                                         exam->wordTableSize * sizeof(char *));
            }

            exam->wordTable[exam->words] = strdup(buffer);
            exam->words += 1;
        }
    } while (1);
}

void sortNum(exam_t *exam) {
    // sort numTable ascending

    // bubble sort
    for (int i = 0 ; i < exam->nums - 1; i++) {
        for (int j = 0 ; j < exam->nums - i - 1; j++) {
            // swap down if larger
            if (*exam->numTable[j] > *exam->numTable[j + 1]) {
                int *tmp = exam->numTable[j];
                exam->numTable[j] = exam->numTable[j + 1];
                exam->numTable[j + 1] = tmp;
            }
        }
    }
}

void output(exam_t *exam) {
    // print both wordTable and numTable

    for (int i = 0; i < exam->words; i++) {
        printf("%s ", exam->wordTable[i]);
    }

    printf("\n");

    for (int i = 0; i < exam->nums; i++) {
        printf("%i ", *exam->numTable[i]);
    }
}

void freeMemory(exam_t *exam) {
    for (int i = 0; i < exam->words; i++) {
        free(exam->wordTable[i]);
        exam->wordTable[i] = NULL;
    }

    for (int i = 0; i < exam->nums; i++) {
        free(exam->numTable[i]);
        exam->numTable[i] = NULL;
    }

    free(exam->wordTable);
    exam->wordTable = NULL;
    exam->words = 0;
    free(exam->numTable);
    exam->nums = 0;
    exam->numTable = NULL;
}