This is the array.
arr=[1,2,2,1,5,1]
i need to calculate the abs value of index differences between in and all the other elements if the same value, like explained below.
distance metric for a[0] = |0-3|+|0-5|=8
distance metric for a[1] = |1-2|=1
distance metric for a[2] = |2-1|=1
distance metric for a[3] = |3-0|+|3-5|=5
distance metric for a[4] = 0
distance metric for a[5] = |5-0|+|5-3|=7
output is
[8,1,1,5,0,7]
can someone help in coding this in python.
You can use this working example:
arr=[1,2,2,1,5,1]
res = []
for i, n in enumerate(arr):
val = 0
occur = [j for j, x in enumerate(arr) if x == n and j != i]
for o in occur:
val += abs(i-o)
res.append(val)
print(res)
[8, 1, 1, 5, 0, 7]
a bit more efficient version with a complexity of O(n**2)
arr=[1,2,2,1,5,1]
res = []
for i, n in enumerate(arr):
val = 0
for j, x in enumerate(arr):
if x == n and j != i:
val += abs(i-j)
res.append(val)
print(res)
Using list comprehensions and avoiding intermediate variables
arr = [1, 2, 2, 1, 5, 1]
output = []
for index in range(len(arr)):
output.append(sum(abs(index - k) if arr[k] == arr[index] else 0 for k in range(len(arr))))
print(output)
Related
I am given undirected graph that consists of N vertices numbered from 0 to N-1 connected with M edges.The graph is described by two arrays, A and B both of length M. A pair ([A[k],B[k]) describes edge between A[k] and B[k] for k from 0 to M-1.
Each second every vertex with at most 1 edge connected to disappears.Every edge which is connected to one of disappearing vertices also disappears.
After how many seconds will the vertices stop disappearing.
For N=7, ((0,1),(1,2),(2,0),(1,4),(4,5),(4,6)) answer should be 2.
def solution(N,A,B):
d2 = dict.fromkeys(range(N), 0)
count = 0
arr = []
for i in range(len(A)):
arr.append((A[i],B[i]))
while True:
for i in range(len(A)+1):
for c in arr:
if i in c:
d2[i] += 1
arr1 = arr
for i in range(len(A)+1):
if d2[i] <= 1:
arr = list(filter(lambda x: x[1] != i and x[0] != i, arr))
if len(arr) == len(arr1):
return count + 1
break
count += 1
Here is my code.For this test case (4, [0, 1, 2, 3], [1, 2, 3, 0]) it outputs Keyerror: 4. Can you help me to solve the problem.Thank you.
Try this (I inserted a couple of print() to let you see what's going on):
def solution(N, A, B):
linked = defaultdict(list)
for i in range(len(A)):
linked[A[i]].append(B[i])
linked[B[i]].append(A[i])
changed = True
seconds = 0
removing = []
while changed:
changed = False
seconds += 1
print(f'second {seconds}')
for i in list(linked.keys())[:]:
if len(linked[i]) > 1:
continue
if len(linked[i]) == 1:
removing.append((linked[i][0],i))
del linked[i]
changed = True
for i,j in removing:
print(f'remove {j} from {i}')
linked[i].remove(j)
removing = []
return seconds - 1
I've come across this question:
Given an integer array nums, return all the triplets [nums[i], nums[j], nums[k]] such that i != j, i != k, and j != k, and nums[i] + nums[j] + nums[k] == 0.
Notice that the solution set must not contain duplicate triplets.
Here's the most optimized solution:
nums = [-22, -5, -4, -2, -1, -1, 0, 1, 2, 11, 11, 22, 100]
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
if len(nums) < 3:
return []
counter = {}
for i in nums:
if i not in counter:
counter[i] = 0
counter[i] += 1
nums = sorted(counter)
if nums[0] > 0 or nums[-1] < 0:
return []
output = []
# find answer with no duplicates within combo
for i in range(len(nums)-1):
# search range
twoSum = -nums[i]
min_half, max_half = twoSum - nums[-1], twoSum / 2
l = bisect_left(nums, min_half, i + 1)
r = bisect_left(nums, max_half, l)
for j in nums[l:r]:
if twoSum - j in counter:
output.append([nums[i], j, twoSum - j])
# find ans with duplicates within combo
for k in counter:
if counter[k] > 1:
if k == 0 and counter[k] >= 3:
output.append([0, 0, 0])
elif k != 0 and -2 * k in counter:
output.append([k, k, -2 * k])
return output
Can someone explain why:
min_half = twoSum - nums[-1]
max_half = twoSum/2
I understand we need to find the range of the remaining two numbers and what bisec_left and bisect_right does. But why min_half and max_half that way?
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'm trying to implement a merge sort in Python. I completed a merge sort lesson on Khan Academy where they had me implement it in JavaScript, but I wanted to try and implement it in Python.
Lesson: https://www.khanacademy.org/computing/computer-science/algorithms#merge-sort
Here is my code:
from math import floor
def merge(array, p, q, r):
left_array = []
right_array = []
k = p
while (k < q):
left_array.append(array[k])
k += 1
while (k < r):
right_array.append(array[k])
k += 1
k = p
i = 0
j = 0
while (i < len(left_array) and j < len(right_array)):
if (left_array[i] <= right_array[j]):
array[k] = left_array[i]
k += 1
i += 1
else:
array[k] = right_array[j]
k += 1
j += 1
while (i < len(left_array)):
array[k] = left_array[i]
k += 1
i += 1
while (j < len(right_array)):
array[k] = right_array[j]
k += 1
j += 1
print("Merging", array)
def merge_sort(array, p, r):
print("Splitting", array)
if p < r:
q = floor((p + r) / 2)
merge_sort(array, p, q)
merge_sort(array, q + 1, r)
merge(array, p, q, r)
test3 = [3, 2, 1]
merge_sort(test3, 0, len(test3))
There's a bug somewhere in my code and I can't seem to get it. I think that it has to do with my splicing, but I haven't been able to confirm this. Here is my output for the test at the bottom:
Splitting [3, 2, 1]
Splitting [3, 2, 1]
Splitting [3, 2, 1]
Splitting [3, 2, 1]
Merging [3, 2, 1]
Splitting [3, 2, 1]
Splitting [3, 2, 1]
Splitting [3, 2, 1]
Merging [3, 2, 1]
Merging [2, 1, 3]
I took the idea of adding print statements from here.
Any help is appreciated. Thank you!
Your code is not following the conventions of the text you linked to on whether the bounds are exclusive or inclusive. In the text, they are inclusive, but in your code they are exclusive of the upper bound. As a result, when you have these two lines:
merge_sort(array, p, q)
merge_sort(array, q + 1, r)
the first sorts array[p] through array[q-1], the second sorts array[q+1] through array[r-1], and you end up completely skipping array[q].
I think you will find it easier to follow the conventions of the text and make both bounds inclusive. So modify you code, start with
test3 = [3, 2, 1]
merge_sort(test3, 0, len(test3) - 1)
, and go from there.
You can also clean up your code greatly by using python slice notation. For example:
left_array = []
right_array = []
k = p
while (k < q):
left_array.append(array[k])
k += 1
while (k < r):
right_array.append(array[k])
k += 1
can be simplified to
left_array = array[p:q]
right_array = array[q:r]
although, as I stated, you'll probably want to start using inclusive indices.
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.