By

Technical – Brain Fog

This weekend I watched the CS50 Week 3 lecture, despite not completing Week 2 as of yet. Week 2 has a final task “Substitution” which sets the goal of creating a program capable of encrypting using said cipher. To my detriment I decided I’d try both encrypting and decrypting…

A cipher is simply a recipe, or instruction set, to encrypt or decrypt a message. Caesar famously had a cypher where messages would be keyed by incrementing the letters along the alphabet. For example a=2,b=3 with a key of +1. A substitution cipher instead swaps letters of the alphabet around. So:

ABCDEFGHIJKLMNOPQRSTUVWYXZ becomes NQXPOMAFTRHLZGECYJIUWSKDVB

Hello becomes Folle

The logic is straightforward, you take the index of each letter from the alphabet (H = 8), and then move it over to the key to return the encrypted letter (8 = F) and so on through the rest of the message.

After a few hours I had made most of the code, but could not get the logic correct for the actual program, something I’m attributing to a lack of sleep mostly, and a general brain fog or malaise.

I’ll post the code I have now, and will include the completed version in the next post along with any other progress I make.

What I’ve also discovered is that Harvard offer an older course, Introduction to Games, which focuses on Love2D. Love2D is the same engine used to make the titular Balatro that recently won Indie game of the year and also consumes a not-insignificant part of my game time currently. Although the content is old, I think after CS50 I’ll give that a go. It pushes some of my personally set game dev goals back, but overall might boost my progression in the long run.

Here’s what I have for this Sundays coding session:

#import <cs50.h>
#import <ctype.h>
#import <string.h>
#import <stdio.h>


// PSEUDO
/*
    ascii lowercase alpha start = 97

    Get KEY
        must be 26 characters
        must be all uppercase
        must be only alphabetic
        must not have duplicates

    Get Encrypt or Decrypt
    Get String

    if Encrypt
        for each char in string
            return key to output string
        output string
    if Decrypt
        for each char in string
            return alphabet to output string
*/


// Define
#define alpha_u 65
#define alpha_l 97
#define alpha_length 26


// PROTO
bool is_valid_key(char *argv, int KEY_LENGTH);
char *to_lower(char *INPUT, int KEY_LENGTH);
char *encrypt(char *KEY, char* INPUT, int KEY_LENGTH, int INPUT_LENGTH);
char *decrypt(char *KEY, char* INPUT, int KEY_LENGTH, int INPUT_LENGTH);


// MAIN
int main(int argc, char *argv[])
{
    int choice = 0;
    int KEY_LENGTH = strlen(argv[1]);

    // CMDLINE Argument checking
    if(argc !=2)
    {
        printf("Usage: .\\substitution KEY\n");
        return 1;
    }
    if(!is_valid_key(argv[1], KEY_LENGTH))
    {
        return 1;
    }

    // Cryption choice
    while (choice < 1 || choice > 2)
    {
        choice = get_int("Would you like to encrypt(1) or decrypt(2)?: ");
    }

    char *INPUT = get_string("Enter the message: ");
    int INPUT_LENGTH = strlen(INPUT);
    char *OUTPUT;
    printf("%s", INPUT);

    if (choice == 1)
    {
        printf("\nEncrypt selected\n");
        OUTPUT = encrypt(argv[1], INPUT, KEY_LENGTH, INPUT_LENGTH);
        printf("Encryption: %s\n", OUTPUT);
    }
    else if (choice == 2)
    {
        printf("\nDecrypt selected\n");
        OUTPUT = decrypt(argv[1], INPUT, KEY_LENGTH, INPUT_LENGTH);
        printf("Decryption: %s\n", OUTPUT);
    }
}


// FUNCTIONS
bool is_valid_key(char *KEY, int KEY_LENGTH)
{
    if ((KEY_LENGTH != alpha_length)) // Check length
    {
        printf("KEY must be 26 characters. Entered KEY length %i\n", KEY_LENGTH);
        return false;
    }
    for (int i = 0; i < KEY_LENGTH; i++)      // For current character
    {
        if (!isalpha(KEY[i]))                // Check for numbers
        {
            printf("KEY must only contain letters\n");
            return false;
        }
        for (int j = 0; j < KEY_LENGTH; j++)    // Check for duplicates
        {
            if ((i != j) && (KEY[j] == KEY[i]))
            {
                printf("Duplicates are not allowed\n");
                return false;
            }
        }
    }
    return true;
}

char *encrypt(char *KEY, char* INPUT, int KEY_LENGTH, int INPUT_LENGTH)
{
    // encrypt message
    // loop INPUT[i]
        // loop KEY[j]
            // if INPUT[i] == KEY[j]
                // update INPUT
    // return INPUT
    for (int i = 0; i < INPUT_LENGTH; i++)
    {
        for (int j = 0; j < KEY_LENGTH; j++)
        {
            if (INPUT[i] == KEY[j])
            {
                if (isupper(INPUT[i]))
                {
                    INPUT[i] = alpha_u + j;
                }
                else
                {
                    INPUT[i] = alpha_l + j;
                }
                break;
            }
        }
    }

    return INPUT;
}

char *decrypt(char *KEY, char* INPUT, int KEY_LENGTH, int INPUT_LENGTH)
{
    // loop INPUT[i]
        // loop KEY[j]
            // if INPUT[i] == KEY[j]
                // update INPUT
    // return INPUT
    for (int i = 0; i < INPUT_LENGTH; i++)
    {
        for (int j = 0; j < KEY_LENGTH; j++)
        {
            if (INPUT[i] == KEY[j])
            {
                if (isupper(INPUT[i]))
                {
                    INPUT[i] = alpha_u + j;
                    break;
                }
                else
                {
                    INPUT[i] = alpha_l + j;
                }
            }
        }
    }

    return INPUT;
}


Leave a comment