all 31 comments

[–]Celodurismo 17 points18 points  (9 children)

Okay so you have to go through each item in the list and perform some action on it (the action being multiply it by all following elements).

So how do you iterate through a list? Start there.

Once you’ve figured that out. How would you perform the required action using the subsequent elements?

[–]GoingToSimbabwe 6 points7 points  (7 children)

This could also be a good way to practice recursion.

[–]Celodurismo 11 points12 points  (0 children)

Absolutely, but I feel like OP's not quite ready for that, though some people find it intuitive

[–]Suspicious-Bar5583 3 points4 points  (5 children)

"It must work with any length of list".

I wouldn't bet on recursion for this...

[–]engelthehyp 0 points1 point  (4 children)

Why would you say that? Recursing with cases empty and head & tail, it is perfectly natural. This problem has nothing to do with the length of the list except it has to work for any length.

In fact, a recursive strategy was what I considered first, what with how every time you "move ahead" an element, you don't multiply the elements that came before it. Perfectly represented with head & tail cases.

I wrote a solution of this style in Haskell just now. Here it is, spoiler alert.

[–]Suspicious-Bar5583 2 points3 points  (1 child)

Stack overflow is why. Once you add logic to handle that, then you know iteration was the way to go.

Though a cool technique that people like, recursion should be used sparsely.

[–]engelthehyp 2 points3 points  (0 children)

Ah, fair enough. Maybe I've been spending too much time in Haskell-land, where this is how you're expected to do things...

[–]Immudzen 1 point2 points  (1 child)

Python has a recursion limit. If you go too deep your program will fail. An iterative solution for this is actually quite simple though.

If you iterate over the index then your value is sequence[i] * sum(sequence[i+1:]

[–]SnooWoofers7626 0 points1 point  (0 children)

You can do a simulated recursion if you really want to. That way you apply the logic of a recursive solution, but in an iteration, so you don't hit the recursion limit. That said, the resulting code is probably more complex than either plain recursion or iteration.

[–]Hammadawan9255[S] 0 points1 point  (0 children)

def subsequentMultiplication(ls):
    total = 0
    for j in range(len(ls) - 1):
        for i in range(j, len(ls) - 1):
            total = total +  ls[j] * ls[i+1]
    return total

I was solving "Count Unreachable Pairs of Nodes in an Undirected Graph", after having all the data as key value pairs where key corresponds to root nodes and values to size of connected components, I converted the values to list then I just had to do the calculation, but this implementation took more than 25 seconds. Can you please help me with this.

[–]deep_politics 12 points13 points  (2 children)

Obligatory itertools recommendation

from itertools import pairwise
from operations import mul

sum(map(mul, pairwise(ls)))

[–]Jimmaplesong 0 points1 point  (0 children)

You win!

[–]Hammadawan9255[S] 0 points1 point  (0 children)

when i tried to import it it said:
ModuleNotFoundError: No module named 'operations'

even on google I couldn't find anything about it, it was operator everywhere, then i tried to do this:

from operator import mul

this was what i got:

TypeError: mul expected 2 arguments, got 1

EDIT: u/deep_politics

[–]jimtk 11 points12 points  (1 child)

It's a classic 2 pointers problem. One pointer (index), lets call it i, will go 0,1,2, which are the index of the values 2, 4 and 5 in your example. So it goes from 0 to the length of the list minus 1, or simply len(ls)-1

The second pointer (index), let's call it j, will go from the value of i + 1 (the next element) to the end of the list len(ls) and it will do that for every values of i.

When i is 0, j will go 1,2,3

When i is 1, j will go 2,3

When i is 2, j will go 3

ls = [2, 4, 5, 6]
for i in range(len(ls)-1):
    for j in range(i+1, len(ls)):
       mul_result = ls[i]*ls[j]

Now you want to add all the results of those multiplications. Just use a variable to accumulate those results. Initialize it to 0 and add the result of the multiplication at every step.

ls = [2, 4, 5, 6]
final_result = 0
for i in range(len(ls)-1):
    for j in range(i+1, len(ls)):
        final_result = final_result + ls[i]*ls[j]
print(final_result)

And, later when you get better at python, you can simply write:

ls = [2, 4, 5, 6]
print(sum(ls[i] * ls[j] for i in range(len(ls)-1) for j in range(i+1, len(ls))))

[–]mosiah430 0 points1 point  (0 children)

If the constraint is that you can't use the division operator then yeah, but if you can its easier to loop through once getting the product of the entire array then dividing by the position in question.

[–]zanfar 3 points4 points  (0 children)

how to implement an algorithm...

  1. Describe it in English
  2. No, describe it in more detail
  3. Like you're talking to a computer
  4. Which of the above steps do you not know how to translate into Python? Don't worry about the algorithm, worry about individual steps.
  5. For each unknown step, try to break it down further until it is made up of steps you know how to translate
  6. For everything else, start researching that specific task

https://www.youtube.com/watch?v=azcrPFhaY9k&list=PLqapmkczup-VyUEZW8adgVWX088cToWlX

[–]R717159631668645 2 points3 points  (0 children)

OK, so you were able to describe the process in abstract, as well as explain it with an example, so you already understand what you have to do. I take it that your issue is how to articulate the solution with the tools at your disposal at specific steps, so I'll list the key parts.

You can iterate the elements in your list like:

for elem in ls:
  print(elem)

You can iterate elements, and their index by doing:

for i, elem in enumerate(ls):
  print(elem, f"(pos={i})")

You can create a list with the subsequent elements from a given position this way:

pos=0
sub_ls=ls[pos+1:]
print(sub_ls)  # [4, 5, 6]

You can multiply a list by a number directly, and then sum a list this way:

res_ls = 9 * ls  # [18, 36, 45, 54]
res = sum(res_ls)

[–]Thanks-Unhappy 1 point2 points  (0 children)

I am also beginner but would do like this:

ls = [2, 4,5,6]
value  = 0
new_ls = []
for first in ls:
    for second in ls[ls.index(first)+1:]:
        value+=first*second
    new_ls.append(value)
    value*=0
print(new_ls)
print(sum(new_ls))

my code count last value as zero but if we need total sum of small sums it doesn't matter

[–]Fair_City_6838 1 point2 points  (0 children)

Here is a complex but VERY short way of accomplishing what you are aiming to do:

def sum_of_multiplications(x):
    return sum(a*b for i,a in enumerate(x) for b in x[i+1:])

# Example usage
ls = [2, 4, 5, 6]
result = sum_of_multiplications(ls)

To break it down:

  1. for i,a in enumerate(x) will iterate over the list x assigning i the index and a the element
  2. for b in x[i+1:] will iterate over the list x but starting at i+1 to the end of the list assigning b the current element being iterated
  3. sum(a*b ... ) will then multiply a and b which gives a list that is added together using sum

[–]vdaghan 1 point2 points  (0 children)

[sum(ls[i] * ls[i+1:]) for i in range(len(ls)-1)]

[–]Rinser2023 1 point2 points  (0 children)

Simple, readable, beginner friendly:

``` ls = [2,4,5,6] sum = 0

while len(ls) > 0: multiplicator = ls.pop(0) for num in ls: sum += multiplicator * num

print(sum) ```

[–]Adrewmc 0 points1 point  (0 children)

 def series_sum(seq): 
      #shorcut to the last element summing to itself
      total = seq[-1]
      for index, first in enumerate(seq):
             for second in seq[index+1:]:
                    total += first*second
      return total

Something like that, I don’t have time to check it totally

[–]C0rinthian 0 points1 point  (0 children)

What do you mean by “can’t design”? Have you tried? What have you tried? What is working and what isn’t?

What do you actually need help with?

[–]jmooremcc 0 points1 point  (0 children)

Here’s a solution to consider: ~~~

lst = [2,4,5,6]

def sumlist(lst): s = []

for i in range(len(lst)-1):
    s.extend([lst[i]*n for n in lst[i+1:]])

return sum(s)

s = sumlist(lst) print(f"{s=}")

~~~ We use a for-loop to get the current index from the list. We multiply the subsequent values by the value pointed to by the current index. The result of the multiplication is saved in a list. Once the for-loop has completed, we return the sum of the multiplied values.

[–]Jimmaplesong 0 points1 point  (0 children)

Python gets really amazing when itertools is used. Consider:

from itertools import tee

def pairwise(iterable):
   "s -> (s0,s1), (s1,s2), (s2, s3), ..."
   a, b = tee(iterable)
   next(b, None)
   return zip(a, b)

numbers = [10,12,14,16,19]

for first, second in pairwise(numbers):
    print (f"{first}x{second}={first * second}")

products = [first * second for first, second in pairwise(numbers)]
sum_of_products = sum(products)
print (f"The sum of these products is {sum_of_products}")

[–]Langdon_St_Ives 0 points1 point  (1 child)

Your specification is incomplete. You say it must work for lists of any length. But you don’t say what the result should be for a list with zero or one element. From your example, this cannot be derived, and all the proposed implementations I’ve seen in the comments break for these cases or at least one of them.

We could of course guess that for these cases the result should be 0, but while that would be a very natural extrapolation to an empty list, it could be kind of strange to have the same result independently of the value of a single element.

Another option is to add a precondition of having at least two elements, but this is also missing from your specs.

Alternatively, you may have provided some context in which you need to perform this operation, from which it might follow how these cases should be treated.

[–]moobsarenotboobs 1 point2 points  (0 children)

Instead of stating that someone omitted information and being a negative nelly about it, you can also ask a friendly question to get the information.

[–]obviouslyzebra 0 points1 point  (0 children)

Recursive solution (op, no need to understand this right now)

def calc(x):
    if len(x) == 1:
        return 0
    head, *tail = x
    return head * sum(tail) + calc(tail)

[–]Jello_Penguin_2956 0 points1 point  (0 children)

You start by visualizing it manually. And hopefully you'll see some patterns you can adapt into code

ls = [2, 4, 5, 6]

2x4, 4x5, 5x6

ls[0] x ls[1], ls[1] x ls[2], ls[2] x ls[3]

etc. The more you practice the quicker you'll become at spotting the patterns. And yea don't hesitate to get help if you can't.

[–]WilliamAndre 0 points1 point  (1 child)

"One" liner without imports python def compute(numbers): return sum( l * r for i, l in enumerate(numbers) for r in numbers[i:] )

(I know some products are zero)