Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 months ago.
Improve this question
I have a tuple x with elements as x = (2, 3, 4, 5). I also have another data structure that holds closed intervals with the number of elements equal to the number of elements in the tuple x, as y = ((2,3), (3.5, 4.5), (6, 9), (4, 7)).
Now, I can set up a nested loop and check if each element of x lies within the respective intervals in y. But the issue is that it takes too long for a tuple with 10000 elements. Although efficiency might not matter, I do want the code to run fast.
Note: By efficient I do mean time wise, where the code runs faster than any other 'obvious' solutions.
I was wondering if there was a more efficient way to do this using Python instead of the obvious nested loop? This seems to be only possible with the nested loops solution.
I don't have any code as I can not figure the question out. If I could have hints as to how to make it efficient then please provide them.
What about something like this
>>> x = (2, 3, 4, 5)
>>> y = ((2,3), (3.5, 4.5), (6, 9), (4, 7))
>>> def f(e):
... p, (q, r) = e
... return q <= p <= r
>>> list(map(f, zip(x,y)))
[True, False, False, True]
You can achieve this in linear time using one loop.
You only have to iterate once on both of the tuples, something like this:
x = (2, 3, 4, 5)
y = ((2,3), (3.5, 4.5), (6, 9), (4, 7))
for index, number in enumerate(x):
if number > y[index][1] or number < y[index][0]:
print(f'{number} is NOT in {y[index}')
else:
print(f'{number} is in {y[index]}')
the output is:
2 is in the interval (2, 3)
3 is NOT in the interval (3.5, 4.5)
4 is NOT in the interval (6, 9)
5 is in the interval (4, 7)
As i said, this solution will take O(n), instead of O(n^2)
Welcome to SO.
Although this is definitely not efficient for a small tuple, for a large one this will speed up the process greatly (from an O(n^2) solution to an O(n)). I hope this helps.
x = (2, 3, 4, 5)
y = ((2, 3), (3.5, 4.5), (6, 9), (4, 7))
for a, b in enumerate(y):
if b[0] <= x[a] <= b[1]:
print(f'{x[a]} is in between {b}.')
else:
print(f'{x[a]} is not in between {b}')
For boolean values:
interval = lambda t, i: [b[0] <= t[a] <= b[1] for a, b in enumerate(i)]
x = (2, 3, 4, 5)
y = ((2, 3), (3.5, 4.5), (6, 9), (4, 7))
print(interval(x, y))
All within linear (O(n)) time! Thanks for reading and have a great day.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I have a set of tuples:
(1, 3, 6)
(5, 2, 4)
...
(8, 1, 9)
I can get combinations of middle (or first or last) values whose sum is below a certain value:
def func(tuples, maxVal):
values = [i[1] for i in tuples]
result = [seq for s in range(len(values), 0, -1) for seq in itertools.combinations(values, s) if sum(seq) <= maxVal]
print(result)
but i'd like to be able to keep track of which tuples the values came from, so instead of just returning sets of values with appropriate sum, i want to return whole tuples which those values came from. Not sure how to do that.
How about
from itertools import combinations
def func(tuples, maxVal):
return [seq for s in range(len(tuples), 0, -1)
for seq in combinations(tuples, s)
if sum(t[1] for t in seq) <= maxVal]
tuplesset = {(1, 3, 6), (5, 2, 4), (8, 1, 9)}
print(func(tuplesset, 4))
The printout from that is
[((1, 3, 6), (8, 1, 9)), ((5, 2, 4), (8, 1, 9)), ((1, 3, 6),), ((5, 2, 4),), ((8, 1, 9),)]
which seems to be correct.
The main differences between my routine and yours is that I leave out the values variable (the middle values in your tuples) and have the expression sum(t[1] for t in seq) rather than sum(seq) for summing the middle values of the tuples. I also broke your one long line into multiple shorter lines for legibility and to follow PEP8 better.
You could use a dictionary mapped to pairs if you really want to save the tuples instead of just saving the indices:
{(x, x, x) : ( (z,z,z), (y,y,y) ), ... }
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
Write a Python function histogram(l) that takes as input a list of integers with repetitions and returns a list of pairs as follows:
for each number n that appears in l, there should be exactly one pair (n,r) in the list returned by the function, where r is is the number of repetitions of n in l.
the final list should be sorted in ascending order by r, the number of repetitions. For numbers that occur with the same number of repetitions, arrange the pairs in ascending order of the value of the number.
For instance:
>>> histogram([13,12,11,13,14,13,7,7,13,14,12])
[(11, 1), (7, 2), (12, 2), (14, 2), (13, 4)]
>>> histogram([7,12,11,13,7,11,13,14,12])
[(14, 1), (7, 2), (11, 2), (12, 2), (13, 2)]
>>> histogram([13,7,12,7,11,13,14,13,7,11,13,14,12,14,14,7])
[(11, 2), (12, 2), (7, 4), (13, 4), (14, 4)]
The Counter object is perfect for this.
>>> from collections import Counter
>>> Counter([13,12,11,13,14,13,7,7,13,14,12])
Counter({13: 4, 12: 2, 14: 2, 7: 2, 11: 1})
Edit:
And if you want the result in a list of tuples sorted by value, you can do the following.
>>> count = Counter([13,12,11,13,14,13,7,7,13,14,12])
>>> sorted(count.items(), key=lambda c: c[1])
[(11, 1), (12, 2), (14, 2), (7, 2), (13, 4)]
Next time please share what you've tried yourself.
def make_histogram(lst):
new_lst = list(set([(i, lst.count(i)) for i in lst]))
new_lst.sort(key=lambda x: x[1])
return new_lst
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I am writing a program where I need to calculate the total watch time of a movie.
1st watch = (0,10)
2nd Watch =(13,18)
3rd watch =(15,23)
4th watch =(21,26)
Total movie watched=10+5+5+3=23 min
How can I implement this in Python
OK, the real challenge here is with the overlapping sequences. Sorry but your question is not very clear.
It is not optimal (see below for a better algorithm) but you can try:
l = [(0, 10), (13, 18), (15, 23), (21, 26)]
s = set()
for w in l:
s = s.union(range(*w))
d = len(s)
It should do the trick. It gives d = 23.
EDIT : better algorithm
l = [(0, 10), (13, 18), (15, 23), (21, 26)]
flat_list = sorted([(t[0], 1) for t in l] + [(t[1], -1) for t in l])
# flat_list == [(0, 1), (10, -1), (13, 1), (15, 1), (18, -1), (21, 1), (23, -1), (26, -1)]
duration = level = 0
start = None
for minute, level_inc in flat_list:
level += level_inc
if level == 0:
duration += minute - start
start = None
elif start is None and level == 1:
start = minute
assert(level == 0) # something is wrong otherwise
print("Duration is {}".format(duration))
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
This question is similar to "Aligning to Lists in python" question, but I have a problem with using a dictionary because of repeated numbers for potential keys.
Here is an example. Start with these 2 lists:
If I used a dictionary these would be the keys. [5,6,6,1,6,1,6,1,1,2,1,2,1,2,2,1]
[13,14,15,10,16,11,17,12,12,13,13,14,14,15,16,17]
I am able to rearrange the first list the way I want it, which is:
[5,6,6,6,6,1,1,1,1,1,1,2,2,2,2,1]
I want the second list to keep it's same alignment, to the first list and look exactly like this:
[13,14,15,16,17,10,11,12,12,13,14,13,14,15,16,17]
Notice that it matters that the list of potential keys has it's repeated values aligned by position with the corresponding values in the second list.
Like other people below your post, I don't completely understand your problem (could you be more specific about relation you want to obtain?), but maybe zip is the answer for your question:
>>> a = [5,6,6,6,6,1,1,1,1,1,1,2,2,2,2,1]
>>> b = [13,14,15,16,17,10,11,12,12,13,14,13,14,15,16,17]
>>> alignment = zip(a, b)
>>> alignment
[(5, 13), (6, 14), (6, 15), (6, 16), (6, 17), (1, 10), (1, 11), (1, 12), (1, 12), (1, 13), (1, 14), (2, 13), (2, 14), (2, 15), (2, 16), (1, 17)]
Edited:
key_list = [5,6,6,1,6,1,6,1,1,2,1,2,1,2,2,1]
values_list = [13,14,15,10,16,11,17,12,12,13,13,14,14,15,16,17]
zipped_lists = zip(key_list, values_list)
sorted_zip = sorted(zipped_lists)
pattern = [5,6,6,6,6,1,1,1,1,1,1,2,2,2,2,1]
temp_dict = {}
for key, value in sorted_zip:
if key not in temp_dict:
temp_dict[key] = [value]
else:
temp_dict[key].append(value)
final_list = []
for i in pattern:
final_list.append((i, temp_dict[i].pop(0)))
And, of course, final_list is your result.