What's the most efficient (in time) way of checking if two relatively short (about 3-8 elements) lists are shifted copies of one another? And if so, determine and return the offset?
Here is the example code and output I'd like:
>>> def is_shifted_copy(list_one, list_two):
>>> # TODO
>>>
>>> is_shifted_copy([1, 2, 3], [1, 2, 3])
0
>>> is_shifted_copy([1, 2, 3], [3, 1, 2])
1
>>> is_shifted_copy([1, 2, 3], [2, 3, 1])
2
>>> is_shifted_copy([1, 2, 3], [3, 2, 1])
None
>>> is_shifted_copy([1, 2, 3], [1])
None
>>> is_shifted_copy([1, 1, 2], [2, 1, 1])
1
Lists may have duplicate entries. If more than one offset is valid, return any offset.
Python collection.counter() method can be used to compare lists efficiently. The counter() function counts the frequency of the items in a list and stores the data as a dictionary in the format <value>:<frequency>. If two lists have the exact same dictionary output, we can infer that the lists are the same.
The difference between two lists (say list1 and list2) can be found using the following simple function. By Using the above function, the difference can be found using diff(temp2, temp1) or diff(temp1, temp2) . Both will give the result ['Four', 'Three'] .
Using traversal in two lists, we can check if there exists one common element at least in them. While traversing two lists if we find one element to be common in them, then we return true. After complete traversal and checking, if no elements are same, then we return false.
Using traversal, we have to double the given list. Check for any x(0<=n) to any x+n and compare with list2 to see if the list1 and list2 are same, if both are same then the list2 is circularly identical.
here's a simple iterator version that does the job in 2n iterations (n being the length of list)
import itertools
def is_shifted_copy(list1, list2):
if len(list1) != len(list2):
return False
iterator = iter(list2)
for i, item in enumerate(itertools.chain(list1, list1)):
try:
if item == iterator.next():
continue
else:
iterator = iter(list2)
except StopIteration:
return i - len(list2)
else:
return False
print is_shifted_copy([1, 2, 3], [1, 2, 3]) #0
print is_shifted_copy([1, 2, 3], [3, 1, 2]) #2
print is_shifted_copy([1, 2, 3], [3, 2, 1]) #False
print is_shifted_copy([1, 2, 3], [2, 3, 1]) #1
print is_shifted_copy([1, 1, 2], [2, 1, 1]) #2
print is_shifted_copy([1, 2, 3], [1]) #False
print is_shifted_copy([1, 2, 1], [2, 1, 1]) #1
print is_shifted_copy([1, 1, 1], [1, 1, 1]) #0
and from your specification,
shouldn't is_shifted_copy([1, 1, 2], [2, 1, 1])
return 2
?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With