View Single Post
Old 2020-01-12, 01:44   #17
Dylan14's Avatar
Mar 2017

22×3×72 Posts
Default Putting it all together

Now that we have learned about if, else, elif, for and while, we can go on and try to work with all of these to build programs. We'll do a few examples, one of which is an OEIS sequence.

Example: OEIS A003599:

OEIS A003599 lists all numbers of the form 7^i*11^j for i and j non negative. The terms are given as 1, 7, 11, 49, 77, 121, etc., corresponding to the (i, j) values of (0,0), (1,0), (0,1), (2,0), (1,1), (2, 0), respectively. The listings goes up to 5764801, which is 7^8*11^0. Now, how can we code this?
1. We need two variables, i and j. They should both start at 0.
2. Since the limit of the sequence shown on the page is 5764801 (*), we should limit ourselves to, say, 6000000.
So we could first use a for loop to loop over i, and then while we are under the limit, we print i, j, and the resulting number.
So let's code it.
First, we should define a function to compute the numbers:
def numform(i, j):
     #computes 7^i*11^j
     return (7**i)*(11**j)
Next, we develop the main loop: we iterate over i in a for loop, and then we test if 7^i*11^j is smaller than our bound. If it is, we then print the tuple (i, j), and the resulting number, and then we increment j. Otherwise, we set j = 0, and increment i. This is coded as follows:
j = 0
for i in range(0,11): #test all i's from 0 to 10
  #if 7^i*11^j is smaller than a certain bound (namely, 6000000), print i, j and the resulting number
  while numform(i,j) <= 6000000:
    print("(" + str(i) + ", " + str(j) + "), " + str(numform(i,j)))
    j += 1
    j = 0
When we do this, we get the following output:
(0, 0), 1
(0, 1), 11
(0, 2), 121
(0, 3), 1331
(0, 4), 14641
(0, 5), 161051
(0, 6), 1771561
(1, 0), 7
(1, 1), 77
(1, 2), 847
(1, 3), 9317
(1, 4), 102487
(1, 5), 1127357
which does correspond to the entries in A003599.
By changing the appropriate things in the code, you can recreate the following sequences in OEIS: A003591-A003599. I'll leave it as an exercise to do that.

Using else in for and while loops:

In our code for A003599, we used else after a while loop, which we would usually use after an if statement. But we were able to use else after a while loop, within a for loop in Python. This is actually unique to Python. The following happens when you use else with a loop:
* If else follows after a for loop, then the code that is in the else block runs once the code exhausts the iterable object that the for loop is operating on.
* If else follows after a while loop, then the code that is in the else block runs once the condition that governs the while loop becomes false.
To see this in action, let's go back to the code we wrote for A003599. With the code that we used and the bounds that we set, we get results all the way up to i = 8. If, instead, we excluded the else block, we get the following output:

(0, 0), 1
(0, 1), 11
(0, 2), 121
(0, 3), 1331
(0, 4), 14641
(0, 5), 161051
(0, 6), 1771561
so we only get the lines with i = 0, as then j is not reduced afterwards from 7. Then, clearly 11^7 = 19487171 is larger than our bound of 6000000, so we increment i. But when we increment i, we will get an even bigger number. So we never get another number that is smaller than our bound, so the output stops.

Example: Logging in (**)

Many websites require you to log in in order to get use all the functionality of the site. Such logins usually involve a username and a password (and occasionally some two factor authentication). Sometimes sites (like Mersenneforum) will only allow you to try x number of times before locking you out for a short period of time. How can we implement this?
1. We set up a password (here we will use a plain string). Usually, it is encrypted and salted on the server. However this is beyond the scope of this section.
2. While we have not exceeded the number of attempts, we ask the user to supply the password.
3. If it is correct, then we break out of the loop.
4. If it is incorrect, then we tell the user "wrong password, try again", and increment the attempts by 1.
5. If the maximum number of attempts have been made, then we lock the user out (here we'll just print a message).
Here's the code:
#Passwords and logging in
password = "passw0rd"
i = 1
while i <= 3: #3 attempts
  #ask for input
  inputtedpassword = input("Enter your password: ")
  if inputtedpassword == password:
    #log in
    print("Logging in...")
    #warn user, ask them to try again
    print("Wrong password, try again")
    i += 1
  #lock user out
  print("You have been locked out. Try again later")
This does work, but I would advise not using this code for your website. It is meant to be a proof of concept (***)

(*) The b-file goes a lot higher than this, but we want to just recreate the terms on the main sequence page.
(**) This checks against a plain string, which is in the code. Needless to say, you should NEVER have passwords in plain sight (for obvious reasons).
(***) Python does have a getpass module, which enables the password to be hidden when typing it in. That is the least of my concerns with using this (see point (**) above).
Dylan14 is offline