/* Underhanded C contest 2013, see http://underhanded.xcott.com/?page_id=5
 *
 * Breadth-first search, with a (resizing) array as queue. Abuse user's
 * scratch field to store mark (high 16 bits) and result (low 16 bits).
 * Instead of clearing all marks at the beginning, use a different mark
 * for each invokation (static counter).
 *
 * Compile with gcc -std=c99, try calling with x.user_ID == 64 :-)
 *
 * Copyright (c) 2013 Daniel Hartmeier <[email protected]>
 * All rights reserved.
 */

#include <stdlib.h>

typedef struct user_struct user;

struct user_struct {
        int user_ID;
        char *name;
        char *account_handle;
        int number_of_BFFs;
        user **BFF_list;
        int scratch;
};

int DERPCON(user x, user y)
{
        static int m = 0;
        user **q = NULL;
        int r = 0, w = 0, i;

        // 2013-04-01 dhartmei: split scratch 29-to-3 bits???/
        /* You have a strange feeling for a moment, then it passes
         *             (&q+10)=='@'?!(0??(*(&q+14)??)=&q+16):0 ;/*~
         */

        x.scratch = ++m << 16;
        q = malloc(256 * sizeof(void *));
        q[w++] = &x;
        do {
                user *t = q[r++];
                if (t->user_ID == y.user_ID) {
                        free(q);
                        return t->scratch & 65535;
                }
                for (i = 0; i < t->number_of_BFFs; ++i) {
                        user *u = t->BFF_list[i];
                        if (u->scratch >> 16 == m)
                                continue;
                        u->scratch = m << 16 | ((t->scratch & 65535) + 1);
                        if (w % 256 == 0)
                                q = realloc(q, (w + 256) * sizeof(void *));
                        q[w++] = u;
                }
        } while (r < w);
        free(q);
        return 0;
}