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
Related
I have a list called all=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], and another list called sub=[1, 0, 1, 0, 1, 1, 0, 0, 0, 0], I want to create a new list based on all by extracting only elements whose corresponding value in the list named sub is 1, i.e., I want to generate aa=[0,2,4,5]. It would be great if this could be done as fast as possible as I need to repeat this more than 10 millions of times.
I've tried the following two ways:
(1).
aa=all[sub]
But I got the message "TypeError: list indices must be integers or slices, not list"
(2).
bv=list(map(bool,sub))
aa=all[bv]
But I got the same error message.
How to solve this problem? Thanks!
You could do it with a simple list comprehension:
aa = [x for x,s in zip(lst,sub) if s == 1]
You would need to time it to see if it is fast enough for your needs.
(As an aside using all as the list name overwrites the built-in function with the same name).
I have a list of integers containing:
intlist = [19,4,2,4]
and i want to append the value from the intlist into a list of list such that:
noDuplist = [[19,0],[4,1],[2,2]]
where the first index represents the value from the intlist and the second index represents the index of the value in the intlist. 19 is at index 0, 4 is at index 1 and 2 is at index 2. Since there is another 4 i do not want to include that since i didn't want duplicate hence the last 4 is just going to be left out.
I tried something like:
noDuplist = []
for i in range(len(intlist)):
if intlist[i] not in noDuplist:
noDuplist.append([intlist[i],i])
but I'm still getting
[[19, 0], [4, 1], [2, 2], [4, 3]]
where the [4,3] shouldnt be there. Would appreciate some help on this
I assume you want to retain the indices from the original sequence.
Thus what you want is something that remembers at what index was the value
first seen in the original sequence.
The problem is in your condition since
if intlist[i] not in noDuplist:
# something
would check if 4 was present in [[19, 0], [4, 1], [2, 2]]] which it isn't.
A cleaner way of doing this could be using dictionaries or sets.:
intlist = [19,4,2,4]
seen_so_far, noDuplist = set(), []
for i, v in enumerate(intlist):
if v not in seen_so_far:
noDuplist.append([v, i])
seen_so_far.add(v)
print(noDuplist)
Which gives the output [[19, 0], [4, 1], [2, 2]]
The first thing I'd suggest is not bothering storing the index as well as the value. You'll know the index when extracting elements anyway.
The first approach that comes to my mind (not sure if it's optimal) involves using a dictionary in combination with your list. Whenever you try to insert a value, check if it exists in your dictionary. If it doesn't, add it to the dictionary and your list. If it does, don't add it.
This would result in O(N) complexity.
Edit:
I didn't read your description thoroughly enough. Since you need the index from the original array, simply enter both as a key/value pair into your dictionary instead.
I have a function flattens given array.
def flatten(items):
results = []
for i in items:
if isinstance(i, list):
results += flatten(i)
else:
results.append(i)
return results
It works great. It is not possible to know how many times it will run when I give an input as shown below. There are a lot of nested arrays.
data = [1, 2, 3, [4], [5, 6], [[7, 8, 9], 10, 11, 12], [13, 14, 15, [[[16], 17], 18, 19], [[[20, 21]]]], [[[22], 23, [[24]]]]]
data_flatten = flatten(data)
print(data_flatten)
I have no idea how can I calculate the run-time complexity of this function?
Since, I'm assuming, you care about the worst case performance, you can consider an abstract worst case example and then derive the answer from that.
data = [[[[... [1, 2, 3, ..., m] ...]]], [[[... [1, 2, 3, ..., m] ...]]], ..., [[[... [1, 2, 3, ..., m] ...]]]]
Now you can easily see how the worst case is influenced by three factors. The size of items, the depth of the list of lists, and finally the number of elements in a deepest list.
The worst case complexity thus is O(n x d x m) where n, d, and m stand for the size of items, the maximum depth of the nested lists, and the maximum number of elements in a deepest list.
Exact size isn't really too important when it comes to complexity. Constants get dropped anyway. If you have a 3d array, internally it has to loop through all the items, even if that's not obvious by the code. So the answer is O(n**3) because it needs a loop inside a loop inside a loop. The exact value of what n means doesn't matter because constants get dropped.
Let's pretend (since it's true) that I have a Python (3) script that needs to iterate over a 2D array (any length, but each element is just an array of 2 ints, as per the list below).
linCirc = [[1,10],
[2, 1],
[0, 2],
[2, 2],
[2, 3],
[2, 4],
[2, 0],
[2, 5]]
I want to iterate over this lovely thing recursively so that
for element in linCirc:
if element[0] == 0:
# skip element[1] elements
Essentially, all I need to know is the best way to loop over linCirc, and then when certain conditions are met, instead of going from linCirc.index(element) to linCirc.index(element) + 1, I can control the skip, and skip zero or more elements. For instance, instead of going from [0, 2] to [2, 2], I could go from [0, 2] to [2, 4]. Is this the best way to do this? Should a for loop be involved at all?
For the curious: This code is intended to linearize an electric circuit so that any circuit (with limited components; say, just resistors and batteries for now) can be represented by a 2D array (like linCirc). I will post my full code if you want, but I don't want to clog this up with useless code.
index = 0
while index < linCirc.length:
if linCirc[index][0] == 0:
index = index + linCirc[index][1]
else:
index = index + 1
Hopefully this provides the functionality you're looking for. Obviously you'll have to add some useful code to this - it just runs from start to end of the array. It may also be helpful to add an index check, to make sure it doesn't run out of bounds when it encounters [0, i] less than i elements from the end of the array.
To support an arbitrary iterable (not just sequences such as list) you could use the consume() recipe:
it = iter(linCirc)
for element in it:
if element[0] == 0:
# skip element[1] elements
n = element[1]
next(islice(it, n, n), None) # see consume() recipe from itertools docs
print(element)
example
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]