I have nx4 matrix. I need to find max value and it's index. I use
[mVal,mInd]=max(A,[],2)
When a row contains same value more than once and it is the max value I need to find all indices of the row.
Example: Say A(10,:) is [-1.2 1.6 1.6 1.6] I need to return 2,3,4 as indices.
Try this:
A(10,:)=[-1.2 1.6 1.6 1.6];
[i,j]=find(A==max(max(A)))
The row indices of the maxima should be in the vector i, the column indices in j.
Related
I have a diagonal matrix and a matrix of same dimensions. How do I arrange the diagonal matrix in ascending order and then do the same steps on the other matrix ? For example if my matrix is 3 x 3, and I have to swap the 1st and 2nd column entries in diagonal to make it ascending, how do I apply this same set of steps to the other matrix but here I swap the whole 1st and 2nd column?
I thought about using some kind of merge sort but then it will not arrange the values on the diagonals. How do I do that ?
To sort a set of values, you usually have to reorder them. You can do so by sorting the directly, but you can also sort them indirectly, by first computing a sequence of indices which tells you how you would reorder the sequence. In Python, this sequence can be obtained by the numpy.argsort method. Once you have the sequence, you can apply it to sort your set of numbers, but you can also use it to rearrange any array of values in the same way. Here is an example:
import numpy as np
# construct example matrices
n = 4
D = np.diag(np.random.rand(n))
A = np.random.rand(n,n)
# obtain a sequence of indices that would sort the array.
idx = np.argsort(np.diag(D))
# order the diagonal entries according to the sequence
Dp = np.diag(np.diag(D)[idx])
# order the columns according to the sequence
Ap = A[:,idx]
print('idx')
print(idx)
print('D:')
print(D)
print('Dp:')
print(Dp)
print('A:')
print(A)
print('Ap:')
print(Ap)
Note, in Matlab the index sequence that sorts a sequence is given in the second return value of the sort function.
A standard problem in many languages is to sort an array and sort the indices as well. So for instance, if a = {4,1,3,2} the sorted array is b = {1,2,3,4} and the original indices moved would be {1,3,2,0}. This is easy to do by sorting a vector of pairs for instance.
What I want instead is an array c so that c[i] is the new position of element a[i] in the array b. So, in my example, c = {3,0,2,1} because 4 moves to position 3, 1 moved to position 0 and so on.
One way is to look up each element a[i] in b (perhaps using binary search to reduce lookup time) and then add the corresponding index in c. Is there a more efficient way?
Can you assume that you have the array of originally indices moved? It's the only array above that you didn't assign to a variable. If so, one efficient way of solving this problem is to back calculate it from that array of original indices moved.
You have that as {1,3,2,0}. All you need to do it march through it and put each values index at the value indicated.
So index 0 has a 1. That means at index 1 of the new array there should be a zero. Index 1 is a 3, so at index 3 of the new array put a 1. You would get your goal of {3,0,2,1}
I have a bag that has the following:
6 red marbles
5 green marbles
2 blue marbles
I want to remove a random marble from the bag, record its color, and repeat until no more marbles are left in the bag:
sort the counts
bag = {2:blue, 5:green, 6:red}
compute the cumulative counts
cumulative = {2:blue, 7:green, 13:red}
pick a random number in [0, max cumulative count]
rand(0, 13) = 3
find insertion point index of this integer using binary search
i = 1
record the color corresponding to this index
green
reduce that count by 1
bag = {2:blue, 4:green, 6:red}
repeat until no more marbles in bag
Is this a good way to do this or are there more efficient ways in terms of time complexity?
Your algorithm is pretty good, but it could be optimized further:
You don't need to sort the colors! You can skip the first step.
Instead of calculating the cumulative counts each time you can do it iteratively by decreasing all values right of the selected one (including the selected color itself).
You also don't need the binary search, you can just start decreasing the cumulative counts from the end until you reach the correct number.
There is also another algorithm based on lists:
Create a list with all the items (0=red, 1=green, 2=blue): [0,0,0,0,0,0,1,1,1,1,1,2,2].
Get a random integer i between 0 and the size of the list - 1.
Remove the ith item from the list and add it to the result.
Repeat 2. and 3. until the list is empty.
Instead of relying on extraction, you can shuffle the array in-place.
like in maraca's answer, you store the items individually in the array (citing it here: "Create a list with all the items (0=red, 1=green, 2=blue): [0,0,0,0,0,0,1,1,1,1,1,2,2].")
iterate through the array and, for each element i, pick a random index j of an element to swap place with
at the end, just iterate over the array to get a shuffled order.
Something like
for(i=0..len-1) {
j=random(0..len-1);
// swap them
aux=a[i]; a[i]=a[j]; a[j]=aux;
}
// now consume the array - it is as random as it can be
// without extracting from it on the way
Note: many programming languages will have libraries providing already implemented array/list shuffling functions
C++ - std::random_shuffle
Java - Collections.shuffle
Python - random.shuffle
If you have a binary matrix of 1s and 0s, and you are able to toggle columns (change all 1s to 0s in the column, and all 0s to 1s), how do you find the max number of "pure" rows for all possible combinations of column toggles?
"pure" meaning the row is all 0s, or all 1s.
Ex:
1 0
1 0
1 1
You can toggle either column to get 2 rows that are "pure", which is the best you can do (toggling both is not better), so you return 2 (the max number of "pure" rows).
I can't seem to figure out an efficient way to do this. The only way I've gotten so far is with a bunch of loops and brute force and checking for sameness by checking if the sum of a row is either 0 (all 0s) or N (the number of elements in a row).
Update
After clarification from the OP, the max-pure row problem is to find the max number of rows that become either 00...0 or 11...1 after toggling. I have updated my solution accordingly.
Note that we have the following facts:
If two rows ri and rj reduce to a pure row after toggling, then we must have ri = rj to start with.
If ri ≠ rj and ri overlaps rj (i.e. some of their corresponding column are the same), then both of them cannot map to a pure row.
Both of the facts above comes directly from the following observation:
Max number of "pure" rows is the same as the max number of identical rows
Proof
We claim that all the rows that constitute a solution of the max-pure problem must be identical in the matrix M.
Suppose we are given a m-by-n matrix M, and we have found a solution of the max-pure row problem. Let rows ri and rj be two arbitrary rows that get reduce to pure rows after toggling.
Observe that after all the necessary toggling operation on the columns (denote by σ1, σ2, ..., σk), ri and rj are both "pure" rows. i.e. We have the following:
σ1(σ2(...(σk(ri)...)) = σ1(σ2(...(σk(rj)...)) = 00...0
or
σ1(σ2(...(σk(ri)...)) = σ1(σ2(...(σk(rj)...)) = 11...1
So after applying all these toggling operations, ri and rj will equal each other. If we undo the very last toggling (i.e. we toggling the same column entry of these rows), it is obviously that both ri and rj will still map to the same output. i.e. We have the following:
σ2(σ3(...(σk(ri)...)) = σ2(σ3(...(σk(rj)...))
If we we continue undoing the toggling operations, we can conclude that ri = rj. In other words, if you pick any arbitrary rows from a solution of the max-pure problem, these rows must be identical in the beginning.
Idea
Given a row ri, if it can be reduce to the pure row, say 00...0, then we know that another row rj cannot be reduced to 11...1 if ri overlaps with rj (from fact 2 above). We can only hope that another row rk which does not overlap with ri to reduce to 11...1.
Algorithm
From the preceding idea, we can have the following simple algorithm to solve the max-pure row problem.
We first scan over the rows of matrix M, and then find all the unique rows of the matrix (denote by s1, s2, ..., sk). We let count(si) denotes the number of times si appears in M.
We then loop over all the pairs (si, sj) to determine the max-pure row number as below:
int maxCount = 0;
for each row si:
for each sj ≠ si:
if (sj overlaps si)
continue;
else
if (count(si) + count(sj) > maxCount)
// We have found a better pair
maxCount = count(si) + count(sj);
return maxCount;
We are doing O(n) works in the inner for loop (for entry-wise checking whether two rows overlap), and the loops are over O(m2) rows in the worst-case, so the running time of the algorithm is O(nm2).
Maybe I'm missing something, but a quick run down the rows should answer your question.
Start with the top row, and flip each column as needed until the top row is all T. Count the number of pure rows. Repeat for every other row, finding if the count is greater than any previous row.
You don't need to invert the whole matrix so each row is all F, the count will be the same.
The worst-case running time would be O(nm).
i need to write algo for this problem. i have never written an algo before . please correct me.
there is a list which contains four collumns each with numbers with upto 5 digits and about 10 rows in total. we have to remove the rows containng any number with less than 3 digits.
here is how i have tried
read list into multi-dimensional array
for each number in the array
if numdigits < 3
delete all numbers of that row
i know this is not the correct algorithm . can you help me correct it .
When creating your original list, rather check the individual values then, and not add it to that list if any of the numbers has less than 3 digits, that way reducing the original list size.
EDIT:
foreach row in original_document
{
bool allMoreThan3Digits = true
foreach cell in row
allMoreThan3Digits = allMoreThan3Digits && (ABS(cell.Value) >= 100)
if (allMoreThan3Digits)
add row to new list
}
Something like that.
With up to 5 digits in total in each column? If so here is what I would do.
For each row in list
For each column in row
if column number < 100 then
row delete