Why is the last element repeating? - python

I'm trying to find the diagonal and counter diagonal elements for a given list. The function is written below:
def diagonalDifference(arr):
side_1=0
side_2 =0
for row in arr:
for column in row:
if(arr.index(row)==row.index(column)):
side_1+=column
if(arr.index(row)+row.index(column)==(len(arr)-1)):
print(arr.index(row),row.index(column)) #(1)index for counter diagonal
side_2+=column
return(abs(side_1-side_2))
Edit: The values passed are:
(-1 1 -7 -8),
(-10 -8 -5 -2),
(0 9 7 -1),
(4 4 -2 1)
The result of (1) is:
(0,3),
(1,2),
(2,1),
(3,0),
(3,0)
The repeated values 4, 4 in the position [3][0],[3][1] is generating the problem

As you've noted, with repeating values, your index lookup fails. You are also iterating over the every value instead of just the ones you want (the diagonals). Rather than taking the entries of the list and then finding their index (with index method), just use the indices to start with.
>>> a = ((-1, 1, -7, -8), (-10, -8, -5, -2), (0, 9, 7, -1), (4, 4 ,-2, 1))
>>> d1 = d2 = 0
>>> dim = len(a)
>>> for i in range(dim):
... d1 += a[i][i]
... d2 += a[i][dim-i-1]
...
>>> print(d1, d2)
-1 0
You may want some validation that all the lists are the same length and that the array is square, but if you can assume that, this should be ok.

Related

Accessing column in sparse CSR matrix

Having some issues with accessing the last column in the sparse CSR matrix. Ideally, I would like to convert the last column into some sort of array that can be used as my label set. My CSR matrix looks like this:
(0, 1976) 1
(0, 2916) 1
(0, 3871) 1
(0, 4437) 1
(0, 8202) 1
(0, 9458) 1
(0, 10597) 1
(1, 4801) 1
(1, 6903) 1
(1, 7525) 1
(2, 873) 1
(2, 1017) 1
(2, 1740) 1
(2, 1925) 1
(3, 1976) 1
(3, 5606) 1
(3, 6898) 1
I want to access the last column, which contains all the '1'. Is there a way in which I can do this?
CSR matrix has indicies and indptr properties, see below example which converts matrix to list using these properties:
def sparse_to_string_list(matrix: csr_matrix):
res = []
indptr = matrix.indptr
indices = matrix.indices
for row in range(matrix.shape[0]):
arr = [k for k in indices[indptr[row]: indptr[row + 1]]]
arr.sort()
res.append(' '.join([str(k) for k in arr]))
return res

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)]

Pandas: return index values for first instance and last instance of value

I have the following DataFrame:
df = pd.DataFrame({'index':[0,1,2,3,4,5,6,7,8,9,10], 'X':[0,0,1,1,0,0,1,1,1,0,0]})
df.set_index('index', inplace = True)
X
index
0 0
1 0
2 1
3 1
4 0
5 0
6 1
7 1
8 1
9 0
10 0
What I need is to return a list of tuples showing the index value for the first and last instances of the 1s for each sequence of 1s (sorry if that's confusing). i.e.
Want:
[(2,3), (6,8)]
The first instance of the first 1 occurs at index point 2, then the last 1 in that sequence occurs at index point 3. The next 1 occurs at index point 6, and the last 1 in that sequence occurs at index point 8.
What I've tried:
I can grab the first one using numpy's argmax function. i.e.
x1 = np.argmax(df.values)
y1 = np.argmin(df.values[x1:])
(x1,2 + y1 - 1)
Which will give me the first tuple, but iterating through seems messy and I feel like there's a better way.
You need more_itertools.consecutive_groups
import more_itertools as mit
def find_ranges(iterable):
"""Yield range of consecutive numbers."""
for group in mit.consecutive_groups(iterable):
group = list(group)
if len(group) == 1:
yield group[0]
else:
yield group[0], group[-1]
list(find_ranges(df['X'][df['X']==1].index))
Output:
[(2, 3), (6, 8)]
You can use a third party library: more_itertools
loc with mit.consecutive_groups
[list(group) for group in mit.consecutive_groups(df.loc[df.ones == 1].index)]
# [[2, 3], [6, 7, 8]]
Simple list comprehension:
x = [(i[0], i[-1]) for i in x]
# [(2, 3), (6, 8)]
An approach using numpy, adapted from a great answer by #Warren Weckesser
def runs(a):
isone = np.concatenate(([0], np.equal(a, 1).view(np.int8), [0]))
absdiff = np.abs(np.diff(isone))
ranges = np.where(absdiff == 1)[0].reshape(-1, 2)
return [(i, j-1) for i, j in ranges]
runs(df.ones.values)
# [(2, 3), (6, 8)]
Here's a pure pandas solution:
df.groupby(df['X'].eq(0).cumsum().mask(df['X'].eq(0)))\
.apply(lambda x: (x.first_valid_index(),x.last_valid_index()))\
.tolist()
Output:
[(2, 3), (6, 8)]

How to get the position of the highest value in a row of a matrix

I need to create a program that, given a matrix, asks for a row in the matrix and gives the position of the highest value in that row.
For example with the matrix:
D = [(0 1 3),
(1 0 4),
(3 4 0)]
when given the value 2 should return 1 (because in the row[2] the highest value is 4 which is in position 1 in that row).
Right now I'm trying:
def farthest(matrix, row, point):
maxdist = 0
matrix2 = []
for i in range(0, len(matrix)):
if i == int(point):
matrix2.append(i)
if i != int(point):
pass
for j in range(0, len(matrix2)):
if j < maxdist :
pass
if j > maxdist:
maxdist = maxdist + j
print(matrix2)
print(maxdist)
return matrix2
I should find a solution using loops.
The current output that I get is [2] and [0].
You can use numpy and argmax for axis 1 for this, to get the position of the maximum value per row.
import numpy as np
D = [(0, 1, 3),
(1, 0, 4),
(3, 4, 0)]
t = np.array(D).argmax(axis=1)
t
Which will give you
array([2, 2, 1])
Can can then index with the row you are after
t[2]
1

Maximum number of elements in the path of a matrix

I tried to solve a problem of map (matrix 4x4) using python.
I want to find Maximum number of elements in the path of a map provided the next node must be lesser than the previous node with all possible combinations of elements in the matrix.
4 8 7 3
2 5 9 3
6 3 2 5
4 4 1 6
The movement is like from an element can move to east-west-north-south
For example from m[0][1] can move to m[0][2] and m[1][1] 4-> 8 or 2
Here is the sample code but i have no idea to how to recursively check every element.
#import itertools
n = 4
matrix = [[4, 8, 7, 3 ], [2, 5, 9, 3 ], [6, 3, 2, 5 ], [4, 4, 1, 6]]
for index,ele in enumerate(matrix):
vals=[]
for i2,e2 in enumerate(ele):
for index2,ele2 in enumerate(ele):
if index < (n-1):
if ele2 > matrix[index+1] [index2]:
vals.append(matrix[index+1] [index2])
if index > 0:
if ele2 > matrix[index-1] [index2]:
vals.append(matrix[index-1] [index2])
if index2 < n-1:
if ele2 > matrix[index] [index2+1]:
vals.append(matrix[index] [index2+1])
if index2 >0:
if ele2 > matrix[index] [index2-1]:
vals.append(matrix[index] [index2-1])
how to recurse this function to loop till the end
For Example the answer will be like 8-5-3-2-1 (Longest Path with decreasing factor)
Try this recursion: The longest path starting at element (x, y) is the longest longest path starting at any of its strictly smaller neighbors, plus 1.
def longest_path(matrix):
def inner_longest_path(x, y):
best, best_path = 0, []
# for all possible neighbor cells...
for dx, dy in ((+1, 0), (-1, 0), (0, +1), (0, -1)):
# if cell is valid and strictly smaller...
if (0 <= x + dx < len(matrix) and 0 <= y + dy < len(matrix[x])
and matrix[x+dx][y+dy] < matrix[x][y]):
n, path = inner_longest_path(x+dx, y+dy)
# check if the path starting at that cell is better
if n > best:
best, best_path = n, path
return best + 1, [matrix[x][y]] + best_path
return max(inner_longest_path(x, y) for x, row in enumerate(matrix)
for y, _ in enumerate(row))
Note that this will do a lot of duplicate calculations. Adding memoization is left as an excercise to the reader.
Example:
>>> longest_path(matrix)
(5, [9, 5, 3, 2, 1])

Categories

Resources