// Arup Guha
// 9/21/2023
// Solution to CIS 3362 Quiz 2 Problem 6

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char* newtrans(char* plain, int* perm, int n);
char* newtransalt(char* plain, int* perm, int n);

int main() {

    // A small test.
    int perm[5] = {2,4,3,0,1};
    char msg[201];
    printf("Please enter a message 200 chars or less also multiple of 5 chars.\n");
    scanf("%s", msg);

    // Encrypt and print.
    char* cipher = newtrans(msg, perm, 5);
    printf("%s\n", cipher);
    free(cipher);

    cipher = newtransalt(msg, perm, 5);
    printf("%s\n", cipher);
    free(cipher);

    return 0;
}

char* newtrans(char* plain, int* perm, int n) {

    // Get the length of the message and # of columns for copying.
    int len = strlen(plain);
    int cols = len/n;

    // Will store the inverse permuttion here.
    int* invperm = malloc(sizeof(int)*n);

    // Just map output to input (from perm).
    for (int i=0; i<n; i++)
        invperm [ perm[i] ] = i ;

    // Store result here.
    char* cipher = malloc(sizeof(char)*(len+1));

    // Copy chars from plain into cipher.
    int j = 0;
    for (int i=0; i<n; i++)

        // To start at the last column offset by (cols-1)*n.
        // Then add invperm[i]. Finally, subtract n to go up one column each time.
        for (int idx=(cols-1)*n+invperm[i]; idx>=0; idx-=n)
            cipher[j++] = plain[idx];

    // This is important before you return...
    cipher[len] = '\0';
    free(invperm);
    return cipher;
}

char* newtransalt(char* plain, int* perm, int n) {

    // Get the length of the message and # of columns for copying.
    int len = strlen(plain);
    int cols = len/n;

    // Store result here.
    char* cipher = malloc(sizeof(char)*(len+1));

    // Copy chars from plain into cipher.
    for (int i=0; i<n; i++) {
        int j = perm[i]*cols;
        for (int idx=(cols-1)*n+i; idx>=0; idx-=n)
            cipher[j++] = plain[idx];
    }

    // This is important before you return...
    cipher[len] = '\0';
    return cipher;
}
