File: netconnections.c - Tab length: 1 2 4 8 - Lines: on off - No wrap: on off

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

struct  Config { unsigned int machine, network, next, size; };

#define setMachine(m, n, x) ({ struct Config* p = (m); p->network = (n); p->next = (x); })
#define setNetwork(n, m, s) ({ struct Config* p = (n); p->machine = (m); p->size = (s); })

void    exec_command (struct Config* configs, unsigned int m1, unsigned int m2, unsigned int* unique)
{
        struct Config*  machine;
        unsigned int    n1 = configs[m1 - 1].network, n2 = configs[m2 - 1].network;

        if (n1 == 0)
        {
                if (n2 != 0)
                {
                        setMachine (&configs[m1 - 1], n2, configs[n2 - 1].machine);
                        setNetwork (&configs[n2 - 1], m1, configs[n2 - 1].size + 1);
                }
                else if (m1 != m2)
                {
                        setMachine (&configs[m1 - 1], (n1 = ++(*unique)), m2);
                        setMachine (&configs[m2 - 1], n1, 0);
                        setNetwork (&configs[n1 - 1], m1, 2);
                }
        }
        else if (n2 == 0)
        {
                setMachine (&configs[m2 - 1], n1, configs[n1 - 1].machine);
                setNetwork (&configs[n1 - 1], m2, configs[n1 - 1].size + 1);
        }
        else if (n1 != n2)
        {
                if (configs[n1 - 1].size > configs[n2 - 1].size)
                        n1 ^= n2 ^= n1 ^= n2;

                for (machine = &configs[configs[n1 - 1].machine - 1]; machine->next; machine = &configs[machine->next - 1])
                        machine->network = n2;

                setMachine (machine, n2, configs[n2 - 1].machine);
                setNetwork (&configs[n2 - 1], configs[n1 - 1].machine, configs[n2 - 1].size + configs[n1 - 1].size);
        }
}

int     exec_query (const struct Config* configs, unsigned int m1, unsigned int m2)
{
        return configs[m1 - 1].network == 0 ? m1 == m2 : configs[m1 - 1].network == configs[m2 - 1].network;
}

char    read_char (char* buffer, unsigned int length, unsigned int* offset)
{
        while (*offset < length && buffer[*offset] <= ' ')
                ++(*offset);

        return *offset < length ? buffer[(*offset)++] : '\0';
}

unsigned int    read_uint (char* buffer, unsigned int length, unsigned int* offset)
{
        unsigned int    value = 0;

        for (; *offset < length && ((value == 0 && buffer[*offset] <= ' ') || (buffer[*offset] >= '0' && buffer[*offset] <= '9')); ++(*offset))
                value = (buffer[*offset] <= ' ') ? value : (value * 10 + buffer[*offset] - '0');

        return value;
}

int     main (int argc, char* argv[])
{
        struct Config*  configs;
        FILE*                   file = fopen (argv[1], "r");
        unsigned int    length, m1, offset = 0, unique = 0, query[2] = {0, 0};
        char*                   buffer, type;

        length = !fseek (file, 0, SEEK_END) ? ftell (file) : 0;
        buffer = (char*)malloc (length * sizeof (*buffer));
        fseek (file, 0, SEEK_SET);
        fread (buffer, sizeof (*buffer), length, file);

        for (configs = (struct Config*)calloc (read_uint (buffer, length, &offset), sizeof (*configs)); (type = read_char (buffer, length, &offset)) != '\0'; )
        {
                m1 = read_uint (buffer, length, &offset);

                if (type == 'c')
                        exec_command (configs, m1, read_uint (buffer, length, &offset), &unique);
                else
                        ++query[!exec_query (configs, m1, read_uint (buffer, length, &offset))];
        }

        printf ("%u,%u\n", query[0], query[1]);

        return 0;
}