average of the list in Python - python

I have a problem: i need to find an average of the list using this scheme:
First of all, we find an average of two elements, three elements..... len(list) elements and form a new list using averages. The use .pop() and find all averages again. Function should stop when len(list) == 2. Recursion should be used.
Example:
list: [-1, 4, 8, 1]
1 step:
find an average of [-1, 4], [-1, 4, 8], [-1, 4, 8, 1]
Then we form a new list: [1.5, 3.66..., 3] (averages)
Then find averages of new list: [1.5, 3.66...], [1.5, 3.66..., 3]
Then we form a new list: [2.5833.., 7.222...] (averages)
When len(list) == 2, find an average of this two elements.
Answer is 2.652777.
What should i write:
jada = []
while True:
print 'Lst elements:'
a = input()
if (a == ''):
break
jada.append(a)
print 'Lst is:' + str(Jada)
def keskmine(Jada):
for i in range(len(Jada) - 1):
...
jada.pop()
return keskmine(Jada)
Actually, this is a part of a homework, but i don't know how to solve it.

Accept the list as the function argument. If the list has one item, return that. Create two iterators from the list. Pop one item off one of the lists, zip them together, then find the averages of the zip results. Recurse.

In short, you're finding the "running average" from a list of numbers.
Using recursion would be helpful here. Return the only element when "len(lst) == 1" otherwise, compute the running average and recurse.
There are two parts in this assignment. First, you need to transform lists like [-1, 4, 8, 1] to lists like [1.5, 3.66, 3] (find the running averages). Second, you need to repeat this process with the result of the running averages until your list's length is 2 (or 1).
You can tackle the first problem (find the running averages) independently from the second. Finding the running average is simple, you first keep track of the running sum (e.g. if the list is [-1, 4, 8, 1] the running sum is [-1, 3, 11, 12]) and divide each elements by their respective running index (i.e. just [1, 2, 3, 4]), to get [-1/1, 3/2, 11/3, 12/4] = [-1, 1.5, 3.66, 3]. Then you can discard the first element to get [1.5, 3.66, 3].
The second problem can be easily solved using recursion. Recursion is just another form of looping, all recursive code can be transformed to a regular for/while-loops code and all looping code can be transformed to recursive code. However, some problems have a tendency towards a more "natural" solution in either recursion or looping. In my opinion, the second problem (repeating the process of taking running averages) is more naturally solved using recursion. Let's assume you have solved the first problem (of finding the running average) and we have a function runavg(lst) to solve the first problem. We want to write a function which repeatedly find the running average of lst, or return the average when the lst's length is 2.

First I'll give you an explanation, and then some pseudo code, which you'll have to rewrite in Python. The main idea is to have one function that calls itself passing a lesser problem with each iteration. In this case you would like to decrease the number of items by 1.
You can either make a new list with every call, or reuse the same one if you'd like. Before passing on the list to the next iteration, you will need to calculate the averages thus creating a shorter list.
The idea is that you sum the numbers in a parameter and divide by the number of items you've added so far into the appropriate index in the list. Once you are done, you can pop the last item out.
The code should look something like this: (indexes in sample are zero based)
average(list[])
if(list.length == 0) // Check input and handle errors
exit
if(list.length == 1) // Recursion should stop
return list[0] // The one item is it's own average!
// calculate the averages into the list in indices 0 to length - 2
list.pop() // remove the last value
return average(list) // the recursion happens here

This is also an opportunity to use python 3.x itertools.accumulate:
From docs:
>>> list(accumulate(8, 2, 50))
[8, 10, 60]
Then, you only need to divide each item by its index increased by 1, eliminate the first element and repeat until finished
For example, this works for any list of any length, doing most of the above-indicated steps inside a list comprehension:
>>> from itertools import accumulate
>>> a = [-1, 4, 8, 1]
>>> while len(a) > 1:
a = [item / (index + 1) for (index, item) in enumerate(accumulate(a)) if index > 0]
>>> print(a)
[2.6527777777777777]

Related

Python cross multiplication with an arbitrary number of lists

I'm not sure what the correct term is for the multiplication here but I need to multiply an element from List A for example by every element in List B and create a new list for the new elements, so that the total length of the new list is len(A)*len(B).
As an example
A = [1,3,5], B=[4,6,8]
I need to multiply the two together to get
C = [4,6,8,12,18,24,20,30,40]
I have researched this and I have found that itertools(product) have exactly what I needed, however it is for a specific number of lists and I need to generalise to any number of lists as requested by the user.
I don't have access to the full code right now but the code asks the user for some lists (can be any number of lists) and the lists can have any number of elements in the lists (but all lists contain the same number of elements). These lists are then stored in one big list.
For example (user input)
A = [2,5,8], B= [4,7,3]
The big list will be
C = [[2,5,8],[4,7,3]]
In this case there are two lists in the big list but in general it can be any number of lists.
Once the code has this I have
print([a*b for a,b in itertools.product(C[0],C[1])])
>> [8,14,6,20,35,15,32,56,24]
The output of this is exactly what I want, however in this case the code is written for exactly two lists and I need it generalised to n lists.
I've been thinking about creating a loop to somehow loop over it n times but so far I have not been successful in this. Since C could any of any length then the loop needs a way to know when it's reached the end of the list. I don't need it to compute the product with n lists at the same time
print([a0*a1*...*a(n-1) for a0,a1,...,a(n-1) in itertools.product(C[0],C[1],C[2],...C[n-1])])
The loop could multiply two lists at a time then use the result from that multiplication against the next list in C and so on until C[n-1].
I would appreciate any advice to see if I'm at least heading in the right direction.
p.s. I am using numpy and the lists are arrays.
You can pass variable number of arguments to itertools.product with *. * is the unpacking operator that unpacks the list and passes its values the values of list to the function as if they are separately passed.
import itertools
import math
A = [[1, 2], [3, 4], [5, 6]]
result = list(map(math.prod, itertools.product(*A)))
print(result)
Result:
[15, 18, 20, 24, 30, 36, 40, 48]
You can find many explanations on the internet about * operator. In short, if you call a function like f(*lst), it will be roughly equivalent to f(lst[0], lst[1], ..., lst[len(lst) - 1]). So, it will save you from the need to know the length of the list.
Edit: I just realized that math.prod is a 3.8+ feature. If you're running an older version of Python, you can replace it with its numpy equivalent, np.prod.
You could use a reduce function that is intended exactly for these types of operations, which is based on recursion and accumulation. I am providing you an example with a primitive function so you can better understand its functionality:
lists = [
[4, 6, 8],
[1, 3, 5]
]
def reduce(function, iterable, initializer=None):
it = iter(iterable)
if initializer is None:
value = next(it)
else:
value = initializer
for element in it:
value = function(value, element)
return value
def cmp(a, b):
for x in a:
for y in b:
yield x*y
summed = list(reduce(cmp, lists))
# OUTPUT
[4, 12, 20, 6, 18, 30, 8, 24, 40]
In case you need it sorted just make use of the sort() function.

Seeking explanation about the usage of index() method in for loop

What is the usage of this particular section of this line of code :
[number_sets.index(number_set)]
According to my understanding, index() is an inbuilt function in Python, which searches for a given element from the start of the list and returns the lowest index where the element appears.
However, this does not apply to the usage of index() in this case.
# Create original list
number_sets = [[2, 4, 6], [3, 6, 9], [4, 8, 12]]
# Create empty list to copy into
square_sets = []
# Start outer for loop to iterate over inner lists
for number_set in number_sets:
# Add a new empty list to the new list for each iteration
square_sets.append([])
# Start inner for loop to iterate over numbers and append them into the new list
for number in number_set:
print("The original number is %d, and the result is %d." % (number, number ** 2))
square_sets[number_sets.index(number_set)].append(number ** 2)
print(square_sets)
index is a Method of list, so the statement [number_sets.index(number_set)]
works like this:
[name_of_your_list.index(element) and by definition:
Returns the index of the first element with the specified value.
https://www.w3schools.com/python/python_ref_list.asp
Maybe running your code through:
http://pythontutor.com/visualize.html#mode=display
could help you to better understand what is happening.

Fastest way to exclude numbers from an array in each loop iteration

I am not a python expert.
I am trying to implement a solution for a K-Coloring interval problem.
Only using the python standard library, so no numpy,.
What i want to achieve :
So i have a sorted list of elements, and in each loop iteration i need to exclude multiple elements , so that in the next iteration the loop Continues to work on the sorted subset that resulted from the last iteration.
In each iteration i am accessing the indexes using binary search algorithm, and the list must always be sorted when worked on.
I've tried using array.pop(index) but my solution was slow and not efficient for a list of 100000 elements since it has O(n) complexity according to https://wiki.python.org/moin/TimeComplexity with n being number of elements in the list.
I've tried storing the inputs in a set() and work on them, however since in every iteration i have to execute binary search algorithm i can't store them because i will be needing to access elements by index for the sake of binary search, which is not possible in a set TypeError: 'set' object is not subscriptable.
Ex:
Input is a list sorted in ascending order according to the second item of each subarray.
arr = [[0, -1, 0], [1, 4, 0], [3, 5, 0], [0, 6, 0], [4, 7, 0], [3, 7, 0], [5, 9, 0], [6, 10, 0]]
for i in range(len(arr)) :
x = binarysearch(arr, value) #returns an index
while x > 0 :
helper = x
array.exclude(x)
x = binarysearch(arr, arr[helper][0]) #returns an index
I don't want all the arr[x] that were excluded from the last iteration to be included in the current one.
Any ideas of thoughts would be much appreciated.
Thanks in advance

Where am I wrong?

Question
Write function mssl() (minimum sum sub-list) that takes as input a list of integers.It then computes and returns the sum of the maximum sum sub-list of the input list. The maximum sum sub-list is a sub-list (slice) of the input list whose sum of entries is largest. The empty sub-list is defined to have sum 0. For example, the maximum sum sub-list of the list [4, -2, -8, 5, -2, 7, 7, 2, -6, 5] is [5, -2, 7, 7, 2] and the sum of its entries is 19.
l = [4, -2, -8, 5, -2, 7, 7, 2, -6, 5]
mssl(l)
19
mssl([3,4,5])
12
mssl([-2,-3,-5])
0
In the last example, the maximum sum sub-list is the empty sub-list because all list items are
negative.
THIS IS MY SOLUTION
def mssl(lst):
pos,neg,TotalList=[],[],[]
for items in range(len(lst)):
if(lst[items]>0):
pos+=[lst[items]]
else:
neg+=[lst[items]]
TotalPos=sum(pos)
TotalNeg=sum(neg)
if(len(neg)>0):
for negatives in range(len(neg)):
TotalList=[TotalPos+neg[negatives]]
if(TotalList>TotalList[negatives-1]):
print(TotalList)
else:
TotalList=TotalPos
print(TotalList)
THIS IS NOT A HOMEWORK QUESTION I AM LEARNING PYTHON FOR FUN, PLEASE LET ME KNOW WHERE I AM WRONG
It looks like you're trying to learn programming, with python as your first language. This particular problem is a somewhat difficult one to start with. I would advise you to take a straightforward, brute-force approach at first. Evaluate the sums of all the subsequences, one after another, and keep track of which is largest. Once you have a function that will produce the correct answer, you can look for a better (faster, more elegant, whatever) solution.
As to your code, it really has nothing to do with the question. For example, TotalList is always a one-element list. The expression TotalList[negatives-1] doesn't make much sense; if there's only one element in the list, you can access it as TotalList[0]. The expression TotalList>TotalList[negatives-1] makes no sense at all; you don't want to compare a list to a number.
This is a well-known problem, and a simple, fast solution is not at all easy to come up with, so don't be discouraged if you don't find it. Once you get a straightforward solution, you can think about an elegant one. This problem can be solved in one line of python, using list comprehensions. Trying to do that will lead to improvement in your python style. For example, instead of writing
for items in range(len(lst)):
if(lst[items]>0):
pos+=[lst[items]]
else:
neg+=[lst[items]]
you can, and should write
pos = [x for x in lst if x > 0]
neg = [x for x in lst if x < 0]
Good luck learning python.

Sorting Function. Explanantion

def my_sort(array):
length_of_array = range(1, len(array))
for i in length_of_array:
value = array[i]
last_value = array[i-1]
if value<last_value:
array[i]=last_value
array[i-1]=value
my_sort(array)
return array
I know what the function does in general. Its a sorting alogarithm.... But i dont know how what each individual part/section does.
Well, I have to say that the best way to understand this is to experiment with it, learn what it is using, and, basically, learn Python. :)
However, I'll go through the lines one-by-one to help:
Define a function named my_sort that accepts one argument named array. The rest of the lines are contained in this function.
Create a range of numbers using range that spans from 1 inclusive to the length of array non-inclusive. Then, assign this range to the variable length_of_array.
Start a for-loop that iterates through the range defined in the preceding line. Furthermore, assign each number returned to the variable i. This for-loop encloses lines 4 through 9.
Create a variable value that is equal to the item returned by indexing array at position i.
Create a variable last_value that is equal to the item returned by indexing array at position i-1.
Test if value is less than last_value. If so, run lines 7 through 9.
Make the i index of array equal last_value.
Make the i-1 index of array equal value.
Rerun my_sort recursively, passing in the argument array.
Return array for this iteration of the recursive function.
When array is finally sorted, the recursion will end and you will be left with array all nice and sorted.
I hope this shed some light on the subject!
I'll see what I can do for you. The code, for reference:
def my_sort(array):
length_of_array = range(1, len(array))
for i in length_of_array:
value = array[i]
last_value = array[i-1]
if value<last_value:
array[i]=last_value
array[i-1]=value
my_sort(array)
return array
def my_sort(array):
A function that takes an array as an argument.
length_of_array = range(1, len(array))
We set the variable length_of_array to a range of numbers that we can iterate over, based on the number of items in array. I assume you know what range does, but if you don't, in short you can iterate over it in the same way you'd iterate over a list. (You could also use xrange() here.)
for i in length_of_array:
value = array[i]
last_value = array[-1]
What we're doing is using the range to indirectly traverse the array because there's the same total of items in each. If we look closely, though, value uses the i as its index, which starts off at 1, so value is actually array[1], and last_value is array[1-1] or array[0].
if value<last_value:
array[i]=last_value
array[i-1]=value
So now we're comparing the values. Let's say we passed in [3, 1, 3, 2, 6, 4]. We're at the first iteration of the loop, so we're essentially saying, if array[1], which is 1, is less than array[0], which is 3, swap them. Of course 1 is less than 3, so swap them we do. But since the code can only compare each item to the previous item, there's no guarantee that array will be properly sorted from lowest to highest. Each iteration could unswap a properly swapped item if the item following it is larger (e.g. [2,5,6,4] will remain the same on the first two iterations -- they will be skipped over by the if test -- but when it hits the third, 6 will swap with 4, which is still wrong). In fact, if we were to finish this out without the call to my_sort(array) directly below it, our original array would evaluate to [1, 3, 2, 3, 4, 6]. Not quite right.
my_sort(array)
So we call my_sort() recursively. What we're basically saying is, if on the first iteration something is wrong, correct it, then pass the new array back to my_sort(). This sounds weird at first, but it works. If the if test was never satisfied at all, that would mean each item in our original list was smaller than the next, which is another way (the computer's way, really) of saying it was sorted in ascending order to begin with. That's the key. So if any list item is smaller than the preceding item, we jerk it one index left. But we don't really know if that's correct -- maybe it needs to go further still. So we have to go back to the beginning and (i.e., call my_sort() again on our newly-minted list), and recheck to see if we should pull it left again. If we can't, the if test fails (each item is smaller than the next) until it hits the next error. On each iteration, this teases the same smaller number leftward by one index until it's in its correct position. This sounds more confusing than it is, so let's just look at the output for each iteration:
[3, 1, 3, 2, 6, 4]
[1, 3, 3, 2, 6, 4]
[1, 3, 2, 3, 6, 4]
[1, 2, 3, 3, 6, 4]
[1, 2, 3, 3, 4, 6]
Are you seeing what's going on? How about if we only look at what's changing on each iteration:
[3, 1, ... # Wrong; swap. Further work ceases; recur (return to beginning with a fresh call to my_sort()).
[1, 3, 3, 2, ... # Wrong; swap. Further work ceases; recur
[1, 3, 2, ... # Wrong; swap. Further work ceases; recur
[1, 2, 3, 3, 6, 4 # Wrong; swap. Further work ceases; recur
[1, 2, 3, 3, 4, 6] # All numbers all smaller than following number; correct.
This allows the function to call itself as many times as it needs to pull a number from the back to the front. Again, each time it's called, it focuses on the first wrong instance, pulling it one left until it puts it in its proper position. Hope that helps! Let me know if you're still having trouble.

Categories

Resources