// Arup Guha
// 9/16/2021
// Program to make a large test case for Program #1

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

// Prints the large case.
void printLargeCase();

// Allows us to get larger random integers.
int randInt();

// Returns a random smoothie recipe with numItems # of items were all item numbers range from 0 to maxItem-1.
int* smoothieRecipe(int numItems, int maxItem);

// Returns an ingredient list with n ingredient names.
char** mkIngredList(int n);

// Returns a name with rank n with exactly size letters.
char* mkName(int n, int size);

// Returns 1 iff val is in arr[0..len-1], 0 otherwise.
int in(int* arr, int val, int len);

// For printing.
void printList(char** ingred, int n);
void print(int* nums, int n);

int main(void) {

    srand(time(0));
    printLargeCase();

    return 0;
}

void printLargeCase() {

    // Max ingredients.
    printf("100000\n");
    char** ingred = mkIngredList(100000);
    printList(ingred, 100000);
    for (int i=0; i<100000; i++)
        free(ingred[i]);
    free(ingred);

    // 1 to 10 ingredients for each of 100000 smoothies.
    printf("100000\n");
    for (int i=0; i<100000; i++) {
        int len = 1+rand()%10;
        int* tmp = smoothieRecipe(len, 100000);
        print(tmp, 2*len);
        free(tmp);
    }

    // 100 stores.
    printf("100\n");

    // Do each store.
    for (int i=0; i<100; i++) {

        // In between 5 and 34 smoothies per store.
        int numS = 5 + rand()%30;
        printf("%d", numS);

        // Clunky but generates numS unique IDs from 0 to 99999.
        int ids[100];
        for (int j=0; j<numS; j++) {

            int next = -1;
            while (1) {
                next = randInt()%100000;

                if (!in(ids, next, j)) {
                    ids[j] = next;
                    break;
                }
            }
        }

        // Just give a random weight to each smoothie.
        for (int j=0; j<numS; j++) {
            printf(" %d %d", ids[j], 1+randInt()%1000);
        }
        printf("\n");
    }



}

// Returns 1 iff val is in arr[0..len-1], 0 otherwise.
int in(int* arr, int val, int len) {
    for (int i=0; i<len; i++)
        if (arr[i] == val)
            return 1;
    return 0;
}

// Prints the n strings in ingred.
void printList(char** ingred, int n) {
    for (int i=0; i<n; i++)
        printf("%s\n", ingred[i]);
}

// Prints the n integers in nums preceded by n/2, the number of pairs of ints.
void print(int* nums, int n) {
    printf("%d", n/2);
    for (int i=0; i<n; i++)
        printf(" %d", nums[i]);
    printf("\n");
}

// Returns a larger random integer.
int randInt() {
    return (rand()<<10) + (rand()&1023);
}

// Returns a random smoothie recipe with numItems # of items were all item numbers range from 0 to maxItem-1.
int* smoothieRecipe(int numItems, int maxItem) {

    // Store the result here.
    int* res = malloc(sizeof(int)*2*numItems);

    // Will store which items we've used so far.
    int* used = calloc(maxItem, sizeof(int));

    int i = 0;

    // Keep going till we fill it.
    while (i < 2*numItems) {

        // Get a new ID.
        int id = 0;
        while (1) {
            id = randInt()%maxItem;
            if (used[id]) continue;
            used[id] = 1;
            break;
        }

        // Put in this smoothie and in between 1 and 8 parts.
        res[i] = id;
        res[i+1] = 1 + randInt()%8;
        i += 2;
    }

    // Don't need this any more.
    free(used);

    return res;
}

// Returns the first n names using our convention of size 4 (hard-coded for now).
char** mkIngredList(int n) {
    char** res = malloc(sizeof(char*)*n);
    for (int i=0; i<n; i++)
        res[i] = mkName(i, 4);
    return res;
}

// Returns the nth alphabetic name of lowercase letters with size letters.
char* mkName(int n, int size) {

    // This is basically base conversion.
    char* res = malloc(sizeof(char)*(size+1));
    for (int i=0; i<size; i++) {
        res[size-1-i] = (char)('a'+n%26);
        n /= 26;
    }
    res[size] = '\0';
    return res;
}
