-4

I have a list of numbers ; 1 6 3 15 54...

Let's say list is L, I want to apply this condition as simple as possible ;

L[2]-L[1] 
L[4]-L[3]
.
.
.

Then a new list emerges let's say L2, apply the same rule again ;

L2[2]-L2[1]
L2[4]-L2[3]
.
.
.

Until there is only one number is left from the initial L list.

I am currently working on something like this ;

for n in range(2,len(L),1):
  r.append(s[n]-s[n-1])

works for 1 loop but to introduce corresponding iterations I am looking for a decent approach. I will gladly accept the innovative answer. Thank you!

y33t
  • 649
  • 4
  • 14
  • 23

3 Answers3

2

Assuming that your example should be the following:

[1, 6, 3, 15, 54]
[5, -3, 12, 39]
[-8, 15, 27]
[23, 12]
[-11]

Where in each step, the numbers are taken as a pair and the first number is substracted from the second.

In that case, you can use the pairwise function from the itertools recipes:

# original list
l = [1, 6, 3, 15, 54]

# copy it over to a new name which will be updated on each iteration
lst = l

# repeat until the list only contains a single element
while len(lst) > 1:
    # take all pairs from the list and substract the first from the second
    # collect the results in a list and assign that to `lst`
    lst = [y - x for x, y in pairwise(lst)]

# finally, print the single element that’s left in the list
print(lst[0])
poke
  • 369,085
  • 72
  • 557
  • 602
1

Assuming that [1, 6, 3, 15, 54] gets reduced to [-11] in the end, you can just use recursion for this. What recursion will do here is keep calling the same function over and over again, until a base case is met. In your case, it will keep reducing the list on each recursive call, until the length of the list only has one element. I'm also assuming that you want to return the final singleton list at the end.

Recursion Approach:

lst = [1, 6, 3, 15, 54]

def reduce_list(l):
    if len(l) == 1:
        return l

    return reduce_list([y - x for x, y in zip(l, l[1:])])

print(reduce_list(lst))

Which Outputs:

[-11]

Note: zip() was used to pair every 2 elements elements together in the list, and minus the second element from the first element.

Here is an example that breaks down the above usage of zip():

>>> lst = [1, 6, 3, 15, 54]
>>> zipped = list(zip(lst, lst[1:]))
[(1, 6), (6, 3), (3, 15), (15, 54)]
>>> print([y - x for x, y in zipped])
[5, -3, 12, 39]

Additionally, anything done with recursion can be done with a simple loop, which @poke has nicely shown.

EDIT:

Since the above code is prone to RecursionError: maximum recursion depth errors with lists of size 1000 or greater, because 1000 is the recusion limit, you can see this post for more details on how to increase the limit. Alternatively, you can also just make an iterative version that is bypasses this problem, as shown below.

Iterative Approach:

lst = [1, 6, 3, 15, 54]

def reduce_list(l):
    return [y - x for x, y in zip(l, l[1:])]

# Since 5 elements reduce to 1, 4 iterations only needed
for _ in range(len(lst) - 1):
    lst = reduce_list(lst)

print(lst)
# [-11]
RoadRunner
  • 25,803
  • 6
  • 42
  • 75
  • RuntimeError: maximum recursion depth exceeded Any ideas ? – y33t Dec 31 '17 at 14:28
  • @y33t What example are you running this on? – RoadRunner Dec 31 '17 at 14:30
  • there is a list I generated consisting of approximately 10 elements. – y33t Dec 31 '17 at 14:41
  • Yeah thats strange, I'm running this code on 100 elements and its working fine. You could just use @poke's example, its much simpler and error prone compared to this one. – RoadRunner Dec 31 '17 at 14:45
  • @y33t made an iterative version at the bottom. – RoadRunner Dec 31 '17 at 15:31
  • Wait, do you actually believe their recursion-error-for-10-elements nonsense? – Stefan Pochmann Dec 31 '17 at 15:49
  • @StefanPochmann Something doesn't seem right with it. I get recursion errors on 1000 elements + with python 3.5. I don't understand how the OP was getting errors with only 10 elements. – RoadRunner Dec 31 '17 at 15:50
  • Well *that* is expected, since the default maximum is 1000. But if they get it with 10, then they messed something up. – Stefan Pochmann Dec 31 '17 at 15:51
  • Wrote something more efficient, maybe you're interested: https://ideone.com/szyfCP – Stefan Pochmann Dec 31 '17 at 16:31
  • @StefanPochmann Don’t benchmark manually with `time()`. Use the `timeit` module. – poke Dec 31 '17 at 16:32
  • @poke Why? And how would `timeit` give me not just the time but also the results so I can compare them? – Stefan Pochmann Dec 31 '17 at 16:35
  • @StefanPochmann See [this answer](https://stackoverflow.com/a/17579466/216074) for example. Also, you don’t need to repeat the call thousand times to compare the results. Verifying correctness and measuring performance are two separate things. If the function is not correct, you don’t need to measure its performance in the first place. – poke Dec 31 '17 at 16:39
  • @poke I knew that stuff already. And I'm not repeating the call thousand times, I call only once. The function *is* correct (as far as I can tell), so I don't know why you're talking about that. Anyway... yes, timeit is better in general and I use it a lot, but do you really think it's needed when I'm showing that my function is orders of magnitude faster? Who cares whether it's 50 times or 100 times? That's not the point. Oh well, here's a timeit way (and I increased the data size): https://ideone.com/nuZKEZ – Stefan Pochmann Dec 31 '17 at 16:47
  • @poke Included yours as well now: https://ideone.com/oi7sGe Yours is a bit slower than RoadRunner's there and about 164 times slower than mine. I'm actually surprised, thought the itertools overhead would be larger. – Stefan Pochmann Dec 31 '17 at 17:00
  • @RoadRunner I'm glad not everyone only looked at how I measured :-). Yes, it's nice. I would've posted it as an answer if the question wasn't all about that process of computing list differences, which I'm not doing... – Stefan Pochmann Jan 01 '18 at 11:57
0

You can try recursive approach :

data=[1,6,3,15,54]

def finding(list_1):
    if not list_1:
        return 0
    list_2=[]
    for i in range(0,len(list_1),1):
        chunk=list_1[i:i+2]
        if len(chunk)==2:
            list_2.append(chunk[1]-chunk[0])

    if list_2:
        print(list_2)



    return finding(list_2)


print(finding(data))

output:

[5, -3, 12, 39]
[-8, 15, 27]
[23, 12]
[-11]
0