Hello how would I get numbers randomly from a group of specific numbers using arrays in C? Say, I wanted to generate 50 numbers from a set of these numbers:
52 67 80 87 90 95
make an array A of size n to store arbitrary set eg, { 52, 67, 80, 87, 90, 95 }
save the length l of the fixed array eg, 6
make a random number r from 0 to length exclusive
item = A[r] where r = rand % l
Related
I iterate through a 100x100 array and pick every time four neighbours (one left of the center node, one above, one right and one below), like in the picture below
the red one is the center node and the blue ones are the neighbours. I struggle to find a convenient way in MATLAB to pick randomly one of the neighbours.
The following assumes that
Each entry is replaced by one of its original neighbours, independently of what happens to other entries.
Each neighbour has the same probability of being picked.
Neighbourhood is defined cyclically. Thus, for example, in the first column the "left" neighbour belongs to the last column.
The code builds a cyclically extended matrix for convenience, and then uses linear indexing to (randomly) select the neighbours.
x = [10 20 30 40; 50 60 70 80; 90 100 110 120]; % example data
x_ext = x([end 1:end 1], [end 1:end 1]); % cyclically extended matrix
ind = bsxfun(#plus, (2:size(x,1)+1).', (1:size(x,2))*(size(x,1)+2)); % linear indices
% of the original matrix in the extended matrix
delta = [-1 1 -size(x_ext,1) size(x_ext,1)]; % possible displacements for neighbours,
% as linear indices
r = delta(randi(4, size(x))); % generate random displacements
result = x_ext(ind + r); % pick neighbours in extended matrix
Example:
>> x
x =
10 20 30 40
50 60 70 80
90 100 110 120
>> result
result =
20 30 70 30
90 100 60 120
50 110 70 40
I need to find the minimum positive values in each column and its position inside the column of a certain matrix. So if I have:
A = [1 4
2 3
3 6]
I need to obtain the values 1 and 3, and the positions 1 and 2. Doing this inside a for loop I obtain correctly the minimum values and its position, but it also catches the negative values:
for bit = 1:2
[y(bit),x(bit)] = min(A(:,bit));
end
And if I use:
[y(bit),x(bit)] = min(A(A(:,bit)>0));
I don't receive the expected result. What I'm doing wrong? Thanks.
This can be easily achieved using inf and min...
New method using inf and no looping
Take some random example:
% Generated using A = randi([-100, 100], 10, 3)
A = [ 31 41 -12
-93 -94 -24
70 -45 53
87 -91 59
36 -81 -63
52 65 -2
49 39 -11
-22 -37 29
31 90 42
-66 -94 51];
Set all negative values to positive infinity, which will ensure they are never the minimum value in the column.
A(A<=0) = inf;
% if you want to preserve A, use A2=A; A2(A<=0)=inf;
Now you can just use the min function as expected.
[mins, idx] = min(A);
% mins = 31, 39, 29: as expected
% idx = 1, 7, 8: the indices of the above values in each column as expected.
By default, min will get the column-wise minimum as you want.To specify this explicitly, use min(A,[],1), see the documentation for more details.
Note that you could achieve the same result by using NaN instead of inf.
Your method
In response to why you were getting an unexpected result, it's because you weren't selecting the column of A in your loop, the second attempt should be corrected to
[y(bit),x(bit)] = min(A(A(:,bit)>0, bit));
However, this will still give an unexpected result! The minimums will be correct, but their indices will be lower than expected. This is because the indices will only count the positive values in each column, so you will get the nth positive number rather than the nth number. The easiest "workaround" is to abandon this method and use the quicker one above which doesn't require looping.
I have an array with three columns like this:
A B C
10 75 20
30 67 50
85 12 30
98 49 70
I have A and B values, and I want to get the corresponding C value.
For example if I enter (30,67) it should display 50.
Does Matlab have any trick for getting C value?
(my dataset is very large, and I need a fast way)
you can use ismember:
ABC = [10 75 20
30 67 50
85 12 30
98 49 70];
q = [30 67
85 12];
[~, locb] = ismember( q, ABC(:,1:2), 'rows' );
C = ABC(locb,3);
The result you get is
C =
50
30
Note that the code assume all pairs in q can be found in ABC.
Let your input data be defined as
data = [ 10 75 20
30 67 50
85 12 30
98 49 70];
values = [ 30 67];
This should be pretty fast:
index = data(:,1)==values(1) & data(:,2)==values(2); %// logical index to matching rows
result = data(index,3); %// third-column value for those rows
This gives all third-column values that match, should there be more than one.
If you want to specify several pairs of values at once, and obtain all matching results:
index = any(bsxfun(#eq, data(:,1).', values(:,1)), 1) & ...
any(bsxfun(#eq, data(:,2).', values(:,2)), 1);
result = data(index,3);
For example, given
data = [ 10 75 20
30 67 50
85 12 30
98 49 70
30 67 80 ];
values = [ 30 67
98 49];
the result would be
result =
50
70
80
You can create a sparse matrix. This solution only works if C does not contain any zeros and A and B are integers larger 0
A = [10 30 85 98]';
B = [75 67 12 49]';
C = [20 50 30 70]';
S = sparse(A,B,C);
S(10,75) % returns corresponding C-Value if found, 0 otherwise.
Try accumarray:
YourMatrix = accumarray([A B],C,[],#mean,true);
This way YourMatrix will be a matrix of size [max(A) max(B)], with the values of C at YourMatrix(A(ind),B(ind)), with ind the desired index of A and B:
A = [10 30 85 98]';
B = [75 67 12 49]';
C = [20 50 30 70]';
YourMatrix = accumarray([A B],C,[],#mean,true);
ind = 2;
YourMatrix(A(ind),B(ind))
ans =
50
This way, when there is a repetition in A B, it will return the corresponding C value, provided each unique pair of A B has the same C value. The true flag makes accumarray output a sparse matrix as opposed to a full matrix.
I have the following vector A:
A = [34 35 36 5 6 7 78 79 7 9 10 80 81 82 84 85 86 102 3 4 6 103 104 105 106 8 11 107 201 12 202 203 204];
For n = 2, I counted the elements larger or equal to 15 within A:
D = cellfun(#numel, regexp(char((A>=15)+'0'), [repmat('0',1,n) '+'], 'split'));
The above expression gives the following output as duration values:
D = [3 2 7 4 6] = [A(1:3) **stop** A(7:8) **stop** A(12:18) **stop** A(22:25) **stop** A(28:33)];
The above algorithm computes the duration values by counting the elements larger or equal to 15. The counting also allows less than 2 consecutive elements smaller than 15 (n = 2). The counter stops when there are 2 or more consecutive elements smaller than 15 and starts over at the next substring within A.
Eventually, I want a way to find the median position points of the duration events A(1:3), A(7:8), A(12:18), A(22:25) and A(28:33), which are correctly computed. The result should look like this:
a1 = round(median(A(1:3))) = 2;
a2 = round(median(A(7:8))) = 8;
a3 = round(median(A(12:18))) = 15;
a4 = round(median(A(22:25))) = 24;
a5 = round(median(A(28:33))) = 31;
I edited the question to make it more clear, because the solution that was provided here assigns the last number within the row of 2 or more consecutive numbers smaller than 15 (3 in this case) after A(1:3) to the next substring A(7:8)and the same with the other substrings, therefore generating wrong duration values and in consequence wrong median position points of the duration events when n = 2 or for any given even n.
Anyone has any idea how to achieve this?
I have been given an array A of integers. Now I have to found out a sub-array(a sub-sequence of original array) where sum of every pair is greater than or equal to a pre-defined K.
What I thought :-
Will sort the array in O(nlgn) or O(n) depending upon range of values in array.
Find out i in sorted array such that sorted[i] + sorted[i+1]>=k
Set max to sorted[i]
Traverse the original array to delete all value smaller than max, which is the required sub-sequence
Repeat the above for all the elements of the array.
Running Time :- O(nlgn)
Is the solution optimal ? Can we further improve it ?
Example :-
-10 -100 5 2 4 7 10 23 81 5 25
Sorted Array
-100 -10 2 4 5 5 7 10 23 25 81
Let K = 20
Sub Array : -
10 23 25 81
Had the question been to find out longest sub-array, algorithm suggested by alestanis in the answers would work fine :)
Here is a fairly simple solution.
>>> def f(A, k):
... solution = [item for item in A if 2*item >= k]
... m = min(solution)
... for item in A:
... if item + m >= k and 2*item < k:
... solution.append(item)
... break
... return solution
...
>>> f([-10, -100, 5, 2, 4, 7, 10, 23, 81, 5, 25], 20)
[10, 23, 81, 25]
>>>
Here's a slightly different approach, hinted at by one of the earlier comments and similar to the answer by alestanis, but slightly different, in that it doesn't depend on splitting arrays. It makes a single pass through the array (although that doesn't guarantee O(N) ), and just needs to track the two minimum values as well as the start and end point of the subsequence being considered.
For a contiguous subsequence to have all possible pairs sum to 20, the sum of the two least elements must be >= 20. So start by considering subsequent pairs of elements (array[0] and array[1] to start). If they don't sum to 20 or more, then move on to array[1] and array[2]. If they add up to 20 or more, then expand the right hand endpoint by one. If the new element is greater than the other two, then it will sum to 20 or greater with anything already in the subsequence, and you can expand the right hand again. If it's less, then you need to pick the two least elements with a couple comparisons, and if the two new least elements now don't sum to 20 or more, then remove the element you've just added from the subsequence, and note this particular subsequence, then start over with the second and third elements of the existing subsequence. At the end, you will in general have a list of subsequences that fit the constraints, and it should be easy to pick the first or largest or whatever you need.
Example, using the sequence you listed:
-10 -100 5 2 4 7 10 23 81 5 25
Start with -10, -100. They don't sum to 20, so move right one to -100, 5. Again, these don't sum to 20, so continue. The first pair that does sum to 20 is 10, 23. So now, we expand the range to 10, 23, 81. 81 is greater than both the two minimums, so we expand again, to 10, 23, 81, 5. 5 is less than both 10 and 23, so the new minimums are 5 and 10, which don't sum to 20, so adding 5 was a mistake and we need to backtrack. We find 10, 23, 81 is one such subsequence. Next we continue with 23, 81, which will lead us to the subsequence 23, 81, 5, 25, which meets the criteria as well.
So, at the end, we have four possible subsequences that meet the critieria - 10, 23, 81, 23, 81, 5, 25, 81, 5, 25, and 5, 25. The last two could be pruned by not finding additional solutions once we have one that includes the last element in the original list, which would leave just the first two possibilities. From there we can pick either the first or the longest.
First of all, you can't sort your set. I think that part of the problem is to find sub-arrays of the original array given as input.
This can be solved using some recursion:
Find the two minimums of your array, m1 and m2
If m1 + m2 < K then split your array into at most two smaller arrays that don't contain m1 and m2 simultaneously. If indexes for m1 and m2 are i and j with i<j then subarrays are [O, j-1] and [i+1, n].
Repeat from step 1.
If m1 + m2 >= K then your current array is a feasible solution to your problem: return its length.
Add some pruning to discard useless arrays
Let's apply this on your example:
Initialize max = 0;
A1 = -10* -100* 5 2 4 7 10 23 81 5 25
Its two minimums are -10 and -100. Split the array around these values, which gives us only one array (we're lucky!)
A2 = 5 2* 4* 7 10 23 81 5 25
The two minimums of A2 are 2 and 4. We split into
A3_1 = 5* 4* and A3_2 = 2* 7 10 23 81 5* 25
This continues with the following iterations:
A3_1 discarded
A3_2 becomes A4_1 = 2* 7* 10 23 81 A4_2 = 7* 10 23 81 5* 25
A5_1 = 7* 10* 23 81
A5_2 = 7* 10* 23 81 -> Duplicate, discarded
A5_3 = 10* 23 81 5* 25
A6_1 = 10* 23* 81 -> Yay! update max = 3
A6_2 = 10* 23* 81 -> Length <= max. Discarded
A6_3 = 23 81 5* 25 -> Yay! update max = 4
In this example, I pruned the search space by:
Eliminating duplicate subsets (this can be done by storing them in a set for instance)
Discarding subarrays shorter or equal to the current max length known
This algorithm has a complexity of:
O(nlogn) average,
O(n^2) worst case. This happens when array is sorted and minimums are always on one of the sides of the array, so the array can't be split into smaller subarrays (like the first iteration of the example).
void sub_array(int ar[],int n,int val)
{
int max=0;
for(int i=0;i<n;i++)
{
if(ar[max]<ar[i])
max=i;
}
int b[n];
max=ar[max];
int p=0;
int min=0;
for(int i=0;i<n;i++)
{
if(ar[i]+max>val)
{
b[p]=ar[i];
if(ar[i]<max)
{
min=p;
max=ar[i];
}
p++;
}
else
{
if(ar[i]>max)
{
max=ar[i];
b[min]=ar[i];
}
}
}
for(int i=0;i<p;i++)
{
cout<<b[i]<< " " ;
}
}