Stacks project bug

Towers of Hanoi - Stacks Project

i finished the project but for some reason when i want to move one data (in this case disk) to another stack i get the error message doesn’t matter if i’m trying to get data from an empty stack i get the message at Line 57, L-M-R doesn’t matter which one, after that Line 59 again L-M-R then error message (Line 73) this goes on forever until i input another letter how do i solve this?

1 Like

Hi @mryasincengiz,

In the get_input function, you have …

    if user_input in choices: 
      for i in range(len(stacks)):
        return stacks[i]

During the first iteration of the for loop, it will always return the item at index 0, which is left_stack, and that creates an infinite input loop.

Prior to the return statement, you need to check whether the iteration has reached the Stack that corresponds to user_input, by performing this test …

        if user_input == choices[i]:

If the condition is True, the return will execute.

2 Likes

Thank you for your help, i looked at the project walkthrough video but for some reason it didn’t have the if statement.

1 Like
for i in range(len(stacks)):
  name = stacks[i].get_name()
  letter = choices[i]

Iterating over indexes is … rarely the right thing to do

Turn it into a dictionary of {char: name} instead, and then you can do:

for letter, name in choices.items()
  print("Enter {0} for {1}".format(letter, name))

And:

if user_input in choices:
  return choices[user_input]

If you ever have two lists of something that you need to sync up like this, the right thing to do is probably to put them as pairs in a single list, or in this case a dict since you do lookup from one to the other

2 Likes

@ionatan is correct. The solution that is promoted by the instructions and the video is not as efficient as using a dictionary would be.

1 Like

Ahh but it’s like 3 pegs. Doesn’t matter!

However, I can’t read anything with indexes in it. So I assume other people can’t either.

“all of these” compared to [the math that describes all of these]

Efficient with regard to amount of mental power required to understand it I guess

Speaking of which:

class Stack:

They mean list, right. Plain list. whatisthatwholefileevendoing

1 Like

Not much gain here in terms of efficiency, but in preparation for situations where we have larger collections of objects, why not promote the mindset of favoring dictionary lookups over linear searches when it is possible?

I didn’t really like the solution promoted by the instructions.

1 Like

It’s not a linear search though, we know there are three pegs! It’s constant time :smile:

1 Like

They have the user do this …

    if user_input in choices:
      for i in range(len(stacks)):
        if user_input == choices[i]:
          return stacks[i]

With only three pegs, it’s not a big deal, but conceptually it’s kind of ugly to have the player pick an item from a list and then to have the program start looking for it from the beginning of the list.

1 Like

Abstraction-wise it’s more than we want to care about and therefore we want a dict, yeah, absolutely.
Scaling-wise they’re both the right thing.

1 Like

I cleaned up codecademy’s solution a little bit. Got rid of stack.py because it’s just a list

def show_input_options(choices):
    for name in choices:
        print("Enter {} for {}".format(name[0], name))


def get_input(prompt):
    choices = ['Left', 'Middle', 'Right']
    letterToStack = dict(zip('lmr', stacks))
    while True:
        show_input_options(choices)
        user_input = input(prompt)
        if user_input.lower() in letterToStack:
            return letterToStack[user_input]


print("\nLet's play Towers of Hanoi!!")

stacks = [[], [], []]
num_disks = int(input("\nHow many disks do you want to play with?\n"))
while num_disks < 3:
    num_disks = int(input("Enter a number greater than or equal to 3\n"))
stacks[0] = list(range(num_disks, 0, -1))

num_optimal_moves = (2**num_disks) - 1
print("\nThe fastest you can solve this game is in {0} moves"
      .format(num_optimal_moves))


num_user_moves = 0
while len(stacks[-1]) != num_disks:
    while True:
        print("\n\n\n...Current Stacks...")
        for stack in stacks:
            print(stack)
        from_stack = get_input("\nWhich stack do you want to move from?\n> ")
        to_stack = get_input("\nWhich stack do you want to move to?\n> ")
        if not from_stack:
            print("\n\nInvalid Move. Try Again")
        elif len(to_stack) == 0 or from_stack[-1] < to_stack[-1]:
            disk = from_stack.pop()
            to_stack.append(disk)
            num_user_moves += 1
            break
        else:
            print("\n\nInvalid Move. Try Again")


print(
    "\n\nYou completed the game in {0}"
    " moves, and the optimal number of moves is {1}"
    .format(num_user_moves, num_optimal_moves)
)
1 Like

The Stack.py file is a carryover from the Stacks: Python course that the user has just completed, so it is an artifact of the educational sequence.

1 Like

Well. It makes me unhappy. Because it doesn’t help.
And when something doesn’t help it’s difficult to understand what is being done.

In my somewhat cleaned up version most of the things need to be there (unless one starts getting clever)
And, hey, lists are stacks.

It’s a pretty good argument for not using dict though - to only use very basic elements.

1 Like

I was thinking recently about whether Python is too high level as a first language, or if perhaps it’s arbitrary where one starts. There’s always a lower level.

This is a case of the language being higher level than the ideas implemented. I can’t figure out if that makes sense or not.

1 Like

The issue of one’s first programming language is an interesting one. What’s best may vary with the person’s age and learning style. My first programming language was PL/I when I was 31 years old. It was OK, and did get me interested in programming. If I could do it all over again I would probably choose to start at a very early age with turtle graphics or some other sort of drawing program. The first time that one of my early teachers drew a coordinate grid on the chalkboard and started plotting shapes on it, I immediately took great interest in it. I would have really appreciated a system that enabled me to implement algorithms on such a grid.

I think it’s OK for one’s first programming language to be at a higher level than the ideas implemented, so long it offers pretty straightforward means of working with the early concepts that are taught.

We may be getting off topic. Should we split this into a new discussion?

1 Like

I am somewhat unsettled regarding what the instructions should ask the user to do here. Perhaps, since we only have three Stack objects, making efficiency a trivial issue, we should just leave things as they are, with the user keeping a list of them instead of a dictionary. With Codecademy’s current offerings, users might feel more comfortable with implementing a list than a dictionary

In its content offerings, Codecademy teaches about lists before teaching about dictionaries. This is probably true of nearly all courses in Python. A list is simpler in that it is just a sequence of items, while a dictionary consists of key-value pairs. But, in real life, what is a more fundamental concept, a dictionary (a mapping) or a list?

We could argue that a list is the more fundamental of the two. On paper, we go to the store with a list of items to buy, rather than with a dictionary of items. However, in reality, we are going there with a mapping. Each of the items on the list must have a meaning before we would have any reason to write it on the list. So, for each item, the key is what is written on the paper list, and the value associated with each key is in our head, or we might say that the value is the actual item on the shelf. Early on in life, we start work with symbols, each of which is a key to something else. As soon as we start to use language, we are using a mapping.

Although the Python content here teaches lists prior to dictionaries, it teaches about variables before teaching about lists. Each variable has a name and a value. That is a key-value pair. So, while in name, lists are taught before dictionaries, we actually start working with mappings almost immediately. Perhaps the concept of a mapping should be discussed explicitly earlier in the lessons. Then users, as well as the authors of the content, might find it more comfortable to make greater use dictionaries in the later content, the current project included.

Funny, they actually use many dicts to create that Stack class (instance variables of an object are by default backed by a dict)

In fact, in a similar respect, some of the coursework uses dictionaries to create dictionaries, which they refer to by the general term, hash maps. As with the Stack class, when they have the user create a HashMap class, its instance variables are supported by a dictionary. This seeming circularity is acceptable, because they are not having the user explicitly use a Python dict to create the HashMap class. The coursework is just a mechanism for teaching how hash maps work, so what is under the hood doesn’t matter so much, except that the authors of the material should, perhaps, have brought that up and used it as an opportunity to discuss how essential hash maps, as dictionaries, are for the inner workings of Python itself.

Here are some links to the material on hash maps …

They do mention in the exercise Creating the Hash Map Class that …

Python offers a built-in hash table implementation with dictionaries.

… and that might be a good place for them to add discussion about some of the roles that dictionaries play in the inner workings of Python.