MQL5: How to Rank an Array's values - arrays

I used R and the rank function to create the following ranks for the original var x:
x average first last random max min
3 4.5 4 5 5 5 4
1 1.5 1 2 2 2 1
4 6.0 6 6 6 6 6
1 1.5 2 1 1 2 1
5 8.0 7 9 9 9 7
9 11.0 11 11 11 11 11
2 3.0 3 3 3 3 3
6 10.0 10 10 10 10 10
5 8.0 8 8 7 9 7
3 4.5 5 4 4 5 4
5 8.0 9 7 8 9 7
I am struggling to implement the min-version in MQL5. First, you probably need to sort the Array but you need to take care of the original order. How the ranks are assigned manually is quite logical but I have no clue how to implement this in MQL5.

Related

Using multiple indicies to grab values from 2D MATLAB array without returning all combinations [duplicate]

This question already has an answer here:
3d matrix: how to use (row, column) pairs with 3rd dimension wildcard in MATLAB?
(1 answer)
Closed 5 years ago.
I am trying to get a few values from a 2D matrix
Consider the starting matrix:
>> test = randi(10,10)
test =
10 4 8 7 10 4 2 8 4 1
6 5 6 5 5 2 10 4 7 6
7 2 5 4 1 1 3 7 6 1
1 3 3 9 9 5 10 4 6 9
9 1 8 4 7 2 3 7 3 10
8 10 3 9 4 8 4 1 3 1
2 7 1 8 10 4 1 10 5 10
6 10 8 9 3 9 7 9 3 1
4 2 7 6 7 8 2 8 9 7
6 10 8 7 7 6 1 9 10 8
What I want to do is grab elements (1,4);(2,5);and(3,6) only
So I try
test([1,2,3],[4,5,6])
but that returns all combinations of the two indicies!
ans =
6 3 1
1 2 4
8 4 8
Without this intermediate step, how do I do what I want in one line? There must be a way.
I cannot use the intermediate step because in actuality, my matrix is very large and so are my indices lengths so I will run out of memory.
You can do this using sub2ind as was already pointed out at mathworks:
test(sub2ind(size(test),[1,2,3],[4,5,6]))
Applied to 3D
test = randi(10,10,10,10);
test(sub2ind(size(test),[1,2,3],[4,5,6], [3,3,3]))

J: Coordinates with specific value

Let's say we have array
0 1 2 3 4 5 8 7 8 9
There are two indexes that have value 8:
(i.10) ([#~8={) 0 1 2 3 4 5 8 7 8 9
6 8
Is there any shorter way to get this result? May be some built-in verb.
But more important. What about higher dimensions?
Let's say we have matrix 5x4
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8
I want to find out what are coordinates with value 6.
I want to get result such (there are three coordinates):
4 1
3 2
2 3
It's pretty basic task and I think it should exist some simple solution.
The same in three dimensions?
Thank you
Using Sparse array functionality ($.) provides a very fast and lean solution that also works for multiple dimensions.
]a=: 5 ]\ 1 + i. 8
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8
6 = a
0 0 0 0 0
0 0 0 0 1
0 0 0 1 0
0 0 1 0 0
4 $. $. 6 = a
1 4
2 3
3 2
Tacitly:
getCoords=: 4 $. $.
getCoords 6 = a ,: a
0 1 4
0 2 3
0 3 2
1 1 4
1 2 3
1 3 2
Verb indices I. almost does the job.
When you have a simple list, I.'s use is straightforward:
I. 8 = 0 1 2 3 4 5 8 7 8 9
6 8
For higher order matrices you can pair it with antibase #: to get the coordinates in base $ matrix. Eg:
]a =: 4 5 $ 1 2 3 4 5 2 3 4 5 6 3 4 5 6 7 4 5 6 7 8
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8
I. 6 = ,a
9 13 17
($a) #: 9 13 17
1 4
2 3
3 2
Similarly, for any number of dimensions: flatten (,), compare (=), get indices (I.) and convert coordinates (($a)&#:):
]coords =: ($a) #: I. 5 = , a =: ? 5 6 7 $ 10
0 0 2
0 2 1
0 2 3
...
(<"1 coords) { a
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
By the way, you can write I. x = y as x (I.#:=) y for extra performance. It is special code for
indices where x f y

How do I accept info from a file and input it into an array?

I have a file with these values:
9 10 11 9.5 10.2 9.8 10 8.7 9.3 9.1 9 8.9
4 5 5 4 6 5 4 3 4 5 5 4
8 11 10 8.5 10.7 9 11 8.5 9.4 9 10 9.9
5 5 5 5 5 5 5 5 5 5 5 5
9 9 9 9 9 9 9 9 9 9 9 9
4 5 5 4 6 5 4 3 4 5 5 4
8 9 10 8.5 9.2 8.8 9 7.7 8.3 8.1 8 7.9
7 4 6 6 6 5 6 6 6 6 5 6
10 11 12 10 11.2 9 11 9.7 9 9.1 10 9.9
6 5 6 6 6 5 6 6 6 6 5 6
10 9 11.2 9.5 10.8 9 10.3 8 9.3 9.1 9 8.9
5 4 5 4 6 5 4 3 4 5 5 4
9 10 10.4 8.5 10.2 9.2 11.1 8 9.4 9 10 9.9
6 4 5 5 5 5 5 5 5 5 5 5
10 8 9.6 9 9.6 9.7 9 9 9.7 8 10 9
5 4 5 4 6 5 4 3 4 5 5 4
9 8 10.8 8.5 9.5 8 9.5 7 8.3 8.1 8.8 9
5 4 5 4 6 5 4 3 4 5 5 4
11 10 11 10 11.3 9.4 11 9 9.5 8 10 7
4 5 5 4 6 5 4 3 4 5 5 4
I need to accept these values into an array, so I can then get the largest number out of every other line, and the lowest out of the other lines.
Say I make an array
float array[20][12];
This doesn't seem to work:
fscanf(ifp, "%f", &main_array[20][12]);
So how can I accept these values into my array?
you need to read value by value, using a loop, you could make something like this:
float array[20][12];
int n = 20 * 12;
int i;
for(i = 0; i < n; i++)
fscanf(ifp, "%f", (&array[0][0] + i));
That's because you cannot read all file at once.
Another way, and maybe more easy to understand(because not uses pointer arithmetic) is:
int i, j;
for(i = 0; i < 20; i++)
for(j = 0; j < 12; j++)
fscanf(ifp, "%f", &array[i][j]);

How can I create a 3D array by stenciling the columns of a 2D array in MATLAB?

Suppose I have a 2D array called A. I want to create a 3D array called B, whose "pages" are select columns of a stencil moving across A, column-by-column. For example, the first page of B might be the 1st, 3rd, and 5th columns of A. Then the second page would be the 2nd, 4th, and 6th columns of A, etc.
Anyone have an efficient way of doing this is MATLAB?
Thanks!
I am guessing you are looking for this -
%%// Given 2D array
A = randi(10,4,12)
t1 = reshape(A,size(A,1)*2,[]);
t2 = reshape(t1',size(A,2)/2,[],2); %%//'
B = permute(t2,[2 1 3]) %%// Output 3D array
Output -
A =
5 10 3 5 6 8 4 3 8 10 8 7
10 8 3 7 6 10 9 2 7 8 8 5
10 4 7 8 6 4 5 4 1 1 3 7
7 7 6 6 1 10 5 8 9 4 3 3
B(:,:,1) =
5 3 6 4 8 8
10 3 6 9 7 8
10 7 6 5 1 3
7 6 1 5 9 3
B(:,:,2) =
10 5 8 3 10 7
8 7 10 2 8 5
4 8 4 4 1 7
7 6 10 8 4 3
Of course, there is an alternative straight-forward approach for this special case -
B(:,:,1)=A(:,1:2:end);
B(:,:,2)=A(:,2:2:end);

Tacit function to multiply five consecutive number in a list: J, j701

I'm working on Project Euler, I'm on problem 8, and I'm trying a simple brute force: Multiply each consecutive 5 digit of the number, make a list with the results, and find the higher.
This is the code I'm currently trying to write in J:
n =: 731671765313x
NB. 'n' will be the complete 1000-digits number
itl =: (".#;"0#":)
NB. 'itl' transform an integer in a list of his digit
N =: itl n
NB. just for short writing
takeFive =: 5 {. ] }.~ 1 -~ [
NB. this is a dyad, I get this code thanks to '13 : '5{.(x-1)}.y'
NB. that take a starting index and it's applied to a list
How I can use takeFive for all the index of N?
I tried:
(i.#N) takeFive N
|length error: takeFive
| (i.#N) takeFive N
but it doesn't work and I don't know why.
Thank you all.
1. The reason that (i.#N) takeFive N is not working is that you are essentially trying to run 5{. ((i.#N)-1) }. Nbut you have to use x not as a list but as an atom. You can do that by setting the appropriate left-right rank " of the verb:
(i.#N) (takeFive"0 _) N
7 3 1 6 7
7 3 1 6 7
3 1 6 7 1
1 6 7 1 7
6 7 1 7 6
7 1 7 6 5
1 7 6 5 3
7 6 5 3 1
6 5 3 1 3
5 3 1 3 0
3 1 3 0 0
1 3 0 0 0
2. One other way is to bind (&) your list (N) to takeFive and then run the binded-verb through every i.#N. To do this, it's better to use the reverse version of takeFive: takeFive~:
((N&(takeFive~))"0) i.#N
7 3 1 6 7
7 3 1 6 7
3 1 6 7 1
1 6 7 1 7
6 7 1 7 6
7 1 7 6 5
1 7 6 5 3
7 6 5 3 1
6 5 3 1 3
5 3 1 3 0
3 1 3 0 0
1 3 0 0 0
or (N&(takeFive~)) each i.#N.
3. I think, though, that the infix dyad \ might serve you better:
5 >\N
7 3 1 6 7
3 1 6 7 1
1 6 7 1 7
6 7 1 7 6
7 1 7 6 5
1 7 6 5 3
7 6 5 3 1
6 5 3 1 3

Resources