Week 2 - Arrays
Welcome to CS50 Week 2! As normal, I will be going through my summary of Week 1's content.
Problem Set 2
Things to notice in the problem statement
It is not case-sensitive, which means for example 'c' and 'C' carry the same point.
Every letter that is not alpha carries 0 point.
Divide and Conquer
Define a global variable array to store the points of each letter
Procedure Main
Prompt the user for two words
Compute the score of each word using ComputeWord
Print the winner
End Procedure
Procedure ComputeWord(word)
Initialize score to 0
For each character in the word
Add the character's point value to the score
End For
Return the score
End Procedure
Useful Snippets
Compute the score of a string
int compute_score(string word)
{
// Keep track of score
int score = 0;
//Compute score for each character
for (int i = 0, len = strlen(word); i < l; i++)
{
if (isupper(word[i]))
score += POINTS[word[i] - 'A'];
else if (islower(word[i]))
score += POINTS[word[i] - 'a'];
}
return score;
}
Take-aways
In the snippet, we can learn the style of traversing through a string in C, that's
for (int i, len = strlen(word); i < l; i++)
, then we can useword[i]
to represent each letter in the word in the loop.
Before the problem
To compute the reading level of a text, we will use Coleman-Liau index, whose formula is
index = 0.0588 * L - 0.296 * S - 15.8
, whereL
is the average number of lettes per 100 words, andS
is the average number of sentences per 100 words in the text.Notice that this formula may output "wrongly" if you only input one word, like
hello
, in this case, what you will get isGrade 14
, sincesentence
is 0. However, if we add a termination signal at the end, we will get the reasonable output. This is one disadvantage of this formula.
Things to notice in the problem statement
In
count_letters()
, we only need to count the characters that are alphabetical, soisalpha()
will be useful.In
count_words()
, we may assume that a sentence:will contain at least one word;
will not start or end with a space; and
will not have multiple spaces in a row; and
will not start with
!
,.
or?
So, based on these assumptions, we'll consider any sequence of characters seperated by a space to be a word.
In
count_sentences()
, we only need to consider any sequence of characters that ends with a.
or a!
or a?
to be a sentence.
Divide and Conquer
Procedure Main
Prompt the user for some text
Count the number of letters, words, and sentences in the text
Compute the Coleman-Liau index
Print the grade level
End Procedure
Useful Snippets
count_sentences()
int count_sentences(string text)
{
int count = 0;
for (int i = 0, len = strlen(text); i < len; i++)
{
if (isalpha(text[i]) && (text[i+1] == '!' || text[i+1] == '?' || text[i+1] == '.'))
count++;
}
return count;
}
Take-aways
To round a result (usually in float or double) to the nearest whole number, we can use the
round()
declared inmath.h
.
Before the problem
Caesar's algorithm encrypts messages by "rotating" each letter by positions.
Things to notice in the problem statement
The program should only accept only a single command-line argument, a non-negative integer. Otherwise, the program should output
Usage: ./caesar key
and return formmain
a value of1
.The program must preserve case: capitalized letters, though rotated, must remain capitalized letters; lowercase letters, though rotated, must remain lowercase letters.
Divide and Conquer
Procedure Main
Ensure the program was run with exactly one command-line argument
Verify that every character in argv[1] is a digit
Convert argv[1] from a string to an integer
Prompt the user for plaintext
For each character in the plaintext
Rotate the character if it is a letter
End For
End Procedure
Useful Snippets
The command-line argument,
int argc, string argv[]
template
int main(int argc, string argv[])
{
// ...
}
Check whehter the input is a non-negative integer or not.
int only_digits(string s)
{
int i, l;
for (i = 0, l = strlen(s); i < l; i++)
{
if (!isdigit(s[i]))
return 0;
}
return 1;
}
3. Rotate each alphabetical letter
char rotate(char c, int key)
{
if (!isalpha(c))
return c;
else
{
if (isupper(c))
{
int result = ((int) (c - 'A') + key) % 26 + (int) 'A';
return (char) result;
}
else
{
c = toupper(c);
int result = ((int) (c - 'A') + key) % 26 + (int) 'a';
return (char) result;
}
}
}
Take-aways
The
get_string()
provided in the<cs50.h>
won't truncate the extra white space behind. For example, if you input123
, the extra white space behind3
will also be counted into the string. But in this problem, because of the use ofstring argv[]
, it will use white space to seperate between strings, so the extra white space won't be counted toargv[1]
, and it will only contain123\0
.
Things to notice in the problem statement
Every character in the key must be alphabetical, case-sensitive and appear only once, which means
c
andC
can not appear in the key at the same time.
Dividie and Conquer
Procedure Main
Ensure the program was run with exactly one command-line argument
Verify that the key (argv[1]) is valid
Convert argv[1] from a string to an integer
Prompt the user for plaintext
For each character in the plaintext
Find the corresponding encrypted character if it is a letter
End For
End Procedure
Useful Snippets
Validate the
key
method.
int validate_key(string key) { int i, l, j; for (i = 0, l = strlen(key); i < l; i++) { if (!isalpha(key[i])) return 1; for (j = i+1; j < l; j++) { if (toupper(key[j]) == toupper(key[i])) return 1; } } return 0; }
method
int validate_key(string key) { int record[26] = {0}; for (int i = 0, l = strlen(key); i < l; i++) { int index = toupper(key[i]) - 'A'; if (!isalpha(key[i])) return 1; else if (record[index] == 1) return 1; else record[index] = 1; } return 0; }
Encrypt the alphabetical character
char encrypt(char c, string key)
{
int index;
int case_indicator = 0;
if (!isalpha(c))
return c;
else
{
// calculate the index and record the case_indicator
if (isupper(c))
{
index = (int) c - 'A';
case_indicator = 1;
}
else if (islower(c))
{
index = (int) c - 'a';
case_indicator = 0;
}
if (case_indicator)
return toupper(key[index]);
else
return tolower(key[index]);
}
}
Take-aways
In the validation part, the idea of keep tracking is important and will decrease the time compelxity tremendously.
The idea of index in the letter and array problem is important also. If it is case-sensitive in the problem, we can use
toupper()
ortolower()
to map the letter to its index.
Last updated