Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to think like a Computer Scientist exercise

So as the title hopefully suggest, this is for an example in said book. I'm still new to programming and having difficulty debugging. With that said any criticism is welcomed, specially if it shows a more efficient way of coding; just keep in mind that I'm still new so there's a good chance i might not know what you're referring to if you toss me a new built-in function or something.

So the point of this exercise is to write a function, giving it three arguments, to determine if those three arguments form a triangle. Here's my code:

def is_triangle(a,b,c):
    num_list = [a,b,c]
    biggest = max(num_list)
    other_two = num_list.remove(biggest)
    sum_of_two = sum(other_two)

    if sum_of_two > biggest:
        print 'Congrats, %d, %d, and %d form a triangle!' % (a,b,c)
    elif sum_of_two == biggest:
        print 'That forms a degenerate triangle!'
    else:
        print 'That does\'t make any sort triangle... >:['


def sides():
    side1 = raw_input('Please input side numero Juan: ')
    side2 = raw_input('Now side two: ')
    side3 = raw_input('...aaaannnd three: ')
    import time
    time.sleep(1)
    print 'Thanks >:]'
    side1 = int(side1)
    side2 = int(side2)
    side3 = int(side3)
    is_triangle(side1,side2,side3)

sides()

Whenever i run it, however, i get the following:

Traceback (most recent call last):
  File "A:/Python/is_triangle.py", line 27, in <module>
    sides()
  File "A:/Python/is_triangle.py", line 25, in sides
    is_triangle(side1,side2,side3)
  File "A:/Python/is_triangle.py", line 5, in is_triangle
    sum_of_two = sum(other_two)
TypeError: 'NoneType' object is not iterable

My guess is the sum_of_two line but i don't know what's wrong with it. Could someone help me debug this?

I spend a good hour rewriting it with out the built_in function (in various ways, bunch of ors everywhere). But it looked terrible and I'd rather learn to write this way.

like image 582
KOME Avatar asked May 28 '13 04:05

KOME


3 Answers

The problem is the fact that remove modifies the underlying list - it doesn't return a new list. Change it to:

num_list.remove(biggest)
sum_of_two = sum(num_list)

To see exactly why this happens, try the following in IDLE:

>>> x = [1,2,3,4,5]
>>> x.remove(1)
>>> x
[2,3,4,5]
like image 70
Yuushi Avatar answered Nov 08 '22 20:11

Yuushi


Sincenum_list.remove(biggest) returns None, Consider this instead

other1, other2, biggest = sorted(num_list)
sum_of_two = other1 + other2

It looks like the if block needs to be indented too

def is_triangle(a, b, c):
    num_list = [a, b, c]
    other1, other2, biggest = sorted(num_list)
    sum_of_two = other1 + other2

    if sum_of_two > biggest:
        print 'Congrats, %d, %d, and %d form a triangle!' % (a,b,c)
    elif sum_of_two == biggest:
        print 'That forms a degenerate triangle!'
    else:
        print 'That does\'t make any sort triangle... >:['
like image 2
John La Rooy Avatar answered Nov 08 '22 21:11

John La Rooy


You just made a very common mistake, a simple one. In Python, when a function causes a change in a data structure, it does not return the changed structure. Usually it returns None. If the function gets a new data structure or new value, it returns it.

So, str.lower() doesn't actually change a string; it returns a new string where the characters are lower-case. If you have some list named lst and you run sorted(lst), it doesn't change the list; it returns a new list that is sorted. But lst.sort() sorts the list in-place, so it doesn't return a reference to the list; it returns None.

In the comments below, @lvc pointed out that list.pop() removes a value from a list and returns the value. So, this is an example of a function that changes a data structure and returns something other than None, but it still definitely does not return a reference to the changed data structure.

The list.remove() function changes a list, and it returns None. All you need to do is change your function to use the same list for everything: first use the list to find the max, then remove the max value from the list, then pass the list to sum().

The reason Python does things this way is to obey the "Command/Query Separation" principle.

http://en.wikipedia.org/wiki/Command%E2%80%93query_separation

like image 2
steveha Avatar answered Nov 08 '22 22:11

steveha