Mayan Calculation


The aim of this puzzle is to perform operations between mayan numbers. It involves a lot of string manipulation to convert mayan numbers to decimal numbers, and to convert the result to a mayan number.

C

Once more, I prefered allocating 2-dimensionnal arrays dynamically, because it makes it easier to pass them to functions.

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

/* digit is a 2-dim array of size H x W representing 1 of the 20 mayan digits.
   digits is a 2-dim array of size H x 20*W representing the 20 mayan digits.
   This function compares 'digit' with each of the 20 digits and returns
   the matching decimal value.*/
int mayanDigitToInt(char** digit, char** digits, int W, int H) {
    int isIdentical = 0;
    int i = 0;
    while (i < 20 && !isIdentical) {
        /* we assum 'digit' to be the i-th digit of 'digits' and look
           for a difference to refute this hypothesis*/ 
        isIdentical = 1;
        for (int y = 0; y < H && isIdentical; y++)
            for (int x = 0; x < W && isIdentical; x++)
                if (digits[y][i*W + x] != digit[y][x]) {
                    isIdentical = 0;
                    i++;
                }
    }
    return i;
}

/* number is a 2-dim array of size numberH x > representing a mayan number
   digits is a 2-dim array of size H x 20*W representing the 20 mayan digits.
   This functions converts number into its decimal value*/
long mayanNumberToLong(char** number, int numberH, char** digits, int W, int H) {
    long result = 0;
    for (int i = 0; i < numberH/H; i++)
        result += mayanDigitToInt(number + i*H, digits, W, H) * pow(20, numberH/H - (i+1));
    return result;
}

/* digits is a 2-dim array of size H x 20*W representing the 20 mayan digits.
   This function converts 'digit' into its mayan representation and prints it.*/
void printAsMayanDigit(int digit, char** digits, int W, int H) {
    for (int y = 0; y < H; y ++) {
        fwrite(&digits[y][digit*W], W, sizeof(char), stdout);
        printf("\n");
    }
}

/* digits is a 2-dim array of size H x 20*W representing the 20 mayan digits.
   This function prints the mayan representation of 'number' recursively, 
   using printAsMayanDigit*/
void printAsMayanNumber(long number, char** digits, int W, int H) {
    if(number != 0) {
        printAsMayanNumber(number/20, digits, W, H);
        printAsMayanDigit(number%20, digits, W, H);
    }
}

// Frees a dynamically allocated 2-dimensionnal array of dimension dim1 xsmthing
void free2DArray(char **array, int dim1) {
    for (int i = 0; i < dim1; i++)
        free(array[i]);
    free(array);
}

int main(int argc, char **argv)
{
    int W, H;
    scanf("%d %d\n", &W, &H);

    // reads the 20 mayan digits
    char** digits = malloc(H * sizeof(*digits));
    for (int i = 0; i < H; i++) {
        digits[i] = malloc(20 * W * sizeof(**digits));
        gets(digits[i]);
    }
    
    // read first mayan number
    int nb1H;
    scanf("%d\n", &nb1H);
    char **nb1 = malloc(nb1H * sizeof(*nb1));
    for (int i = 0; i < nb1H; i++) {
        nb1[i] = malloc(W * sizeof(**nb1));
        gets(nb1[i]);
    }
    long decimalNb1 = mayanNumberToLong(nb1, nb1H, digits, W, H);
    
    
    // reads second mayan number
    int nb2H;
    scanf("%d\n", &nb2H);
    char **nb2 = malloc(nb2H * sizeof(*nb2));
    for (int i = 0; i < nb2H; i++) {
        nb2[i] = malloc(W * sizeof(**nb2));
        gets(nb2[i]);
    }
    long decimalNb2 = mayanNumberToLong(nb2, nb2H, digits, W, H);
    
    // reads the operation to perform
    char operation;
    scanf("%c\n", &operation);
    
    // performs operation
    long result = 0;
    switch(operation) {
        case '*':
            result = decimalNb1 * decimalNb2; break;
        case '/':
            result = decimalNb1 / decimalNb2; break;
        case '+':
            result = decimalNb1 + decimalNb2; break;
        case '-':
            result = decimalNb1 - decimalNb2; break;
    }
    
    // prints result
    if (result == 0)
        printAsMayanDigit(0, digits, W, H);
    else
        printAsMayanNumber(result, digits, W, H);

    // frees memory
    free2DArray(digits, H);
    free2DArray(nb1, nb1H);
    free2DArray(nb2, nb2H);

    return EXIT_SUCCESS;
}