Python Forum

Full Version: Trouble creating loops
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I am trying to figure out what's wrong with the code. It's supposed to be a function that counts how many times the sum of some string's elements are equal to an input number. No other libraries are supposed to be used.
For example:
string='1,2,3'
number=3
Output:
2

def calculate(string, number):
    string=''
    result=0
    new_list=[]
    new_list=[int(x) for x in string.split(',')]
    for i in range(0, len(new_list)+1,-1): 
            sum(new_list)
            if sum(new_list)==number: 
                result+= 1    
            else:
                continue
            i+=1   
    return result
Error:
ValueError: invalid literal for int() with base 10: ''
Now there is an interesting problem.
Let's start with the easy part.
You created a function needing two parameters.
In line 2 you empty the first parameter. Why? I think you should remove that line.
In line 6 you start a loop, starting with 0 and ending with len(new_list)+1. Why "+1"? You will get out of range. And you choose a step of "-1". As the loop starts at 0, the end will never be reached. In effect, the loop does not get executed.
In line 7 you compute the sum of the list, but you do not assign the result to a variable.
In line 8 you compute the sum of the list again and compare it correctly to the input number.
In line 12 you increment the loop variable. It is bad practice to manipulate the loop variable in a for loop.

But now the interesting part. Finding the correct algorithm. That is not easy. I tried to set up an example to see what is happening. I chose a list of numbers from 1 through 5 and a target number of 8.
Output:
input list: 1 2 3 4 5 8 = + + + 8 = + + + 8 = + +
We learn from this that the numbers need not be adjacent in the list. So it will not be sufficient to take slices of the list.
The number of numbers to be added is also quite random. It may be 1 or 2 or 3 or...
The algorithm might take one number in the list, and check whether it is equal to the target number.
for i in new_list:
  if i == number:
    result += 1
Then in the next step you should check whether the target number can be found by adding just 2 numbers from the list.
for i in range(0, len(new_list):
  num1 = new_list[i]
  for j in range(i+1, len(new_list):
    num2 = new_list[j]
    if num1 + num2 == number:
      result += 1
Then in the next step you should check whether the target number can be found by adding 3 numbers from the list. Well there seems to be no end to the possibilities. Try by yourself to create a check for 3 numbers.
But we will have to find a better algorithm because there are more possible combinations than there are elements in the list. And as there is no limit on the number of elements in the list we should find something smarter.
Thank you so much for pointing out all those errors, and thank you for the hints!
I've figured out some of them later, sorry, I'm still a beginner.
I've thought about splitting the string, then turning it into a list of integers through a for cycle.
(Also, I don't know how much convenient could it be, but maybe sorting the list, and including the range of the index from to the number of the input, could save time for the loops).
    string.split(',')
    for x in string.split(','):
        d=int(x)
        s.append(d)
   
Anyway, after looking if the number is already in the list, and using the while method pointing j as the len(new_list) in the while method, the sum should be calculated between all the numbers of the list.The index j should get j+=-1 everytime until i and j won't encounter eachother.
Yes, you are quite right to make a list of the numbers.

(Oct-20-2019, 01:34 PM)Den Wrote: [ -> ]Anyway, after looking if the number is already in the list, and using the while method pointing j as the len(new_list) in the while method, the sum should be calculated between all the numbers of the list.The index j should get j+=-1 everytime until i and j won't encounter eachother.
I disagree. If you tried "element[0] + element[1]" then you should not try "element[1] + element[0]" as it is obvious the same. That is why you should not start the inner loop with 0, but with i+1. So i and j will never meet.

I found a method to try to add all combinations of additions of a list of numbers. It recursively builds a tree of all combinations.
show_debug = True   #Show debug info while running or not

def find_additions(target, subtotal, input_list, debug_text):
    """Find combinations of a list of numbers to add to a certain number.

    This is a recursive function. I tries all possible combinations to add
    numbers from a list and counts the combinations that result in a certain
    target number.
    """
    result = 0 #number of times the sum of items equals the target
    for i in range(len(input_list)):
        list_item = input_list[i]
        if list_item + subtotal == target:
            result += 1
            if show_debug:
                print(debug_text + str(list_item))
        result += find_additions(target,
                        subtotal + list_item,
                        input_list[i+1:],
                        debug_text + str(list_item) + " + ")
    return result

target = 3
input_list = [1, 2, 3]
found_combinations = find_additions(target,
                0,
                input_list,
                str(target) + " = ")
print("number of combinations found: ", found_combinations)
Output:
3 = 1 + 2 3 = 3 number of combinations found: 2
The algorithm is implemented very raw and can be greatly optimized. You might want to cut off the recursion as soon as the sum is greater than the target, but beware: can there be negative numbers in the list? Can the target be negative? Can the same number occur twice in the list?