Problem Set 2: Substitution
Evidence of a 5-point submission
- Uses a key validation method that requires only a single loop through the key; validate unique and alphabetic characters simultaneously using an array of size 
ALPHASIZE. - Stores substitution keys as all same-case letters (for efficiency later - only needs to convert one substitution to uppercase or lowercase during encryption)
 - Uses an efficient method to encrypt plaintext (minimal repeated code, printing out the encrypted text directly instead of using a variable, uses the 
isupperandislowerfunctions) - Does not use 26 as a magic number
 
Evidence of a 4-point submission
- Uses a method better than exhaustive search to validate unique characters (does not use two nested for loops that both iterate 
ALPHASIZEtimes; may use an array of sizeALPHASIZEbut in a way that does not short-circuit - see implementation example) - Stores substitution keys as all same-case letters (for efficiency later - only needs to convert one substitution to uppercase or lowercase during encryption)
 - Prints out encrypted text directly (does not store in a variable)
 
Evidence of a 3-point submission
- Uses an exhaustive iterative method to validate unique alphabetic characters that short circuits
 - Uses a 
forloop to iterate through each character of the input and encrypt it 
Evidence of a 2-point submission
- Uses a method worse than exhaustive (e.g., in O(n²)) to validate unique alphabetic characters (uses multiple nested loops to check the same characters more than once)
 - Uses a non-constant time operation to find the index of the key to encrypt a given letter, when 
plaintext[i] - 'a'orplaintext[i] - 'A'will do. - Loops over plaintext multiple times to encrypt
 
Evidence of a 1-point submission
- Uses a confusing method worse than exhaustive to validate unique alphabetic characters (checks for uniqueness in one nested loop, checks for alphabetic characters in a separate loop, doesn’t short-circuit)
 - Uses a confusing and/or very unclear method for encryption
 
Example Implementations (Worse vs. Better)
Validate Key
Worse implementation
In the example below, though this method does use a key validation method check for duplicates, it does not short-circuit.
int letters[26];
for (int i = 0; i < 26; i++)
{
    letters[i] = 0;
}
for (int i = 0; i < 26; i++)
{
    int letter = tolower((int)(key[i]));
    letters[letter - 'a']++;
}
for (int i = 0; i < 26; i++)
{
    if (letters[i] != 1)
    {
        printf("invalid key\n");
        return 1;
    }
}
In the example below, the method uses an exhaustive check method, but the method will short-circuit.
for (int i = 0; i < 26; i++)
{
    for (int j = 0; j < 26; j++)
    {
        if (i != j && s[i] == s[j])
        {
            return 1;
        }
    }
}
Better Implementation
The example below can be validated using O(1)-check calls. Simultaneously checks for alphabetical AND unique characters.
char substitution[ALPHASIZE] = {0};
bool used[ALPHASIZE] = {false};
for (int i = 0; i < ALPHASIZE; i++)
{
    if (!isalpha(key[i]))
    {
        printf("Key must contain only alphabetic characters.\n");
        return 1;
    }
    char c = toupper(key[i]);
    if (used[c - 'A'])
    {
        printf("Key must not contain repeated characters.\n");
        return 1;
    }
    used[c - 'A'] = true;
    substitution[i] = c;
}