mikeizbicki / cmc-csci046

CMC's Data Structures and Algorithms Course Materials
55 stars 155 forks source link

Ladders correct but 1 word longer than they are supposed to be in select test cases #472

Closed NACB closed 1 year ago

NACB commented 1 year ago
(Initially posted on assignment, but realized I should post here for visibility)

My program is passing all tests except for test__word_ladder_ 7, 8, 9, 10 and fuzz. On each, the output of the program is a valid word ladder, it is just 1 word too long. See, for example, the test below:

_____________________________ test__word_ladder_7 ______________________________

    def test__word_ladder_7():
        ladder = word_ladder('babes','child')
>       assert verify_word_ladder(ladder) and len(ladder)==9
E       AssertionError: assert (True and 10 == 9)
E        +  where True = verify_word_ladder(['babes', 'banes', 'wanes', 'wants', 'waits', 'whits', ...])
E        +  and   10 = len(['babes', 'banes', 'wanes', 'wants', 'waits', 'whits', ...])

tests/test_main.py:137: AssertionError
----------------------------- Captured stdout call -----------------------------
working_stack= ['babes', 'banes', 'wanes', 'wants', 'waits', 'whits', 'white', 'while', 'chile', 'child']

As you can see from the captured print statement, the working_stack output is a valid word ladder, but it is 10 words long where the test case wants len(ladder) == 9. Notably this happens ins some but not all tests. What should I be checking for to fix this?

mikeizbicki commented 1 year ago

There's very likely a memory management issue going on. The following code illustrates the problem:

xs = [1, 2, 3, 4, 5]
for x in xs:
    print('x=', x)
    xs.remove(x)

(Go ahead and run this code. You should see that it does something you don't expect.)

The key problem in the code above is that you're removing from a list that you're iterating over at the same time. This causes you to "skip" some of the values.

This is likely happening in your word_vector function. When you are iterating over the dictionary, you are removing values from the dictionary, which causes you to skip some of the words that are needed for the word ladder.

The fix is that you should never iterate over a list that you are also modifying. Instead, you probably should be iterating over a copy of the list. Something like:

xs = [1, 2, 3, 4, 5]
for x in xs[:]:
    print('x=', x)
    xs.remove(x)

Notice the very subtle difference between these two segments of code.

NACB commented 1 year ago

@mikeizbicki

Sure enough, that was the problem. Thanks for the insight, Mike!