Number of pairs [duplicate] - python

I am trying to write a code that takes
m. a, a list of integers
n. b, an integer
and returns the number of pairs (m,n) with m,n in a such that |m-n|<=b.
So far, I've got this
def nearest_pairs(a, b):
m= []
n= int
num_pairs = 0
return num_pairs
def main():
# The nearest pairs are (1,2), (2,1), (2,5) and (5,2)
x = nearest_pairs( [1,2,5] , 3 )
print( "nearest_pairs([1, 2, 5], 3) = " , nearest_pairs([1, 2, 5], 3) )
# The nearest pairs are (1,2) and (2,1)
y = nearest_pairs( [1, 2, 5] , 2 )
print( "nearest_pairs([1, 2, 5], 2) = " , nearest_pairs([1, 2, 5], 2) )
if __name__ == '__main__':
main()
The desired output should look like
>>> nearest_pairs([1,2,5],3) = 4
where 4 is the number of close pairs according to the restrictions. However, I get an error. Could anyone lead me to the right direction?

Yours doesn't make sense. No idea what you're trying with len(a, b), but it's not even allowed, since len takes only one argument. And returning something just when you found the first counting pair? Here's a fix:
def close_pairs(l, d):
ctr = 0
for a,b in permutations(l, 2):
if (a - b) <= d and (b - a) <= d:
ctr += 1
return ctr
And here's how I'd do it:
def close_pairs(l, d):
return sum(abs(a-b) <= d for a, b in permutations(l, 2))

from itertools import permutations
def nearest_pairs(a, b):
for m, n in permutations(a, 2):
if abs(m - n) <= b:
yield (m, n)
>>> list(nearest_pairs([1, 2, 5], 3))
[(1, 2), (2, 1), (2, 5), (5, 2)]
>>> list(nearest_pairs([1, 2, 5], 2))
[(1, 2), (2, 1)]
If you just want the count:
def nearest_pairs_count(a, b):
c, l = 0, len(a)
for i in range(l):
for j in range(i + 1, l):
if abs(a[i] - a[j]) <= b:
c += 2
return c

Related

Function to reverse every sub-array group of size k in python

I did this code so I reverse sub array group of integers but actually it only reverse the first sub array only and I don't know why this is happening!!!
Here is the code:
def reverseInGroups(self, arr, N, K):
rev=list()
count=0
reach=K
limit=0
while limit<N-1:
rev[limit:reach]=reversed(arr[limit:reach])
limit=limit+K
reach=reach+K
if reach==N-1 or reach<N-1:
continue
elif reach>N-1:
reach=N-1
return rev
This is the the input,excpected output and my output:
For Input:
5 3
1 2 3 4 5
Your Output:
1 2 3 4 5
Expected Output:
3 2 1 5 4
I tried your code online and its fine, but you have one logic error in your function to get your desired output.
while limit<N-1:
rev[limit:reach]=reversed(arr[limit:reach])
limit=limit+K #3
reach=reach+K #6
if reach==N-1 or reach<N-1:
continue
elif reach>N-1:
reach=N #5
this is an image to see what I mean image description
You don't have to create new list rev, you can reverse items in list arr. For example:
def reverseInGroups(arr, N, K):
limit = 0
while limit < N:
arr[limit : limit + K] = reversed(arr[limit : limit + K])
limit += K
return arr
l = [1, 2, 3, 4, 5]
print(reverseInGroups(l, 5, 3))
Prints:
[3, 2, 1, 5, 4]
I suggest you use this simpler solution:
arr = [1, 2, 3, 4, 5]
n = 5
k = 3
new_arr = list()
for index in range(0, n - 1, k):
new_arr[index:index+k] = arr[index:index+k][::-1]
print(new_arr)
And the output is:
[3, 2, 1, 5, 4]
After putting this code in your function, it is as below:
def reverseInGroups(self, arr, n, k):
new_arr = list()
for index in range(0, n - 1, k):
new_arr[index:index+k] = arr[index:index+k][::-1]
return new_arr
we can do the loop in the increment of K and then reverse the array of that specific size
def reverseInGroups(self, arr, N, K):
# code here
for i in range(0, N -1 , K):
arr[i:i +K] = arr[i:i +K][::-1]

How to maximise addition/subtraction combinations?

Suppose I have a list of 10 elements [a, b, c, d, e, f, g, h, i, j] and I can multiply each element by 0, 1, 2, -1, -2.
The total of the multiplication factors I use must be equal to zero. Ie if I multiply five numbers by -1 I must multiply the other five by 1, or I can multiply a by 2, b and c by -1 and the rest by 0.
I want to find the list resulting from this operation that has the largest sum.
How can I go about coding this in python?
I've tried coding every single iteration of [2, 1, 0, -1, -2] and deleting the lists that do not add to 0 and then multiplying by the original list, however I got stuck.
You can sort the list, scan it from the ends towards the center, assigning 2 to the larger element and -2 to the smaller.
def baby_knapsack(xs):
xs = sorted(xs, reverse=True)
res = list()
n = len(xs)
for i in range(n//2):
res.extend(((xs[i], 2), (xs[-1-i], -2)))
if n % 2 == 1:
res.append((xs[n//2], 0))
return res
xs = [-10, -5, 0, 5, 10, 15]
# In [73]: q.baby_knapsack(q.xs)
# Out[73]: [(15, 2), (-10, -2), (10, 2), (-5, -2), (5, 2), (0, -2)]

How can I do an operation only for one value on the fly in a numpy array? (or the better way)

I have an array e.g. a = np.arange(0, 5) and it looks like this array([0, 1, 2, 3, 4]).
Now what I want to do is e.g. to add only at the index 2 a value like 5 and get a new numpy array object.
Like this: b = add_value_on_idx(a, 2, 5) # This should return a new object
I have tried this approaches to achieve this
#! /usr/bin/python3.5
import numpy as np
from time import time
# Get a numpy array first
a = np.random.randint(0, 10, (5, ))
# Define a new tuple of zeros with only one number at the
# specific index
def do_add_at_idx_1(arr, idx, val):
return arr+(((0, )*(idx))+(val, )+(0, )*(arr.shape[0]-idx-1))
# Or do it like this
def do_add_at_idx_2(arr, idx, val):
one_val_vec = np.zeros((arr.shape[0], )).astype(arr.dtype)
one_val_vec[idx] = val
return arr+one_val_vec
# Or add it directly to the given array
def do_add_at_idx_3(arr, idx, val):
arr = arr.copy()
arr[idx] += val
return arr
# Or use directly np.add.at function (but need a copy first)
def do_add_at_idx_4(arr, idx, val):
arr = arr.copy()
np.add.at(arr, idx, val)
return arr
a_old = a.copy()
print("a: {}".format(a))
print("do_add_at_idx_1(a, 2, 5): {}".format(do_add_at_idx_1(a, 2, 5)))
print("do_add_at_idx_2(a, 2, 5): {}".format(do_add_at_idx_2(a, 2, 5)))
print("do_add_at_idx_3(a, 2, 5): {}".format(do_add_at_idx_3(a, 2, 5)))
print("do_add_at_idx_4(a, 2, 5): {}".format(do_add_at_idx_4(a, 2, 5)))
print("Was 'a' modified? {}".format("No." if np.all(a==a_old) else "YES!!"))
Which will output something like this:
a: [6 6 9 2 8]
do_add_at_idx_1(a, 2, 5): [ 6 6 14 2 8]
do_add_at_idx_2(a, 2, 5): [ 6 6 14 2 8]
do_add_at_idx_3(a, 2, 5): [ 6 6 14 2 8]
do_add_at_idx_4(a, 2, 5): [ 6 6 14 2 8]
Was 'a' modified? No.
I have also tested the time differences for these functions too:
n = 100000
print("n: {}".format(n))
idxs = np.random.randint(0, a.shape[0], (n, ))
vals = np.random.randint(0, 10, (n, ))
for i in range(1, 5):
func_name = "do_add_at_idx_{}".format(i)
func = globals()[func_name]
start = time()
for idx, val in zip(idxs, vals):
func(a, idx, val)
delta = time()-start
print("Taken time for func '{}': {:2.4f}s".format(func_name, delta))
With this as an output:
Taken time for func 'do_add_at_idx_1': 2.1899s
Taken time for func 'do_add_at_idx_2': 1.4600s
Taken time for func 'do_add_at_idx_3': 0.5757s
Taken time for func 'do_add_at_idx_4': 2.8043s
Are there any better ways to do this approach?

oneliner using pandas or numpy

How would I implment this code using pandas or numpy?
x =[]
for i in xrange(1,6):
x.append(i)
print x
combi = (list(itertools.permutations(x, 5)))
for i in combi:
print i
l = (i[0]) + abs(i[0] - i[1]) + abs(i[1] - i[2]) + abs(i[2] - i[3]) + abs(i[3] - i[4])
print l
output of combi is
(1, 2, 3, 4, 5)
(1, 2, 3, 5, 4)
(1, 2, 4, 3, 5)
(1, 2, 4, 5, 3)
I try to add the first number in each tuple to difference of second third 4th and fifth for each tuple which give me this
5
6
7
7
easier if increase my range to 10 i will have to write the code for variable l upto 10.
You are taking the diff between subsequent elements, and then summing the abs of those diffs and then you add to that, the first element in the sequence:
Code:
for i in it.permutations(xrange(1, 6), 5):
k = i[0] + sum(np.abs(np.diff(i)))
Test Code:
import numpy as np
import itertools as it
for i in it.permutations(xrange(1, 6), 5):
k = i[0] + sum(np.abs(np.diff(i)))
l = (i[0]) + abs(i[0] - i[1]) + abs(i[1] - i[2]) + abs(i[2] - i[3]) + abs(i[3] - i[4])
assert l == k

Python, finding neighbors in a 2-d list

So here's the issue, I have a 2-d list of characters 'T' and 'F', and given coordinates I need to get all of its neighbors. I have this:
from itertools import product, starmap
x, y = (5, 5)
cells = starmap(lambda a, b: (x + a, y + b), product((0, -1, +1), (0, -1, +1)))
from determining neighbors of cell two dimensional list But it will only give me a list of coordinantes, so i still fetch the values afterwords. I'd like the search and retrieval done in one step, so findNeighbors(5,5) would return F,T,F,F,... instead of (5, 4), (5, 6), (4, 5), (4, 4)... Is there a fast way of doing this? The solutin can include a structure other than a list to hold the initial information
The following should work, with just a minor adaptation to the current code:
from itertools import product, starmap, islice
def findNeighbors(grid, x, y):
xi = (0, -1, 1) if 0 < x < len(grid) - 1 else ((0, -1) if x > 0 else (0, 1))
yi = (0, -1, 1) if 0 < y < len(grid[0]) - 1 else ((0, -1) if y > 0 else (0, 1))
return islice(starmap((lambda a, b: grid[x + a][y + b]), product(xi, yi)), 1, None)
For example:
>>> grid = [[ 0, 1, 2, 3],
... [ 4, 5, 6, 7],
... [ 8, 9, 10, 11],
... [12, 13, 14, 15]]
>>> list(findNeighbors(grid, 2, 1)) # find neighbors of 9
[8, 10, 5, 4, 6, 13, 12, 14]
>>> list(findNeighbors(grid, 3, 3)) # find neighbors of 15
[14, 11, 10]
For the sake of clarity, here is some equivalent code without all of the itertools magic:
def findNeighbors(grid, x, y):
if 0 < x < len(grid) - 1:
xi = (0, -1, 1) # this isn't first or last row, so we can look above and below
elif x > 0:
xi = (0, -1) # this is the last row, so we can only look above
else:
xi = (0, 1) # this is the first row, so we can only look below
# the following line accomplishes the same thing as the above code but for columns
yi = (0, -1, 1) if 0 < y < len(grid[0]) - 1 else ((0, -1) if y > 0 else (0, 1))
for a in xi:
for b in yi:
if a == b == 0: # this value is skipped using islice in the original code
continue
yield grid[x + a][y + b]

Categories

Resources