Programing Challenge - Building a Calendar

Building a Calendar - Note: This code is Python 2.7

(extra Credit if yo fix this code to work in Python3)

Programing Challenge  -
Let's write a program in Python to do the same thing. We'll start with this simple program that asks the user of the program for the values for n and d, and then prints out the values from 1 to n using a loop:
def main():
        n = input("Input the number of days in the month (28-31): ")
        d = input("Input the starting day (0=Sun, 1=Mon,...): ")
        i = 1
        while i <= n:
                print i
                i = i + 1

main()
 
Here's the output for n = 30 and d = 4:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
This certainly has all the right numbers, but doesn't look like a calendar. We need numbers to go across as well, so we might change the program, adding an extra comma at the end of the print statement so the cursor stays on the same line for the next number:

def main():
 n = input("Input the number of days in the month (28-31): ")
 d = input("Input the starting day (0=Sun, 1=Mon,...): ")
 i = 1
 while i <= n:
  print i,
  i = i + 1

main()
 
Here's the output now, when n = 30 and d = 4:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

Now we need to move the cursor to the next line whenever we get to the end of a week. In the algorithm, we had a test that said to compute (i+d) modulo 7 to see if it is equal to 0. If it is, then we move to the next row of the calendar. We can do this with an if statement in Python:

def main():
 n = input("Input the number of days in the month (28-31): ")
 d = input("Input the starting day (0=Sun, 1=Mon,...): ")
 i = 1
 while i <= n:
  print i,
  if (i+d) % 7 == 0:
   print " "
  i = i + 1

main()
 
The if statement looks like the while statement but it doesn't loop. It tests the given condition, and if it is valid, we execute the instruction(s) that is(are) indented below the if statement. In this case, the instruction that is indented is a print statement that prints a single space. Note that there is no comma at the end of that line, so once the space is printed, the cursor will move to the next line. Also, in the condition for the if statement, we must put parentheses around i+d since we want to compute that first before we perform the modulo operation. The modulo operation normally has higher precedence than addition, just like multiplication and division does. Finally, note that we use a double equals sign ==, not a single equals sign =, since we want to test for equality, not do an assignment operation.
Here's the output now for n = 30 and d = 4:

1 2 3  
4 5 6 7 8 9 10  
11 12 13 14 15 16 17  
18 19 20 21 22 23 24  
25 26 27 28 29 30 
One problem we see is that some dates have one digit and some have two. This causes the numbers not to line up nicely. We can fix that by printing an additional space if the number is less than 10:

def main():
 n = input("Input the number of days in the month (28-31): ")
 d = input("Input the starting day (0=Sun, 1=Mon,...): ")
 i = 1
 while i <= n:
  if i < 10:
   print "", i,
  else:
   print i,
  if (i+d) % 7 == 0:
   print " "
  i = i + 1

main()
 
First, we used a new version of the if statement which we call the if-else statement. It allows us to specify what to do if the condition is valid and what to do if the condition is not valid (else). In this case, if i is less than 10, it has only one digit so we need to print an extra space before we print the value of i. Otherwise (else), we print the value of i as we did before. A quirk of Python is that when you print anything and leave the cursor on the same line, an extra space is also output. This space separates the output data from any subsequent data that is output on the same line. If we want an extra space before a single digit number, we can output an empty string "" which doesn't output anything but causes an extra space to be output, just as with any other output. An empty string is a string that just doesn't contain anything, including spaces.

Here's the output now for n = 30 and d = 4:

 1  2  3  
 4  5  6  7  8  9 10  
11 12 13 14 15 16 17  
18 19 20 21 22 23 24  
25 26 27 28 29 30
 
We're almost there. As we see above, the first three numbers didn't start in the correct position. The value of d tells us how many columns we have to skip to get to the correct starting position for the first row of the calendar. Each column contains two characters (two digits, or a space and a digit) so we need to print out d copies of " " before we print out the first number. Here's the revised program to do this:

def main():
 n = input("Input the number of days in the month (28-31): ")
 d = input("Input the starting day (0=Sun, 1=Mon,...): ")
 for j in range(d):
  print "  ", 
 i = 1
 while i <= n:
  if i < 10:
   print "", i,
  else:
   print i,
  if (i+d) % 7 == 0:
   print " "
  i = i + 1

main()
 
Recall that the for instruction sets up a loop that repeats the number of times given in the range value. So this loop repeats d times, printing two spaces each time. (Of course, after the first output, every subsequent output gets an additional space due to the Python quirk described above.) If the user enters 0 for the value of d, then the for loops runs 0 times, i.e. it is skipped.
Here's the output now for n = 30 and d = 4:
             1  2  3  
 4  5  6  7  8  9 10  
11 12 13 14 15 16 17  
18 19 20 21 22 23 24  
25 26 27 28 29 30
Finally, we have a valid calendar for a month that has 30 days (n=4) that starts on Thursday (d=4). Try the program for other valid values of n and d to see that it works correctly.

PRACTICE EXERCISES

  1. Modify the program so it outputs a calendar for a society that has 8 days per week

No comments:

Post a Comment