Let's say I have a array like l = [1, 3, 4, 5, 6, 8]
where the nth element represents the distance between the nth and n+1th object.
I want to find the distance between any two objects, and I used this code for this:
def dis(l_list, index1, index2, mylist):
m = mylist.index(index1)
n = mylist.index(index2)
i=0
j=0
if n > m:
while n >= m:
i = i + mylist[m]
m = m + 1
elif n < m:
while n <= m:
i = i + mylist[n]
n = n + 1
else:
return(0)
j = mylist[n] % l_mylist
print(abs(i - j))
l_mylist = input()
l_mylist = int(l_mylist)
mylist = []
mylist = list(map(int, input().split()))
i,j = input().split()
i, j=int(i), int(j)
dis(l_mylist, i, j, mylist)
but I am still getting the wrong output. Can anyone please point out where I am wrong?
If you want to sum around a potentially circular list. You can use a collections.deque() to rotate the list, e.g.:
from collections import deque
def dist(l, i1, i2):
d = deque(l)
d.rotate(-i1)
return sum(list(d)[:i2-i1]))
In []:
l = [1,2,3,4,5,6,7,8]
dist(l, 3-1, 6-1) # 3, 4, 5
Out[]:
12
In []:
dist(l, 6-1, 3-1) # 6, 7, 8, 1, 2
Out[]:
24
def distance(first_index, second_index, my_list):
temp_list = my_list + my_list
if (first_index > second_index):
first_index += len(my_list)
requested_sum = sum(my_list[second_index-1:first_index-1])
else:
requested_sum = sum(my_list[first_index-1:second_index-1])
return requested_sum
If I understood you correctly, then this should do the trick.
There are much more compact and efficient ways to do this, but this is the simplest and easiest to understand in my opinion.
Related
Wrote a simple code for left array rotation, getting the same array without any Rotation done to it as the wrong output.
def leftRotate(arr, d, n):
while (d-1) > 0:
leftRotatebyOne(arr, n)
def leftRotatebyOne(arr, n):
temp = arr[0]
for i in range(n-1):
arr[i] = arr[i + 1]
arr[n - 1] = temp
def PrintArray(arr, size):
for i in range(size):
print("%d" % arr[i], end=" ")
arr = []
l = int(input("Enter the number of elements: "))
for i in range(0, l):
ele = int(input())
arr.append(ele)
d = int(input("Enter the number of rotations: "))
n = len(arr)
leftRotate(arr, d, n)
PrintArray(arr, n)
and here's an example of the output i've got,
Enter the number of elements: 3
1
2
3
Enter the number of rotations: 1
1 2 3
I expected an output of 2 3 1 after one rotation.
I would suggest using array slicing, then adding the slices together, to perform rotation.
def left_rotate(data, num):
return data[num:] + data[:num]
def right_rotate(data, num):
return data[-num:] + data[:-num]
For example
>>> a = [1,2,3,4,5,6,7]
>>> left_rotate(a, 2)
[3, 4, 5, 6, 7, 1, 2]
>>> right_rotate(a, 2)
[6, 7, 1, 2, 3, 4, 5]
Also note that collections.deque has this behavior available already
>>> from collections import deque
>>> d = deque([1,2,3,4,5,6,7])
>>> d.rotate(2)
>>> d
deque([6, 7, 1, 2, 3, 4, 5])
>>> d.rotate(-2)
>>> d
deque([1, 2, 3, 4, 5, 6, 7])
In the function leftRotate,
there is an error in while loop.
Replace
while (d-1) > 0:
leftRotatebyOne(arr, n)
with
while d > 0:
leftRotatebyOne(arr, n)
d -= 1
When d == 1, while (d-1) > 0: will not be executed any time. Also, you never decrement d. The easiest way to solve is by using a for _ in range(d) loop:
def leftRotate(arr, d, n):
for _ in range(d):
leftRotatebyOne(arr, n)
NOTE: Python has way better ways to do rotations than this. This code seems to be C more than Python. Passing the array length makes no sense in Python for example. And the rotation can be done all in one assignation.
def leftRotate(arr, d):
d %= len(arr)
for _ in range(d):
arr[-1], arr[:-1] = arr[0], arr[1:]
Cory Kramer's answer is even more pythonic. But it has a bug and a difference with your question's methods. The bug is that it doesn't work when the number of rotations requested are higher than the length of the list. The difference is that they are returning a new list instead of modifying it. These two issues could be addresed like this:
def left_rotate(data, num):
num %= len(data)
data[:] = data[num:] + data[:num]
def right_rotate(data, num):
num %= len(data)
data[:] = data[-num:] + data[:-num]
I have to get K-th smallest element in unsorted array.
Not to sort the whole array I am trying only sort the subarrays that include K-th element. Then I am printing all K-th from 0 to len(array)
array = [6,5,4,3,2,1]
def quick_sort(lst, k):
if len(lst) <= 1:
return lst
else:
p = (lst[0] + lst[len(lst)-1])/2
left = [x for x in lst if x <= p]
right = [x for x in lst if x > p]
if k > len(left) -1 :
k = k - len(left)+1
return quick_sort(right,k)
else:
return quick_sort(left, k)
for i in range(len(array)):
print(*quick_sort(array,i+1))
I want to get 1,2,3,4,5,6
but my code does 2,3,5,6,6,6.
What I need to change?
P.S. THe main idea is not sorting all arrays and not using python sort functions
array = [6, 5, 4, 3, 2, 1]
def quick_sort(lst, k):
if len(lst) <= 1:
return lst
else:
p = (lst[0] + lst[-1]) / 2
left = [x for x in lst if x <= p]
right = [x for x in lst if x > p]
if k > len(left):
k = k - len(left)
return quick_sort(right, k)
else:
return quick_sort(left, k)
for i in range(len(array)):
print(*quick_sort(array, i + 1))
I am challenging myself to write code by hand for the purpose of interviews and I created a sub-par implementation of a recursive MergeSort.
The concept is basically taking two lists "alist" and "blist", and combining/sorting them into list "clist". The lists are assumed sorted and the same size prior to combination.
How can I make the original code (which I know does not work properly) reflect the model code (working as intended) with the fewest amount of changes possible? Knowing the degree of my errors will help me greatly.
Original Code:
alist = [1,5,8,9]
blist = [2,4,7,10]
clist = []
temp = []
def MergeSort(alist,blist):
if len(alist) > 1:
midpoint = len(alist)//2
MergeSort(alist[midpoint:],alist[:midpoint])
if len(blist) > 1:
midpoint = len(blist)//2
MergeSort(blist[midpoint:],blist[:midpoint])
if alist[0] < blist[0]:
temp[0] = alist[0]
alist[0] = blist[0]
blist[0] = temp[0]
MergeSort(alist,blist)
else:
alist[len(alist)] = blist[len(blist)-1]
MergeSort(alist,blist)
if blist[0] == None:
return alist
clist = MergeSort(alist,blist)
print(clist)
Model Code:
alist = [1,5,8,9]
blist = [2,4,7,10]
def MergeSort(alist, blist):
clist = []
if alist == [] and blist != []:
return clist + blist
if alist != [] and blist != []:
if alist[0] <= blist[0]:
clist.append(alist[0])
clist = clist + MergeSort(alist[1:], blist)
if alist[0] > blist[0]:
clist.append(blist[0])
clist = clist + MergeSort(alist, blist[1:])
return clist
print(MergeSort(alist,blist))
There are two part to the algorithm
Merge Sort : Sort a list
Merge : Merge two already sorted lists into a single sorted list
Merge is missing in your code.
Algorithm:
MergeSort(A, B)
1.1 MergeSort(first_half_of_A, second_half_A)
// Now first_half_of_A and second_half_A are in sorted order independently
1.2 Merge(first_half_of_A, first_half_of_A)
// Now A is fully sorted
2.1 MergeSort(first_half_of_B, second_half_B)
2.2 Merge(first_half_of_B, second_half_B)
// Now B is fully sorted
3. Merge(A, B)
Merge(A,B) is simple, since A and B are already sorted scan thought them picking the smallest element each time.
def merge(alist,blist):
temp = list()
i = 0
j = 0
while i < len(alist) and j < len(blist) :
if alist[i] < blist[j] :
temp.append(alist[i])
i += 1
else:
temp.append(blist[j])
j += 1
while i < len(alist):
temp.append(alist[i])
i += 1
while j < len(blist):
temp.append(blist[j])
j += 1
return temp
# Test case
assert merge([1,5,8,9], [1,2,3,4]) == [1, 1, 2, 3, 4, 5, 8, 9]
Now finally the MergeSort
def MergeSort(alist,blist):
if len(alist) > 1:
midpoint = len(alist)//2
MergeSort(alist[midpoint:],alist[:midpoint])
alist[:] = merge(alist[midpoint:], alist[:midpoint])
if len(blist) > 1:
midpoint = len(blist)//2
MergeSort(blist[midpoint:],blist[:midpoint])
blist[:] = merge(blist[midpoint:], blist[:midpoint])
return merge(alist, blist)
# Test Case
assert MergeSort([1,5,8,9], [2,4,7,10]) == [1, 2, 4, 5, 7, 8, 9, 10]
# Testing
import numpy as np
for i in range(1000):
a = np.random.rand(100)
b = np.random.rand(100)
c = np.append(a,b)
assert np.sum(MergeSort(a,b)-np.sort(c)) == 0
I am trying to find out smallest positive number not present in the list a
def smallitem(a):
a = sorted(set(a))
lst = []
for item in a:
item + = 1
if item not in a:
lst.append(item)
continue
mst = []
for item in lst:
if item < 1:
item += 1
if item not in a:
mst.append(item)
continue
n = 0
if mst:
n = min(mst)
return n or min(lst)
I think I have got the solution but it doesnt look correct to me the way I have done it.
for example:
smallitem([-1, -3]) # 1
smallitem([1,3,6,4,1,2, 87]) # 5
You can convert the list to a set and then keep incrementing a positive integer from 1 until it is not found in the set:
def smallitem(a):
set_a = set(a)
i = 1
while i in set_a:
i += 1
return i
Perhaps there's a lighter way do this.
The time complexity is always O(n).
def small_item(a):
s = set(a)
for i in range(1, max(s)):
if i not in s:
return i
return max(max(s) + 1, 1)
print small_item([1,3,6,4,1,2, 87])
print small_item([-1, -3])
Here's anther way to do this:
def smallitem(l):
l = list(set(sorted(l)))
x = l[0]
for i in l:
if i != x and x >= 1:return x
x += 1
return 1
Testing:
>>> smallitem([-3, -1])
1
>>> smallitem([1, 3, 6, 4, 1, 2, 87])
5
>>>
What is the best way to get a list of the smallest N contiguous integers in a Python set?
>>> s=set([5,6,10,12,13,15,30,40,41,42,43,44,55,56,90,300,500])
>>> s
set([42, 43, 44, 5, 6, 90, 300, 30, 10, 12, 13, 55, 56, 15, 500, 40, 41])
>>> smallest_contiguous(s,5)
[40,41,42,43,44]
>>> smallest_contiguous(s,6)
[]
Edit: Thanks for the answers, everyone.
Sven has the right idea. You can avoid having to check supersets by just checking the number N - 1 ahead.
def smallest_contiguous(s, N):
lst = list(s)
lst.sort()
Nm = N-1
for i in xrange(len(lst) - Nm):
if lst[i] + Nm == lst[i + Nm]:
return range(lst[i], lst[i]+N)
return []
This will only always be correct for a set as input and knowing that the set only contains integers.
How about this?
def smallest_contiguous(s, N):
lst = sorted(s)
for i in lst:
t = range(i, i+N)
if s.issuperset(t):
return t
return []
It might not be the most efficient solution, but it is concise.
Edit: Justin's approach could also be made more concise:
def smallest_contiguous(s, N):
lst = sorted(s)
for a, b in zip(lst, lst[N - 1:]):
if b - a == N - 1:
return range(a, b + 1)
return []
That should do it ... look ahead length - 1 steps in the sorted list. Since it contains integers only and is sorted, the difference must be length - 1 as well.
def smallest_contiguous(myset, length):
if len(myset) < length:
return []
s = sorted(myset)
for idx in range(0, len(myset) - length + 1):
if s[idx+length-1] - s[idx] == length - 1:
return s[idx:idx+length]
return []
s=set([5,6,10,12,13,15,30,40,41,42,43,44,55,56,90,300,500])
print smallest_contiguous(s, 5)
print smallest_contiguous(s, 6)
Here's one I came up with:
def smallest_contiguous(s,N):
try:
result = []
while len(result) < N:
min_value = min(s)
s.remove(min_value)
if result == [] or min_value == result[-1] + 1:
result.append(min_value)
else:
result = [min_value]
return result
except ValueError:
return []
It modifies the input set as a side effect.
itertools to the rescue. groupby does all the grunt work here
The algorithm is O(n logn) because of the call to sorted()
>>> from itertools import groupby, count
>>> def smallest_contiguous(s, N):
... for i,j in groupby(sorted(s), key=lambda i,c=count().next: i-c()):
... res = list(j)
... if len(res) == N:
... return res
... return []
...
>>> smallest_contiguous(s,5)
[40, 41, 42, 43, 44]
>>> smallest_contiguous(s,6)
[]
def smallest_contiguous(s, n):
xs = sorted(s)
return next(x for i, x in enumerate(xs) if xs[i + n - 1] == x + n - 1)