I am new to Matlab and thus this could be a very trivial question and I appreciate those who take the time to help. I have a 618x2 matrix that has values in the first column and then the index of the value (circles on an image for this case). For example
46.9810, 1
0, 2
0, 3
0, 4
43.1429, 5
0, 6
0, 7...
This matrix is called 'Test2'
I have another matrix that is a 1x58 matrix (called overlapindex) The values in this matrix correspond to the index in the 'Test2' matrix
for example:
1, 3, 5, 7, 35, 37, 44, 49,....
I need a new matrix (let's call it NEW) that checks if the value in overlapindex has a nonzero correlating value in the 'Test2' matrix. For example, this NEW matrix would include [43.1429, 5] because the index is in both 'Test2' and also in 'overlapindex' and the corresponding value in 'Test2' is nonzero.
so essentially this 'NEW' matrix would look like...
46.9810, 1
43.1429, 5
and so on until all the indexes are checked and the 'NEW' matrix is made.
I just need to make sure that the index in 'overlapindex' corresponds to an actual non zero value in the 'Test2' matrix.
Please help and thank you in advance!
Your problem can be solved using logical indexing in Matlab:
NEW = Test2(overlapindex(Test2(overlapindex, 1) ~= 0), :)
Explanation
Test2(overlapindex, 1): rows which should be checked (accessing Nonconsecutive Elements)
Test2(overlapindex, 1) ~= 0: checks for every requested row if the condition is true
overlapindex(Test2(overlapindex, 1) ~= 0): indexes of the matched rows (logical indexing)
Note that this solution only works if overlapindex only contains existing indexes of Test2, but the solution could be easily extended to skip non-existing indexes.
Related
I am doing the tictactoe project from the Cisco NetAkad course : https://www.youtube.com/watch?v=7GDtI9SpGgU
I did the game disregarding the stated project requirements.
I used for the board a normal list: board = [1, 2, 3, 4, 5, 6, 7, 8, 9]
The programm works and and the output is the same as the project asks for.
The project requirements state however specifically to use a 2D list: board = [[1, 2, 3], [4, 5, 6], [7, 8, 9]. As I wanted to practise using 2D lists I rewrote the programm and found it requires more lines and more complex indexing.
My 1st question is: in the function, which checks whether there is a winner, is it possible with a 2D list to just use indexing to check whether there are 3 consecutive "X" or "O" for all directions? If yes, how?
(I don't think writing the massive amount of 'if' combined with many 'and', like in the video, is efficient and using indexing works well with a normal list)
As a beginner my wording might be unclear, so here is the section checking whether "X" has won and below what I expect it to do:
if board[0][0:3].count("X") == 3 or board[1][0:3].count("X") == 3 \
or board[2][0:3].count("X") == 3 or board[0:3][0].count("X") == 3 \
or board[0:3][1].count("X") == 3 or board[0:3][2].count("X") == 3 \
or board[0:3][0:3].count("X") == 3 or board[0:3][3::-1].count("X") == 3:
print("I won: you lost.")
The index [0][0:3], [1][0:3] and [2][0:3] work as expected (rows), it recognises the win.
However [0:3][0] is being read as [0][0:3] when the programm is run. (checking colums doesn't work)
[0:3][0:3] and [0:3][3::-1] obviously doesn't work (diagonal).
2nd question: What better way is there to check for a winner?
Last question: Is there an advantage of using a 2D list over a normal list in this case?
I am thankful in advance for any feedback.
You can do something like below:
for key in ['X', 'O']:
temp = []
count = 0
for row in board:
if row.count(key) == 3:
count = 3
break
if key in row:
temp.append(row.index(key))
if count == 3 or (len(list(set(temp))) == 1 and len(temp) == 3) or temp in ([0,1,2], [2,1,0]):
print("I won: you lost. " + key + " wins")
The idea of the solution is to get the indexes of the positions of 'X' in the inner lists (the usage of indexes justifies the reason to go for a '2D list' [list of lists] per your last question). This is done by looping over the list per 'row' of the tic-tac-toe. We store the indexes in the variable 'temp'.
The first condition checks whether a row has 3 'X's and if yes, it breaks the execution of the for loop saving a count=3. The second condition is the most interesting because it stores the index of 'X' in the row. For example, when you have X in the middle column, at the end of the loop, temp will be equal to:
[2,2,2] if the tic-tac-toe was
O-X-
O-X-O
-X-O
Consequently, if there is a single unique number in the 'temp' list ([1,1,1] unique is 1, [2,2,2] unique is 2 etc), then there is a winner. This is done by:
len(list(set(temp))) # (inside) Get unique values / Make it a list / Measure its length
If the length is 1, then there is a unique position. In addition to that, and to account for the code running while the tic-tac-toe is not entirely filled, we check for len(temp) == 3. Finally, we check for a diagonal match using the 'temp in ([0,1,2], [2,1,0])' part of the condition
The reason why the 'index [0:3][0]' does not work as you expect it to, is because the first slice points to the entire list for which you are taking the value at position 0 which is [1,2,3]. In other words board[0:3] is equal to board
Since there are so few potential states and only 8 winning states, I might just go directly with evaluating them all:
gameboard = [
["x","-","-"],
["x","-","-"],
["x","-","-"]
]
possilbe_winning_states = [
[(0,0), (0,1), (0,2)],
[(1,0), (1,1), (1,2)],
[(2,0), (2,1), (2,2)],
[(0,0), (1,0), (2,0)],
[(0,1), (1,1), (2,1)],
[(0,2), (1,2), (2,2)],
[(0,0), (1,1), (2,2)],
[(0,2), (1,1), (2,0)]
]
for possilbe_winning_state in possilbe_winning_states:
squares = [gameboard[square[0]][square[1]] for square in possilbe_winning_state]
if squares.count("x") == 3:
print("X Win")
break
elif squares.count("o") == 3:
print("O Win")
break
else:
print("no winner yet")
Let's say we have a DATA array consisting of 23 elements,
And INDICATORS array of 3 elements (might be whatever size you want: 3, 5, 7 etc but less then DATA array)
Let's say I'm iterating over DATA array, and starting from, say, index 4 in the DATA array, I need to start highlighting INDICATORS one by one, starting from the first, then second, then third and then wrapping back to the first.
For example:
DATA indexes:0...(4, 5, 6) (7, 8, 9)...22
INDICATORS indexes: (0, 1, 2) (0, 1, 2) ... etc
So basically I need to convert index 4 of DATA array to index 0 of the INDICATORS array, index 5 of DATA array to index 1 of the INDICATORS array etc.
dataArrayIndex % indicatorsArraySize doesn't work in this case.
How do I do that?
Thanks.
dataArrayIndex % indicatorsArraySize
Won't work for you because you have that starting index.
Instead, you have to subtract your starting index from the dataArrayIndex first:
(dataArrayIndex - dataStartIndex) % indicatorsArraySize
Alternatively, as you iterate, you can compare your current indicatorsArrayIndex to indicatorsArraySize, after incrementing indicatorsArrayIndex. If they're equal, reset indicatorsArrayIndex to 0.
I need to design an algorithm that finds the k'th smallest element in unsorted array using function that called "MED3":
This function finds the n/3 (floor) and 2n/3 (ceil) elements of the array if it was sorted (very similar to median, but instead of n/2 it returns those values).
I thought about kind of partition around those 2 values, and than to continue like QuickSelect, but the problem is that "MED3" doesn't return indices of the 2 values, only the values.
for example, if the array is: 1, 2, 10, 1, 7, 6, 3, 4, 4 it returns 2 (n/3 value) and 4 (2n/3 value).
I also thought to run over the array and to take all the values between 2 and 4 (for example, in the given array above) to new array and then use "MED3" again, but can be duplicates (if the array is 2, 2, 2, 2, ..., 2 I would take all the elements each time).
Any ideas? I must use "MED3".
* MED3 is like a black box, it runs in linear time.
Thank you.
I think you're on the right track, but instead of taking 2 to 4, I'd suggest removing the first n/3 values that are <= MED3.floor() and the first n/3 values that are >= MED3.ceil(). That avoids issues with too many duplicates. If two passes/cycle aren't too expensive, you can remove all values < MED3.floor() + up to a total of n/3 values = MED3.floor() (do the same for ceil())
then repeat until you are at the k'th smallest target.
I have a function which creates a row vector(N) up to a specified number of N columns. This vector is generated by have the next column add a random integer between 1 and 5 to the previous column and keeps on going until column N. However, I wish to generate the function vector(200) 500 times, where each row vector is randomly generated, and then store each of these vector into a matrix of size 500x200.
I am currently a beginner and I'm just testing Matlab out.
What I tried to do is:
for r=1:500
row(r) = vector(200)
mat(r, :) = row(r)
end
However this does not seem to work. Any help or suggestion will be appreciated.
Thanks!
Assuming the first column is also a random number between 1 and 5, you can do this
result = cumsum(randi(5, 500, 200), 2);
How it works: randi(5, 500, 200) generates 500x200 random integers between 1 and 5; and cumsum(..., 2) gives the cumulative sum along each row.
I have a matrix in MATLAB as follows:
A = [ 0, 0, 0;
1, 2, 3;
4, 2, 3;
0, 0, 0;
1, 3, 4 ];
I would like to remove the zeros from line 1 and line 4 so I can get the following matrix:
B = [ 1, 2, 3;
4, 2, 3;
1, 3, 4 ];
What I did is the following:
for i = 1:length(A)
if (sum(A(i, :)) == 0)
A(i, :) = [];
end
end
I know that the problem is that A is changing in the size so that is the problem. Unfortunately, I cannot fix it. Could you please give me some hint.
If you want to remove the rows with zero sum this might help,
A(sum(A,2)==0,:)=[];
As mentioned by #LuisMendo you can use
A(all(A,2)==0,:)=[];
depending on what criteria you have in mind.
Kamtal's approach would work assuming that you have no rows that summed to zero. To be safer, you should check to see if a row consists only of zeroes. In other words, try doing this:
A(~any(A,2), :) = [];
any checks to see if an array or matrix has any of its elements to be non-zero which outputs logical true and false otherwise. If you use any over a matrix, you can specify whether you want to check for this over the rows or the columns in the second parameter of any. In your case, you want to operate over the columns for each row, and so you'd specify the second parameter to be 2.
Because you want to check to see if any row consists of all zeroes, you would use any over the columns and check for the reverse. As such, any would output logical false if all of a row consisted only of zeroes. This is what we're looking for, but you want this to be true and not false, and hence we invert using ~ as the opposite is what we seek.
However, if you want to get your method working, you would not use a for loop, but a while loop instead as the index to access each row keeps changing. As such, once you remove a row, you would not increment the index to access the next row, until you successfully find a row which doesn't sum to zero. Remember, as you remove a row, the row that was just below it gets moved to the position that was removed, and so you would still check this same position for a row that didn't sum to zero. You would move to the next row once you find a row that didn't sum to zero.
In other words, do this:
i = 1;
while i < length(A)
if (sum(A(i, :)) == 0)
A(i, :) = [];
continue;
end
i = i + 1;
end