I'm following some online courses and I have this function sort but nothing nothing seems to run after the print "here" part:
import unittest
def sort(meetings, indx):
print("call function")
print meetings
firstfirst = meetings[indx][0]
firstsecond = meetings[indx][1]
secondfirst = meetings[indx+1][0]
secondsecond = meetings[indx+1][1]
first = meetings[indx]
second = meetings[indx+1]
print firstfirst
print secondfirst
if firstfirst > secondfirst:
meetings[indx] = second
meetings[indx+1] = first
print "here"
indx = index + 1
print "meetings: "
sort(meetings[indx:len(meetings)-1], indx)
def merge_ranges(meetings):
# Merge meeting range
sort(meetings, 0)
return []
# Tests
class Test(unittest.TestCase):
def test_meetings_overlap(self):
actual = merge_ranges([(1, 3), (2, 4)])
expected = [(1, 4)]
self.assertEqual(actual, expected)
def test_meetings_touch(self):
actual = merge_ranges([(5, 6), (6, 8)])
expected = [(5, 8)]
self.assertEqual(actual, expected)
def test_meeting_contains_other_meeting(self):
actual = merge_ranges([(1, 8), (2, 5)])
expected = [(1, 8)]
self.assertEqual(actual, expected)
def test_meetings_stay_separate(self):
actual = merge_ranges([(1, 3), (4, 8)])
expected = [(1, 3), (4, 8)]
self.assertEqual(actual, expected)
def test_multiple_merged_meetings(self):
actual = merge_ranges([(1, 4), (2, 5), (5, 8)])
expected = [(1, 8)]
self.assertEqual(actual, expected)
def test_meetings_not_sorted(self):
actual = merge_ranges([(5, 8), (1, 4), (6, 8)])
expected = [(1, 4), (5, 8)]
self.assertEqual(actual, expected)
def test_sample_input(self):
actual = merge_ranges([(0, 1), (3, 5), (4, 8), (10, 12), (9, 10)])
expected = [(0, 1), (3, 8), (9, 12)]
self.assertEqual(actual, expected)
unittest.main(verbosity=2)
the output shows this and only throws errors for the test cases (which I didn't include) since those are to be expected...
call function
[(1, 8), (2, 5)]
1
2
here
call function
[(5, 8), (1, 4), (6, 8)]
5
1
here
call function
[(1, 3), (2, 4)]
1
2
here
call function
[(1, 3), (4, 8)]
1
4
here
call function
[(5, 6), (6, 8)]
5
6
here
call function
[(1, 4), (2, 5), (5, 8)]
1
2
here
call function
[(0, 1), (3, 5), (4, 8), (10, 12), (9, 10)]
0
3
here
"but nothing nothing seems to run after the print "here" part"
Are you basing this on the fact that nothing else prints? If so thats because you have to print the variables you change. Also, none of your functions return anything you have worked on within the function and while sort mutates the meetings variable it has no way of knowing when to stop calling itself, it will just eventually throw an error when trying to index into an empty list held in the meetings variable. Even your use of print is confusing. You use print("call function") up top then print meetings afterwards mixing python 2 & 3 print syntax.
But let's get to the heart of your problem here.
def sort(meetings, indx):
print("call function")
print meetings
# eventually meetings will be an empty list and meetings[indx]
# will throw an IndexError
firstfirst = meetings[indx][0]
firstsecond = meetings[indx][1]
secondfirst = meetings[indx+1][0]
secondsecond = meetings[indx+1][1]
first = meetings[indx]
second = meetings[indx+1]
print firstfirst
print secondfirst
if firstfirst > secondfirst:
meetings[indx] = second
meetings[indx+1] = first
# "here" is printed
print "here"
# you alter the indx variable but do not print it
indx = index + 1
# "meetings:" is printed but nothing else is printed below it
print "meetings: "
# sort calls itself without any condition to stop calling itself
# and which will eventually have the indx variable exceed the
# meetings length in the call:
# meetings[indx:len(meetings)-1]
sort(meetings[indx:len(meetings)-1], indx)
# nothing is returned here and sort does not mutate the object in
# any way that I could see that would cause sort to stop
# calling itself
def merge_ranges(meetings):
# Merge meeting range
sort(meetings, 0)
return [] # <- this empty list is always returned no matter what
sort doesn't return anything, which isn't a huge issue if you are just mutating something
sort calls itself recursively until it exceeds the recursion limit, there is nothing to tell it to stop calling itself
Lets assume meetings is this list
meetings = [(0, 1), (3, 5)]
meetings[5:] # ==> [] will always return an empty list when indx exceed meetings length
This means sort keeps calling itself with an empty list and a higher index number
merge_meetings always returns an empty list
You need to test for the index being larger than len(meetings)
Suggestion:
Assuming python 3
def sort(meetings, indx):
print("call function")
print(meetings)
first = meetings[indx]
second = meetings[indx+1]
firstfirst = first[0]
firstsecond = first[1]
secondfirst = second[0]
secondsecond = second[1]
print(firstfirst)
print(secondfirst)
if firstfirst > secondfirst:
meetings[indx] = second
meetings[indx+1] = first
indx = index + 1
print("meetings: ", meetings)
if len(meetings) - 1 > indx:
sort(meetings[indx:], indx)
Now while this takes care of stopping the recursive calls it still doesn't sort completely, it sorts the 2 elements relative to their position to each other but it will need several passes to acheive a proper sort.
for example:
In [1]: a = [(5,3), (0,2), (4,1), (1,1)]
In [2]: sort(a, 0)
call function
[(0, 2), (5, 3), (4, 1), (1, 1)]
0
5
meetings: [(0, 2), (5, 3), (4, 1), (1, 1)]
call function
[(5, 3), (4, 1), (1, 1)]
4
1
meetings: [(5, 3), (1, 1), (4, 1)]
In [3]: a
Out[3]: [(0, 2), (5, 3), (4, 1), (1, 1)]
I'll leave that up to you to figure out seeing as this was an assignment.
Related
Here is a simple for loop through an enumerate object. This terminates due to (this line I have mentioned as a comment). Why is that?
enum_arr = enumerate(arr)
for ele in enum_arr:
print(ele)
print(list(enum_arr)[ele[0]:]) # terminates due to this line
Output:
(0, 0)
[(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)]
If I comment out the second print statement, then:
Output:
(0, 0)
(1, 1)
(2, 2)
(3, 3)
(4, 4)
(5, 5)
As expected.
Why is this happening?
enumerate() gives you an iterator object. Iterators are like a bookmark in a book that can only be moved forward; once you reach the end of the book you can't go back anymore, and have to make a new bookmark.
You then use that iterator in two places; the for loop and list(). The list() function moved the bookmark all the way to the end, so the for loop can't move it any further.
You'd have to create a new enumerate() object in the loop if you want to use a separate, independent iterator:
enum_arr = enumerate(arr)
for ele in enum_arr:
print(ele)
print(list(enumerate(arr[ele[0]:], ele[0])))
This does require that arr is itself not an iterator, it has to be a sequence so you can index into it. I'm assuming here that you have a list, tuple, range or similar value.
Note that I passed in ele[0] twice, the second argument to enumerate() lets you set the start value of the counter.
It is easier to use a tuple assignment here to separate out the count and value:
for count, value in enum_arr:
print((count, value))
print(list(enumerate(arr[count:], count)))
Demo:
>>> arr = range(6)
>>> enum_arr = enumerate(arr)
>>> for count, value in enum_arr:
... print((count, value))
... print(list(enumerate(arr[count:], count)))
...
(0, 0)
[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5)]
(1, 1)
[(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)]
(2, 2)
[(2, 2), (3, 3), (4, 4), (5, 5)]
(3, 3)
[(3, 3), (4, 4), (5, 5)]
(4, 4)
[(4, 4), (5, 5)]
(5, 5)
[(5, 5)]
Coming back to the book analogy, and the requirement that arr is a sequence: as long as arr is a book with page numbers, you can add more bookmarks at any point. If it is some other iterable type, then you can't index into it and so would have to find some other means to 'skip ahead' and back again. Stretching the analogy further: say the book is being streamed to you, one page at a time, then you can't go back once you received all the pages. The solution coud be to create a local cache of pages first; if you can spare the memory that could be done with cached_copy = list(arr). Just take into account that you have to be sure that the book you are receiving is not so long as to require more space than you actually have. And some iterables are endless, so would require infinite memory!
So, I'm trying to sum the number of passenger at each stop.
The "stops" variable are the number of stops, and is conformed by a tuple which contains the in's and out's of passengers, example:
stops = [(in1, out1), (in2, out2), (in3, out3), (in4, out4)]
stops = [(10, 0), (4, 1), (3, 5), (3, 4), (5, 1), (1, 5), (5, 8), (4, 6), (2, 3)]
number_passenger_per_stop = []
for i in stops:
resta = stops[i][0] - stops[i][1]
number_passenger_per_stop.append(resta)
print(number_passenger_per_stop)
I can do the math like this outside the loop, but I don't understand why in the loop crashes:
stops[i][0] - stops[i][1]
i is not the list index, it's the list element itself. You don't need to write stops[i].
resta = i[0] - i[1]
Your code would be correct if you had written
for i in range(len(stops)):
You could also replace the entire thing with a list comprehension:
number_passenger_per_stop = [on - off for on, off in stops]
I just edited the for loop to adress each in the index in the list correctly, you needed to call each element in the list by its position, and not by its value:
stops = [(10, 0), (4, 1), (3, 5), (3, 4), (5, 1), (1, 5), (5, 8), (4, 6), (2, 3)]
number_passenger_per_stop = []
for i in range(len(stops)):
resta = stops[i][0] - stops[i][1]
number_passenger_per_stop.append(resta)
print(number_passenger_per_stop)
Output:
[10, 3, -2, -1, 4, -4, -3, -2, -1]
I have a list of tuples called possible_moves containing possible moves on a board in my game:
[(2, 1), (2, 2), (2, 3), (3, 1), (4, 5), (5, 2), (5, 3), (6, 0), (6, 2), (7, 1)]
Then, I have a dictionary that assigns a value to each cell on the game board:
{(0,0): 10000, (0,1): -3000, (0,2): 1000, (0,3): 800, etc.}
I want to iterate over all possible moves and find the move with the highest value.
my_value = 0
possible_moves = dict(possible_moves)
for move, value in moves_values:
if move in possible_moves and possible_moves[move] > my_value:
my_move = possible_moves[move]
my_value = value
return my_move
The problem is in the part for move, value, because it creates two integer indexes, but I want the index move to be a tuple.
IIUC, you don't even need the list of possible moves. The moves and their scores you care about are already contained in the dictionary.
>>> from operator import itemgetter
>>>
>>> scores = {(0,0): 10000, (0,1): -3000, (0,2): 1000, (0,3): 800}
>>> max_move, max_score = max(scores.items(), key=itemgetter(1))
>>>
>>> max_move
(0, 0)
>>> max_score
10000
edit: turns out I did not understand quite correctly. Assuming that the list of moves, let's call it possible_moves, contains the moves possible right now and that the dictionary scores contains the scores for all moves, even the impossible ones, you can issue:
max_score, max_move = max((scores[move], move) for move in possible_moves)
... or if you don't need the score:
max_move = max(possible_moves, key=scores.get)
You can use max with dict.get:
possible_moves = [(2, 1), (2, 2), (2, 3), (3, 1), (4, 5), (5, 2),
(5, 3), (6, 0), (6, 2), (7, 1), (0, 2), (0, 1)]
scores = {(0,0): 10000, (0,1): -3000, (0,2): 1000, (0,3): 800}
res = max(possible_moves, key=lambda x: scores.get(x, 0)) # (0, 2)
This assumes moves not found in your dictionary have a default score of 0. If you can guarantee that every move is included as a key in your scores dictionary, you can simplify somewhat:
res = max(possible_moves, key=scores.__getitem__)
Note the syntax [] is syntactic sugar for __getitem__: if the key isn't found you'll meet KeyError.
If d is a dict, iterator of d generates keys. d.items() generates key-value pairs. So:
for move, value in moves_values.items():
possibleMoves=[(2, 1), (2, 2), (2, 3), (3, 1), (4, 5), (5, 2),(0, 3),(5, 3), (6, 0), (6, 2), (7, 1),(0,2)]
movevalues={(0,0): 10000, (0,1): -3000, (0,2): 1000, (0,3): 800}
def func():
my_value=0
for i in range(len(possibleMoves)):
for k,v in movevalues.items():
if possibleMoves[i]==k and v>my_value:
my_value=v
return my_value
maxValue=func()
print(maxValue)
I have a list of tuples (let's name it yz_list) that contains N tuples, which have the start and end values like: (start, end), represented by the example below:
yz_list = [(0, 6), (1, 7), (2, 8), (3, 9), (4, 10), (5, 11), (6, 12), (18, 24)]
And I would like to remove all values which are overlapped by the interval of a previous saved tuple. The output that represents this case on the sequences showed above is:
result = [(0,6), (6,12), (18,24)]
How could I achieve this result using Python?
Edit #1
The below code is the code that I'm generating this tuples:
for i, a in enumerate(seq):
if seq[i:i+multiplier] == "x"*multiplier:
to_replace.append((i, i+multiplier))
for i, j in enumerate(to_replace):
print(i,j)
if i == 0:
def_to_replace.append(j)
else:
ind = def_to_replace[i-1]
print(j[0]+1, "\n", ind)
if j[0]+1 not in range(ind[0], ind[1]):
def_to_replace.append(j)
# print(i, j)
print(def_to_replace)
for item in def_to_replace:
frag = replacer(frame_calc(seq[:item[0]]), rep0, rep1, rep2)
for k, v in enumerate(seq_dup[item[0]:item[1]]):
seq_dup[int(item[0]) + int(k)] = list(frag)[k]
return "".join(seq_dup)
As I'm developing with TDD, I'm making a step-by-step progress on the development and now I'm thinking on how to implement the removal of overlaping tuples. I don't really know if it's a good idea to use them as sets, and see the overlapping items.
The pseudocode for generating the result list is:
for item in yz_list:
if is not yz_list first item:
gets item first value
see if the value is betwen any of the values from tuples added on the result list
This may work. No fancy stuff, just manually process each tuple to see if either value is within the range of the saved tuple's set bounds:
yz_list = [(0, 6), (1, 7), (2, 8), (3, 9), (4, 10), (5, 11), (6, 12), (18, 24)]
result = [yz_list[0]]
bounds = yz_list[0][0], yz_list[0][1]
for tup in yz_list[1:]:
if tup[0] in range(bounds[0], bounds[1]) or tup[1] in range(bounds[0], bounds[1]):
pass
else:
result.append(tup)
print result # [(0, 6), (6, 12), (18, 24)]
Here is a class that calculates the overlaps using efficient binary search, and code showing its use to solve your problem. Run with python3.
import bisect
import sys
class Overlap():
def __init__(self):
self._intervals = []
def intervals(self):
return self._intervals
def put(self, interval):
istart, iend = interval
# Ignoring intervals that start after the window.
i = bisect.bisect_right(self._intervals, (iend, sys.maxsize))
# Look at remaining intervals to find overlap.
for start, end in self._intervals[:i]:
if end > istart:
return False
bisect.insort(self._intervals, interval)
return True
yz_list = [(0, 6), (1, 7), (2, 8), (3, 9), (4, 10), (5, 11), (6, 12), (18, 24)]
ov = Overlap()
for i in yz_list:
ov.put(i)
print('Original:', yz_list)
print('Result:', ov.intervals())
OUTPUT:
Original: [(0, 6), (1, 7), (2, 8), (3, 9), (4, 10), (5, 11), (6, 12), (18, 24)]
Result: [(0, 6), (6, 12), (18, 24)]
yz_list = [(0, 6), (1, 7), (2, 8), (3, 9), (4, 10), (5, 11), (6, 12), (18, 24)]
result = []
for start, stop in yz_list:
for low, high in result:
if (low < start < high) or (low < stop < high):
break
else:
result.append((start, stop))
This gives the desired output, and it's pretty easy to see how it works. The else clause basically just means "run this if we didn't break out of the loop".
It gave me an example but how can I compute it?
enter code here
create_dice_sets(6) --> ([(1, 5), (2, 4), (3, 3), (4, 2), (5, 1)])
create_dice_sets(2) --> [(1, 1)]
create_dice_sets(1) --> [()]
this is what i have given.
enter code here
def create_dice_sets(number):
#Fill your code here.
return result
print(create_dice_sets(6))
You can iterate over the range of values between 1 and the given number and create a tuple with the value i and number - i at every turn:
I think this is a homework so I assume you are not allowed to use any built-in function to do this.
>>> def create_dice_sets(number):
... result = []
... for i in range(1, number):
... result.append((i, number - i))
... return result
Btw, there is bug in the code for the given number being equal to 1.
Demo:
>>> create_dice_sets(6)
[(1, 5), (2, 4), (3, 3), (4, 2), (5, 1)]
>>> create_dice_sets(2)
[(1, 1)]
>>> create_dice_sets(1)
[]