The Locker Problem

Problem Statement

There are lots of ways to explore this problem, and we encourage you to spend some time thinking about it on your own. Below, we are going to give you some tools to explore this problem with programming.

We've created a Locker object that will let you simulate this problem. Each locker has 4 properties:

  • id: the locker number)
  • isOpen: a boolean indicating whether the locker is open
  • flipCount: an integer for keeping track of the numebr of times the locker was openened
  • students: a list of all of the students who open or closed the locker
In [12]:
from Locker import Locker

Let's create a locker. When we create a locker, it will be initialized with an id of 1, flipCount of 0, and closed.

In [13]:
locker1 = Locker()

We can "flip" the state of the locker with the flip() funciton. This function requires you also pass it a number indicitating the number of the studnet who "flipped" the locker. In this case, we will assume student 1 flips the locker.

In [14]:
locker1.flip(1)

We can see the status of the locker using the status() function.

In [15]:
print(locker1.status())
11: open: 1 [1]

The status function outputs the number of the locker, followed by its open status, followed by the number of times it has been openend and the list of students who opened it.

Let's delete the locker we created. Python automatically numbers each new locker sequentially, so if we want to create a new locker starting with 1, we need to call the reset function.

To create an entire set of lockers, we can use a for loop. This command would create 10 lockers, for example.

In [27]:
locker1.reset() #re-initialize counter to start at 1
Lockers=[]  #create an empty array to store our lockers
for i in range(10): #repeat 10 times
    l = Locker() #create a locker
    Lockers.append(l) #add l to our list of lockers

We can use a similar loop to print the status of our collection of locekrs:

In [28]:
for l in Lockers:
    print(l.status())
1: closed: 0 []
2: closed: 0 []
3: closed: 0 []
4: closed: 0 []
5: closed: 0 []
6: closed: 0 []
7: closed: 0 []
8: closed: 0 []
9: closed: 0 []
10: closed: 0 []

Now you have a set of lockers that you can begin to experiment with. Using your knowledge of iteration (for loops) and conditionals (if statements), let's see how you can model this problem.

Let's start by just trying to open every locker, using our first student. You'll need a loop to loop over every locker. When we are done, we can go ahead and print the status of the lockers, too.

In [18]:
for l in Lockers:
    l.flip(1) #student 1 flips locker l
In [19]:
for l in Lockers:
    print(l.status())
1: open: 1 [1]
2: open: 1 [1]
3: open: 1 [1]
4: open: 1 [1]
5: open: 1 [1]
6: open: 1 [1]
7: open: 1 [1]
8: open: 1 [1]
9: open: 1 [1]
10: open: 1 [1]

Later students should not flip every single locker, they should only flip lockers that have numbers that are multiples of that student's number. This will require you to use a conditional statement. One easy way to test if a number is a multiple of another number is to use the mod operator, %, which gives you the remainder when the first argument is divided by the second argument. See this example.

In [21]:
print (9 % 3) #9 is a multiple of 3
print (9 % 2) #9 is not a multiple of 2
print (137 % 40) #140 is not a multiple of 40
0
1
17

How can you use this argument to build a test for a conditional (if statement) that will be true when the first argument is a multiple of the second? Here's a small example get you started—here's a way to have the computer test if 2+4 is equal to 5.

In [24]:
print 2 + 4 == 5
False

Build the algorithm

Use the ideas above to build an algorithm that will simulate the first 10 students flipping the first 10 lockers as described in the problem above.

In [ ]:
 

Here's an example of what successful output might look like:

In [ ]:
1: open: 1 [1]
2: closed: 2 [1, 2]
3: closed: 2 [1, 3]
4: open: 3 [1, 2, 4]
5: closed: 2 [1, 5]
6: closed: 4 [1, 2, 3, 6]
7: closed: 2 [1, 7]
8: closed: 4 [1, 2, 4, 8]
9: open: 3 [1, 3, 9]
10: closed: 4 [1, 2, 5, 10]

Your turn to explore

Take some time to explore this problem further on your own. You might start by trying to modify your code to create a set of 200 lockers, and then simulate 200 students flipping them according to the problem. What patterns do you see? Can you predict the status of locker 123, without running all of this code? If you're interested in seeing a visual representation of this, you might check out this [Wolfram Alpha project](https://demonstrations.wolfram.com/TheLockerProblem/). Could you write a function that would give the status of a given locker without needing to actually simulate all of the students opening and closing the lockers? Can you create a function that will report the number of students who changed the state of a locker? What happens if you change the conditions of this problem? What happens if one student, e.g. student 12, doesn't change the state of any lockers? What variations can you think of?
In [ ]: