The bike saga continues

Written by Daniel Veazey on June 9th, 2010

I now know that the combination to my bike lock does not contain both a 1 and a 4. I thought it did, but none of the 302 combinations from my previous program worked. But I haven’t given up hope. Another thing that I seemed to remember was that it had double digits in it somewhere, like 1123 or 4425 or something like that. So I wrote another program to list those combinations. But I didn’t want to list anything that I’ve already tried, so I got a little bit fancier with this program. Also, I put annotated comments in this program. It’s always a good idea to annotate your programs, especially if you’re going to show them to someone else. It makes it easier for the person reading it to understand why you’ve added a particular bit of code. And if you later forget why you wrote a program a certain way, your comments will help you remember. Python ignores anything on a line after a # character, so that is the method for writing comments in your programs. Let’s take a look:

master = [] #create a list of combinations i've already tried in a previous program
for a in range (0, 6):
    for b in range (0, 6):
        for c in range (0, 6):
            for d in range (0, 6):
                combo = str(a+1) + str(b+1) + str(c+1) + str(d+1)
                if "1" in combo and "4" in combo:
                    master.append(combo) #add combinations with both a 1 and a 4 to the master list
possible = 0 #to keep track of the total number of possible combinations that meet the previously mentioned criteria
combo_two = "0000" #to set up a way to prevent counting "double doubles" twice
for a in range (0, 6):
    for b in range (0, 6):
        for c in range (0, 6):
	    for d in range (0, 6):
                combo = str(a+1) + str(b+1) + str(c+1) + str(d+1) #make a string from the values of whichever cycle all four loops are on
                if combo in master: #check to see if this combo has already been tried and added to the master list
                    break
                else:
                    for check in range (0, 3): #set up a loop to compare adjacent digits in combo
                        if combo_two != combo: #only performs the check if this combo hasn't already been counted
                            first = combo[check] #find one digit of combo to compare
                            second = combo[check+1] #find the following digit of combo to compare
                            if first == second:
                                print combo
                                combo_two = combo #this combo has been counted, so combo_two stops it from being checked again
                                possible = possible + 1
print "There are", possible, "possible combinations that have adjacent double digits, but do not contain both a 1 and a 4."
How it works

The first part of the program is very similar to our previous program, combos2.py. But instead of printing out those combinations, we’re adding them to a list called “master.” We first create the empty list with master = []. The brackets are what tell Python we want it to be a list. Then we go through our familiar loops for each digit in the combination. But instead of printing the combinations, we use master.append(combo). Append adds whatever is in the parentheses to our master list. Once it goes through all the loops, we move on to part 2 of the program.

Last time, we counted possible combinations with the variable x. This time, we’re going to be a little more descriptive and name the it “possible.” Being descriptive is another way to make your programs easier to read. We also make a string called combo_two, which we’ll use later to keep the program from counting the same combination more than once.

So we go through the loops again. Each time through, we check to see if combo is already in the master list. If it is, we tell Python to break that loop. Break will interrupt the smallest loop that the program is in at that particular moment. But if the combo we’re working on is not on the master list, then we can go on to the next instructions.

We make a for loop called “check.” Here is where combo_two comes into play. If it is not equal to combo (!= means not equal to), then we do the stuff on the next few lines. But if combo_two is equal to combo, i.e., not meeting the condition of the if statement, then Python skips over the next few lines and goes on back to do another cycle through the four loops that give us a new combo.

Strings

You can reference parts of strings by referring to them like this: Say the string called combo has “2452″ assigned to it. We can find the second character of that string by typing combo[1]. Remember, almost everything in Python begins with position 0, so position 1 is actually the second character in the string. So typing combo[1] would return the character “4.” Typing combo[0] would return “2,” combo[2] would return “5″ and combo[3] would return “2.”

Let’s assume we met the condition of the if statement, meaning that combo_two was not equal to combo. The “check” loop goes from 0 to 3. We’re going to use this loop to compare two adjacent characters in combo. We assign one character of combo to the string “first” by saying first = combo[check]. What’s in the brackets is the position of the string that we want to reference. On the first cycle through the check loop, check has a value of 0, so it’s like saying first = combo[0]. Then we assign the next character in combo to the string called “second” with second = combo[check+1]. So now the string “first” has the one character from the string “combo,” and the string “second” has the following character from combo.

The next line compares first to second. If they’re equal, we print out the combo and add one to the value of possible. Then we make combo_two equal to combo, so when Python goes back around to the next cycle of the check loop, it knows to not perform the checks on the same combo and produce duplicate results. But if the first and second string were not equal, then Python doesn’t print the combo, doesn’t assign combo_two the same value as combo, and repeats the check loop on the next two digits in combo.

So cycle 0 of the check loop compares the first and second digits of combo. Cycle 1 compares the second and third digits, and cycle 2 compares the third and fourth digits. Once it reaches cycle 3, the loop stops because the ending value of a loop is excluded.

Finally, once we have found all the combos that have double digits, but do not contain both a 1 and a 4, we tell Python to print a total to satisfy our curiosity.

Related posts:

  1. Working on the bike problem with Python
  2. Practical programming
  3. timestable.py
  4. Programming with Python
  5. Python, in bitesize chunks
 

Leave a Comment