0

What is wrong with this program? When I compile it, one of the lists, named "single_bovines" keeps being appended to, even though there are no commands telling anything to be appended to it. The lines that end with a #debug line are lines that I put in trying to debug the program.

class Cow(object):
        def __init__(self, height, weight, strength):
                self.height = height
        self.weight = weight
        self.strength = strength
class Combination(object):
    def __init__(self, cows):
        self.cows = cows
        self.evaluated_flag = False
        self.satisfied_height = False
        self.satisfied_strength = False
        self.safety_factor = None

    def evaluate(self, mark_height):
        if sum(map(lambda c: c.height, self.cows)) >= mark_height:
            self.satisfied_height = True

        self.satisfied_strength = True
        for i, cow in enumerate(self.cows):
            if sum(map(lambda c: c.weight, self.cows[i+1:])) > cow.strength:
                self.satisfied_strength = False
                break

        if self.satisfied_height and self.satisfied_strength:
            self.safety_factor = 999999
            for i, cow in enumerate(self.cows):
                self.safety_factor = min(cow.strength - sum(map(lambda c: c.weight, self.cows[i+1:])), self.safety_factor)

        return self.satisfied_height, self.satisfied_strength

    def get_safety_factor(self):
        return self.safety_factor


file = open('guardmark.in', 'r').readlines()
number_of_cows, mark_height = map(lambda item: int(item), file[0].rstrip('\n').split(' '))
consideration_list = []
for line in file[1:]:
    height, weight, strength = map(lambda item: int(item), line.rstrip('\n').split(' '))
    consideration_list.append(Combination([Cow(height, weight, strength)]))
single_bovines = consideration_list
complete_list = []
consideration_done = True

while filter(lambda c: c.evaluated_flag == False, consideration_list):
    for combo in consideration_list:
        print "a combo" #debug line
        height_flag, strength_flag = combo.evaluate(mark_height)
        if height_flag and strength_flag:
            combo.evaluated_flag = True
            complete_list.append(combo)
        if not strength_flag:
            combo.evaluated_flag = True
        if strength_flag and not height_flag:
            combo.evaluated_flag = True
            print "put into consideration" #debug line
            for single_cow in single_bovines:
                print "a cow" , len(single_bovines)#debug line
                if single_cow not in combo.cows:
                    combo_cows_copy = combo.cows
                    combo_cows_copy.append(single_cow)
                    consideration_list.append(Combination(combo_cows_copy))
if not complete_list:
    print "Mark is too tall"
else:
    safety_factors = []
    for combo in complete_list:
        safety_factors.append(combo.get_safety_factor())
    print max(safety_factors)
Songman Yi
  • 13
  • 4
  • Could you shorten your example code? It'd be nice if you could remove the parts not directly related to the problem at hand. (This isn't just helpful to us, it's also a good debugging technique to isolate the problem.) – John Kugelman Jan 31 '15 at 23:35
  • 2
    I think the problem might be that you do `single_bovines = consideration_list`, which means both variable names refer to the *same* list. If you want two different lists (that both have the same contents), use `single_bovines = list(consideration_list)` or `single_bovines = consideration_list.copy()` or `single_bovines = consideration_list[:]`. – Tom Dalton Jan 31 '15 at 23:35
  • possible duplicate of [Python modifying wrong list?](http://stackoverflow.com/questions/4337106/python-modifying-wrong-list) – Fiver Jan 31 '15 at 23:44
  • @JohnKugelman you're right, I just didn't bother to check that was actually the problem so didn't want to post an incorrect answer. But I think it's a safe guess :-) – Tom Dalton Jan 31 '15 at 23:55

2 Answers2

5

I think the problem might be that you do

single_bovines = consideration_list

... which means both variable names refer to the same list. If you want two different lists (that both have the same contents), use any of:

single_bovines = list(consideration_list)
single_bovines = consideration_list.copy()
single_bovines = consideration_list[:]

All 3 of those will copy the contents of the original list into a new list.

Tom Dalton
  • 6,122
  • 24
  • 35
0

See answer here How to clone or copy a list? I suspect that since you do not make a proper copy of consideration_list any further appends to it are appends to single_bovines.

Community
  • 1
  • 1
sturgman
  • 257
  • 2
  • 8