Hendrik
Hendrik

Reputation: 47

Get code to stop adding a list to another list, if the sum of it already exists

I am new to programming in general and am trying to do the "Goldbach Theorie" in Python, that every number between 3 and a given number (in my case 50.)

lijst2 = []
for n in lijst:
    j = 2*n+1
    lijst2.append(j)


priemgetallen = [2]
counter = 2
x = 2
while len(priemgetallen)<50:
    priemgetallendelers = []
    for i in range (1,counter+1):
        if counter % i == 0:
            priemgetallendelers.append(i)
    if len(priemgetallendelers) == 2:
        priemgetallen.append(counter)
        counter += 1
    else:
        counter +=1

The code above is unimportant for my problem and is only there to make it easier to understand what I am trying to do.

while not len(sommen) == len(lijst2):
    for i in lijst2:
        for j in priemgetallen:
            for r in priemgetallen:
                for t in priemgetallen:
                    if i == j+r+t:

Here I am trying to say that if a number in my original list, is made up out of the sum of three prime numbers, add it to the list.

                        sommen2 = []
                        sommen2.append(j)
                        sommen2.append(r)
                        sommen2.append(t)

So until here everything seams to work but if I let it print out the output I get several times the same "I" or rather the same sum from the prime numbers.

                        for q in sommen:
                            if not sum(sommen2) == sum(q):
                                sommen.append(sommen2)

Here I am trying to say that for a q in my list "sommen" if a sum of that q already exists, don't add another one. Bu instead my laptop just calculates for a long time.

print (sommen)

Upvotes: 0

Views: 177

Answers (3)

gold_cy
gold_cy

Reputation: 14226

The problem is your loop. You are returning the same sums more than once because your loop treats [1, 7, 5] as being different from [5, 7, 1] as being different from [7, 5, 1] and so on.

Clean up the loop to be this.

import itertools

l = [10, 15, 4, 2, 7, 20]

p = [1, 2, 3, 5, 7, 11, 13]

sommen = []

for v in map(lambda x: sum(x), itertools.combinations(p, 3)):
    if v in sommen:
        pass
    elif v in l:
        sommen.append(v)

print sommen

>> [10, 15, 20]

As expected

            2 + 3 + 5 = 10
            3 + 5 + 7 = 15
            2 + 7 + 11 = 20

Notice that 1 + 2 + 7 also gives 10 but 10 was not added twice

Notice that 2 + 5 + 13 also gives 20 but 20 was not added twice

Edit: If you want to see the factors that went in how about this:

for combo in itertools.combinations(p, 3):
    if sum(combo) in map(lambda x: x[0],sommen):
        pass
    elif sum(combo) in l:
        sommen.append([sum(combo), combo])

print sommen

>> [[10, (1, 2, 7)], [15, (1, 3, 11)], [20, (2, 5, 13)]]

Upvotes: 0

blacktemplar
blacktemplar

Reputation: 709

The problem is the following code:

                    for q in sommen:
                        if not sum(sommen2) == sum(q):
                            sommen.append(sommen2)

If I understand you correctly you want to add sommen2 to sommen if its sum is not already in sommen. But what you do is, you add it to sommen for every element in sommen which has not the same sum as sommen2. Replace this by the following:

                    if not any(sum(sommen2) == sum(q) for q in sommen):
                        sommen.append(sommen2)

Upvotes: 0

user5244399
user5244399

Reputation:

To answer your original question first:

The issue lies in the fact that you iterated the entire sommen when checking for only one item sommen2. Suppose sommen contains 9 values including one that is equal to sommen2's sum, you are still appending sommen2 for 8 times.

I would use a dict to comprehensively rewrite your program, like this:

sum_summands = dict()
# found a candidate i=j+r+t here
sum_summands[i] = (j,r,t)  #use tuple not list
# or if you want to always keep the first candidate you've found
if i not in sum_summands:  # don't overwrite if sum i already exists
    sum_summands[i] = (j,r,t)

There are a ton of other things you can optimize in your algorithm. Let me point out the most obvious one. Instead of doing this -

for i in lijst2:
    for j in priemgetallen:
        for r in priemgetallen:
            for t in priemgetallen:
                if i == j+r+t:

why don't you get rid of the inner-most loop -

for i in lijst2:
    for j in priemgetallen:
        for r in priemgetallen:
            if i-j-r in priemgetallen:

It's pointless to iterate over a huge list of numbers just to check if they add up to a certain sum - you should do some minimum level of math to simplify things.

Upvotes: 0

Related Questions