This worksheet covers some initial setup and installation of software, followed by some coding exercises that use material from prerequisite courses.
No solutions are needed for this part, as it asked you to complete tasks rather than solve problems.
This section gives a series of exercises in which you'll write programs that are based on things you are expected to have seen in a prerequisite course. We'll talk about these in Lectures 2-3 as well, and the first quiz will cover the same kind of review material.
These start very easy and build up.
Create a simple program squares.py
that prints the squares of the first 10 positive integers, so its output should look like
1
4
9
...
100
Then, add a feature to this program where it accepts an optional command line argument which is the largest integer whose square should be printed (while 10 remains the default if no argument is given). Recall that command line arguments appear in the list sys.argv
which is accessible after you import the sys
module, and the items in this list are strings. So sys.argv[1]
would be a string containing the first word or number on the command line after the name of the script.
Thus, for example, if you run the modified script as
python3 squares.py 3
then it would be expected to produce the output
1
4
9
import sys
if len(sys.argv) == 1:
#use default length of 10
max_len = 10
else:
#use first argument as length
max_len = int(sys.argv[1])
#print the squares
for i in range(1,max_len+1):
print(i**2)
Now that you've written a simple program from scratch, and have a full Python setup working, it's time to get acquainted with some code style rules.
All code you submit for credit needs to follow the rules described in the
These rules enforce good coding practices and ensure your programs are readable to both humans and computers.
Read the list of rules now. If any of the rules seem unclear on a first reading, check the section later in the document that gives examples of compliant and non-compliant code for that rule.
Then, take the program below (which works!) and fix it so that it does the same thing but complies with the MCS 275 rules. (Note: The rules say you need to add a declaration stating that the program is your own work, or that it is derived solely from a template provided by the instructor. That's because all graded work in MCS 275 is done individually. Since this is a worksheet, collaboration is allowed and if you work with others you should instead list your collaborators.)
# I am a program that doesn't follow MCS 275 coding guidelines
# Please fix me.
def thing(x):
return "{} is one greater than {}".format(x,x-1)
def thing2(x):
return "{} is one less than {}".format(x,x+1)
s = str(input("Please enter your name"))
print("Hello",s,", this is a sample Python program.")
ss = list(range(5))
sss = [ x+5 for x in ss ]
ssss = [ 10*x for x in sss ]
for i in range(len(ssss)):
sssss = 'Some things that are true:\n' + thing(ssss[i]) + "\n" + thing2(ssss[i]) + '\n\n'
print(sssss)
The following modifications were made to update the code to course standards
#MCS 275 Spring 2024 Worksheet 1
#Patrick Ward
#Code copied from worksheet and modified
def onegreater(x):
"given an integer, output a sentence which says x is one greater than x-1"
return "{} is one greater than {}".format(x,x-1)
def oneless(x):
"given an integer, output a sentence which says x is one less than x+1"
return "{} is one less than {}".format(x,x+1)
#gather the user's name and print a sentence which their name
name = input("Please enter your name")
print("Hello",name,", this is a sample Python program.")
#create a list of numbers
numbers = [10*(x+5) for x in range(5)]
for i in numbers:
sentence = 'Some things that are true:\n' + onegreater(i) + "\n" + oneless(i) + '\n\n'
print(sentence)
One of the nice things about Python is that strings can contain any Unicode character (as opposed to strings in some other programming languages where the set of available characters is much more limited).
Some Unicode characters are made for drawing "text graphics" boxes, like this:
╔══════════╗
║ Look, ║
║ a box! ║
╚══════════╝
The box drawing characters used above are:
\u2550
or ═
\u2551
or ║
\u2554
or ╔
\u2557
or ╗
\u255a
or ╚
\u255d
or ╝
Write a program box.py
that prints a unicode text box of specified width and height. It should expect at least two command line arguments, giving the width and height of the box. If only those are given, the box should be printed to the screen. If a third argument is given, it should be a filename and the box should be written to that text file instead of being printed to the screen.
So, for example, the command
python box.py 3 4
should result the following text being printed, exactly:
╔═╗
║ ║
║ ║
╚═╝
(This box has a width of 3 characters and a height of 4 lines). Similarly, the command
python box.py 12 2 box.txt
should not print anything to the screen, but should result in a file box.txt
being created that contains the following text, exactly:
╔══════════╗
╚══════════╝
Recommended structure of your program:
There are at most three different lines of text that appear in a box: The top of the box, the line that repeats some number of times to make the vertical sides of the box, and the bottom of the box.
I suggest you generate these three lines and store them in strings, and then assemble them into one bigger string that has all the lines and line breaks (\n
characters) that you need.
To generate the strings, you can use the fact that multiplication of a string by an integer will repeat the string a certain number of times. For example, "foo"*3
evaluates to "foofoofoo"
.
It would be a good idea to put the part of the program that writes the box to a file into a function and have the rest of the program create a string that contains the box. Then you can decide whether to print the string or call the function to write it to a file based on whether there is a third command line argument.
import sys
#read the inputs
length = int(sys.argv[1])
height = int(sys.argv[2])
#create the top, middle and bottom lines of the box
top = "\u2554"+"\u2550"*(length-2)+"\u2557"
mid = "\u2551"+" "*(length-2)+"\u2551"
bottom = "\u255a"+"\u2550"*(length-2)+"\u255d"
#create the box
box = top + ("\n" + mid)*(height-2) + "\n" + bottom
if len(sys.argv) == 3:
#no filename is given, print box
print(box)
else:
#write box to the filename given as third argument
f = open(sys.argv[3], "w", encoding="UTF-8") #encoding allows writing the unicode to the text file
f.write(box+"\n")
f.close()
Work on this more challenging exercise if you finish the rest of the worksheet before discussion ends. The solutions to the worksheet won't include solutions for the bonus problem, but it's still good practice!
Consider this process: Start with a positive integer like
2781
Write out each digit as an english word:
two, seven, eight, one
Then replace each word with its number of letters (e.g. "two" has 3 letters, "seven" as 5, etc.):
3 5 5 3
Use these numbers as digits of a new integer
3553
Finally, take the average of the new integer and the old one, and if the result is not an integer, round it down to the nearest integer:
(2781 + 3553) // 2 = 3167 (no rounding happened in this case)
(Why are there two slashes there? That's how you perform integer division.)
Write a Python function dwl(n)
that takes an integer n
and returns the integer that results from this process. So, for example we have:
dwl(2781)
Now, consider what happens when you apply this function over and over again, e.g. start with n
, compute dwl(n)
, then dwl(dwl(n))
, then dwl(dwl(dwl(n)))
, etc., to get a sequence. For 2781
this sequence looks
like:
2781, 3167, 4251, 4297, 4321, 4427, 4431, 4442, 4442, 4442, 4442, ...
It continues with 4442
repeating forever.
That's what happened when starting with 2781
, but what happens when you do the same thing but start with a different value of n
, like 7847
? Does it always seem to end up repeating some number over and over again?
Write a program to explore this more systematically, for example by searching for a repeating pattern (or lack thereof) for every 4-digit starting number.
#define a dictionary to convert a digit to its spelling
num2words1 = {0: 'Zero', 1: 'One', 2: 'Two', 3: 'Three', 4: 'Four', 5: 'Five', 6: 'Six', 7: 'Seven', 8: 'Eight', 9: 'Nine'}
def dwl(n):
"takes and integer and outputs the average of the original integer and an integer based on word lengths"
#write out digits and replace each word with the length of the word
numlist = [int(d) for d in str(n)]
#create a new number with the lengths
newnum = int("".join([str(len(num2words1[d])) for d in numlist]))
# alternative way to compute newnum, same output
#newnum = sum(len(num2words1[d]) * 10**i for i, d in enumerate(numlist[::-1]))
avg = (newnum + n) // 2
return avg
def findpattern(n):
"takes an integer and returns the pattern from applying dwl() many times"
visited = [n]
next = dwl(n)
while next not in visited:
visited.append(next)
next = dwl(next)
visited.append(next)
return visited
#to avoid too much text in the solutions document, let's only check multiples of 500
check_start = 1000
check_end = 9999
check_step = 500
#uncomment these to check all 4-digit numbers
#check_start = 1000
#check_end = 9999
#check_step = 1
for k in range(check_start,check_end+1,check_step):
print("Applying dwl to {} reaches a repeating pattern after {} steps".format(k,len(findpattern(k))))