Eda Eren

April 5, 2022
  • Miscellaneous
  • Python

Solving the Problem Sets of CS50's Introduction to Programming with Python โ€” One at a Time: Problem Set 0

Being one of the biggest online courses (and, one of the most popular courses of Harvard) is not the only thing that defines CS50. Having absolutely zero knowledge on anything related to computer science beforehand, when I finished the course last year with a final project that surprisingly exceeded my expectations, and managed to create a demo site for it, it was a big dopamine rush. If you literally start taking the course without any prior experience, understanding and finally being able to solve the problem sets of the course is almost like a spiritual experience. David J. Malan is a phenomenal lecturer who helps you internalize concepts that seem difficult for a beginner.

CS50 is now not a single course on Introduction to Computer Programming, but has turned into a bigger ecosystem for different courses with various flavors, be it Web Programming, Artificial Intelligence, or, Mobile App Development. Its latest, Introduction to Programming with Python, does not exactly focus on theoretical computer science concepts, but is a more general programming course using Python. I love Python, and I was really excited to see the new problems that CS50 would provide for us to solve in this new course.

Before I start, here is a disclaimer: I am not going to provide full solutions to Problem Sets. See academic honesty.

I am planning to write about how to start thinking about a given problem, maybe as a kind of guidance, and how one might go about solving it. I assume you already read the problem set explanations, as I might allude to them. Generally, the problems start easy and perhaps more friendly, then the curve becomes steeper. It is a nice challenge, though, that is how you realize that you are actually learning.

Indoor Voice

The first problem seems pretty straightforward. Our given input just has to be "quiet" instead of being in "yelling case". What that means is, if 'THIS IS YELLING', then 'this is not yelling'. And, here is the importance of reading the documentation of the tool that you are using, in this case, Python. Because we work with str data types in the problem, we simply have to look up if Python comes with built-in str methods โ€” and, it does. A lot of them. For example, it has capitalize(), lower(), upper() among many others. Let's see how these would work:

s = 'This is CS50.'

print(s.capitalize()) # This is CS50.
print(s.lower()) # this is cs50.
print(s.upper()) # THIS IS CS50.
s = 'This is CS50.'

print(s.capitalize()) # This is CS50.
print(s.lower()) # this is cs50.
print(s.upper()) # THIS IS CS50.

With that example, you might already see how to totally "quiet down" a given string. As for the input(), again, the documentation helps. In the Python interpreter, for example, typing help(input) enlightens you on how to use it.

Playback Speed

This problem wants us to simulate a slower playback, replacing spaces with ... (three dots). What we want to do is to split a given input string into words, and to join them back again with three dots. Or, we can simply replace the space characters with three dots. As with all kinds of problems, there are different ways for a solution. Here, the documentation again is important. We are working with str types again, there are methods named for exactly what we want to do in this case, no matter which method you choose to implement. Simply seek, and you will find them.

Making Faces

With this one, we need to replace any occurrence of :) with the emoji ๐Ÿ™‚ and :( with ๐Ÿ™. One of the most important things to realize here is that the emojis are also str type in this case. What we want to do is, well, literally replace characters of a given string with other characters. Again, consulting the documentation helps with what we exactly want to do.

This problem set also emphasizes the concept of modularity, splitting code into functions. For example, instead of doing everything on a main() function like this:

def main():
incantation = 'Expecto Patronum'
print(f'{incantation.upper()}!')

main() # EXPECTO PATRONUM!
def main():
incantation = 'Expecto Patronum'
print(f'{incantation.upper()}!')

main() # EXPECTO PATRONUM!

There is a slightly better way to do it:

def say_incantation(incantation):
return f'{incantation.upper()}!'

def main():
incantation = 'Expecto Patronum'
print(say_incantation(incantation))

main() # EXPECTO PATRONUM!
def say_incantation(incantation):
return f'{incantation.upper()}!'

def main():
incantation = 'Expecto Patronum'
print(say_incantation(incantation))

main() # EXPECTO PATRONUM!

And similarly in this problem, we have to split the implementation using a convert function to convert emoticons to emojis, and a main function to call convert inside of it.

Einstein

This problem set uses Einstein's mass-energy equivalence formula E = mc^2. For a given mass, we need to output the energy in Joules. c in the formula, is the constant speed of light that is measured approximately as 300000000 (meters per second). The main thing to do is to plug in the variables to their equivalents in the formula, but one thing to remember is how the input function works. Because, in this problem we do not mostly do operations with str types this time, but rather with the int data type. So, for any kind of string in our program, type casting is a helpful thing to do as we only want integers. For example:

# This would not work
year = '2022'
print(year - 22) # TypeError
# This would not work
year = '2022'
print(year - 22) # TypeError
# But this would work
year = int('2022')
print(year - 22) # 2000
# But this would work
year = int('2022')
print(year - 22) # 2000

Perhaps, why the int type is great and not a slight headache like floats can be appreciated more in later problem sets.

Tip Calculator

The last problem is mostly done, only the remaining two functions are waiting for us to be implemented.

What dollars_to_float and percents_to_float expect as inputs are similar in terms of formatting. The first one expects an input like $50.00 and the second one needs an input like 15%, of course, both being strings. Just like in the Einstein problem, type casting is a useful thing to do in this problem. But, before that, we need to get rid of $ (the dollar sign) and % (the percent sign). Realize that what we need to do in the first case is to remove a prefix (leading characters from the left), and in the second case, to remove a suffix (ending characters from the right). There are more than one way to do these things, we can even slice the string ourselves instead of using any built-in method. And, there is really not much to the solution except these. We do not need to think about edge cases yet, as the explanation says that the input values are assumed to be given in expected formats.

I do not want to give away too much, because the crux of these problems is that you should be the investigator. And, I guess the moral of the story for this problem set is a phrase that might sound annoying to some, but it is what it is: read the documentation. Or, simply, look for the thing that you need and learn to find it in the documentation. For the Problem Set 0, looking up built-in str methods, and some type casting would suffice.

We will see what the next problem set will bring.

Until then, happy coding. ๐Ÿ’œ