Sunday, December 11, 2016

Finished PSET 2 (Encryption)

Rewarding Experience
Well that felt rewarding. I got stuck a few times, got a little frustrated but persevered.
PSET2 to recap I had to make 3 programs using the C programming Language.

initials.c
caesar.c
vigenere.c

Initials.c
This code prompts a user for his/her name, and then prints out the initials.


#include <stdio.h>
#include <cs50.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

int main(void)
{
   
    //asks for name
    string GetName =  GetString();

    //Prints First Initial
    printf("%c", toupper(GetName[0]));

    //Finds whitespace and prints next letter
    for (int i=0, n = strlen(GetName); i <n; i++)
    {
        if (GetName[i] == ' ')
        printf("%c", toupper(GetName[i+1]))   ;  
    }

 printf("\n");
 //return 0;

}


Summary
I had troubles trying to figure out how to find the first character of each name. After many attempts I had a light-bulb go off, printing the first character after a space.   So my code finds the whitespace, then prints out the next letter. Looking back at how long it took my I feel a little dumb, but I think that is a good thing as that means I have learned a lot!


Caesar Cipher
This program runs with a command line argument. The argument has to be an integer. If an integer is not ran when executing the program, it will return an error message and fail.

Key = 7
Example: If I execute: ./caesar 7
This program enciphers text using the Caesar Cipher.

It Spits out
Aopz wyvnyht lujpwolyz alea bzpun aol Jhlzhy Jpwoly

Here is my code.

#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>

int main (int argc, string argv[])
{
    //error checks 1 command line argument
    if (argc != 2)
    {
        printf ("Enter 1 Command Line Integer");
        return 1;
    }
   
    //converts string number into an integer
    int k = atoi(argv[1]);
   
    //grabs a string from the user
    string UserInput = GetString();  
   
    //This will itereate through each character in user input  
    for (int i = 0, n = strlen(UserInput); i < n; i++)    
    {
        int c = 0;
       
        //IF input is a letter  
        if (isalpha(UserInput[i]))    
        {
            //IF input is UpperCase
            if (isupper(UserInput[i]))    
            {
                c = (((int)UserInput[i] - 65 + k) % 26) + 65;    //calculates integer value of upper character and adds caser cipher key
                printf("%c",(char) c);  
            }  
           
            //If string Input is lowerCase  
            if (islower(UserInput[i]))    //If is a letter and lowercase
            {
                c = (((int)UserInput[i] - 97  + k) % 26) + 97;   //calculates integer value of lowercase character and adds caser cipher key
                printf("%c",(char) c );  
            }
               
        }
       
        else
        {
            //prints a space if space in string
            printf("%c", UserInput[i]);
        }  
    }
           
    printf("\n");
    return 0;

}

Summary
I struggled with this quite mightily. I ended up quitting, then coming back to it the next day, and spending probably 9-10 hours on it. I knew I needed to iterate over the string, but after  I was overwhelmed at the next step. When I attempted the next step I wasn't sure if i was doing it right.

I ended up creating and deleting my code multiple times.I found out that I don't break down the problems very well. I was overwhelmed trying to figure how upper/lower case figures out with the algorithm to solve.

This is what I should have done from the start.

  • Really grasp how the modulo works first.   
    • ex  1 % 3 = 1  why?
      • well 1 can't divide into 3, so 1 is the remainder
    • likewise 2 % 3 = 2
  • When figuring out the formula, forget everything else and write down an examples
    • lower case a Key of 7 = h
    • lower case a Key of  33 = h
      • ascii a = 97
      • ascii h = 104
    • you can see you only need to apply modulo to the Key and not the ascii value. That is where I spent a lot of time banging my head against a wall, and the corresponding "duh" moment when I re-visited how modulo works.
Again looking back I feel a bit embarrassed I took so long to solve this. Here I learned a lot about how to convert and add letters to ints, and visa versa. more importantly I think I made a tiny step forward in learning how to break problems down more efficiently.

Vigenere
Instead of a key like Caesar, vigenere takes a keyword. 

This program takes a keyword as a user argument. It then waits for a user to enter a string of text. This program then enciphers the text with vigenere 


#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>

int main (int argc, string argv[])
{
    //if their are less than 1 argument return an error and prompt user to try again   
    if (argc != 2)
    {
        printf ("Enter 1 Command Line Integer\n");
        return 1;
    }
    
    string key = argv[1];
    int keyLength = strlen(key) ;
    
    //Iterate through argv and check to ensure everything is an alphabet character
    for (int i = 0, n = strlen(key); i < n; i++) 
    {
        
        if (!isalpha(key[i]))
        {
            printf("You have a number in your key, Try again\n");
            return 1;
        }
    }    
    
    //Grabs a string to be ciphered    
    string UserInput = GetString();    
     
    
    //i  tracks string position, j tracks keyLength position
     //This will itereate through each character in user input string
    for (int i = 0, j = 0,  n = strlen(UserInput); i < n; i++)     
    {
        int cipherLetter = 0;
        int shift = 0;
        
        //this checks for alphabet characters     
        if (isalpha(UserInput[i]))
        {     
                  
            //finds shift if letter is uppercase
            if (isupper(UserInput[i]))
            {
                //calculates lowercase shift value
                shift = (int)toupper(key[j]) - 65;
                    
                //adds shift value to letter value and wraps around alphabet
                cipherLetter =  (((int)UserInput[i] - 65 + shift) % 26) + 65;
                
                //prints coresponding enciphered letter
                printf("%c", (char)(cipherLetter));
                j++;
            }
                
            //finds key shift if letter is lowercase
            if (islower(UserInput[i]))
            {
               //calculates lwoercase shift value
                shift = (int)tolower(key[j]) - 97;
                    
                //adds shift value to letter value and wraps around alphabet
                cipherLetter =  (((int)UserInput[i] - 97 + shift) % 26) + 97;
                
                //prints coresponding enciphered letter
                printf("%c", (char)(cipherLetter) );
                     
               j++;
            }
            
        }   
            
            else
            {
            printf("%c", UserInput[i]);
            }
            
            //wraps key back to first position
            if (j >= keyLength)
            {
                j = 0;
            }
            
    }
    printf("\n");
}    

Summary:
This didn't take me as long as Caesar did. probably 5 hours. Still longer than I would like to admit. I did get a bit overwhelmed again and looked for help. I had an aha moment when I saw a loop with 2 counter variables being initialized in the condition. I didn't realize that was an option.

I took a small break, stepped back and tried to go through this step by step. I ended up building some test code as I went. I experimented with print f everytime I wrote a line of code to test my integer and character math. I think going forward I will continue to do this if I can as it will help me to break the problems down and not become overwhelmed at the big picture.

I felt I cemented my knowledge of modulo as well as learned how to keep track of 2 changing variables for a loop.

It feels very rewarding to finish this. I am probably going to spend some time watching the RSA encryption video again, as well as week 3's videos.

ProblemSet3
Week 3 has a total of 3.5 hours of video to not only watch, but understand.  I found in the past I usually watch some videos more than once to understand a concept. Most people who have done the course say Pset3 is a slight notch more difficult, but far from the most difficult pset.


The problem sets will be changed at the end of the year. So I essentially have until the end of the year to complete a problem set. Knowing that their is only 2 weeks left in the year, with one of those being Christmas and multiple Christmas parties. I will only attempt one more pset before they change. It might be a tight fit, especially since my freetime after this weekend will be at a premium. 

Hopefully I can get a few hours at work I can escape to learn.

No comments:

Post a Comment