Finding whithout loop the next highest and the next smallest number of a number in a one-dimensional table in Matlab - arrays

am asking if there is a function in matlab which finds the first max and first min numbers compered to a number in an array
example :
if we have an array A = [1 2 3 4 5 6 7 8 9];
and the number is x=3.4;
How can we find whith a function (and not with a loop) and store the fist min and firts max of x in variables min_x max_x ?
desirable results:
min_x = 3
max_x = 4

Use logical indexing to select the entries of A smaller (larger) than x, and then use max (min):
max(A(A-x<0))
min(A(A-x>0))
I'm interpreting "next highest/smallest" as the closest numbers to x in A, from above and from below.

First you'll probably want to convert the decimal to an array. Here are some suggested ways that you can do this. After you have an array of your digits, you should be able to juse use MATLAB's built in max() and min() functions.

Related

2D array minimum sum of Y elements and just two rows that we can chose to get minimum

With given 2d array[X][Y], i have to find the smallest possible sum of Y elements but:
the sum must be created by using just 2 rows,
each value must be from different index
Example:
for array
7 3 7 9
2 20 10 6
8 8 8 8
Result should be 18, as we get 3 + 7 from 1st row and 2 + 6 from 2nd.
I've been thinking about few hours but i can't figure out how to deal with it.
Try this one here.
Method 1 (Naive Approach): Check every possible submatrix in given 2D
array. This solution requires 4 nested loops and time complexity of
this solution would be O(n^4).
Method 2 (Efficient Approach): Kadane’s algorithm for 1D array can be
used to reduce the time complexity to O(n^3).

Finding indexes of maximum values of an array

How do I find the index of the 2 maximum values of a 1D array in MATLAB? Mine is an array with a list of different scores, and I want to print the 2 highest scores.
You can use sort, as #LuisMendo suggested:
[B,I] = sort(array,'descend');
This gives you the sorted version of your array in the variable B and the indexes of the original position in I sorted from highest to lowest. Thus, B(1:2) gives you the highest two values and I(1:2) gives you their indices in your array.
I'll go for an O(k*n) solution, where k is the number of maximum values you're looking for, rather than O(n log n):
x = [3 2 5 4 7 3 2 6 4];
y = x; %// make a copy of x because we're going to modify it
[~, m(1)] = max(y);
y(m(1)) = -Inf;
[~, m(2)] = max(y);
m =
5 8
This is only practical if k is less than log n. In fact, if k>=3 I would put it in a loops, which may offend the sensibilities of some. ;)
To get the indices of the two largest elements: use the second output of sort to get the sorted indices, and then pick the last two:
x = [3 2 5 4 7 3 2 6 4];
[~, ind] = sort(x);
result = ind(end-1:end);
In this case,
result =
8 5

finding maximum sum of a disjoint sequence of an array

Problem from :
https://www.hackerrank.com/contests/epiccode/challenges/white-falcon-and-sequence.
Visit link for references.
I have a sequence of integers (-10^6 to 10^6) A. I need to choose two contiguous disjoint subsequences of A, let's say x and y, of the same size, n.
After that you will calculate the sum given by ∑x(i)y(n−i+1) (1-indexed)
And I have to choose x and y such that sum is maximised.
Eg:
Input:
12
1 7 4 0 9 4 0 1 8 8 2 4
Output: 120
Where x = {4,0,9,4}
y = {8,8,2,4}
∑x(i)y(n−i+1)=4×4+0×2+9×8+4×8=120
Now, the approach that I was thinking of for this is something in lines of O(n^2) which is as follows:
Initialise two variables l = 0 and r = N-1. Here, N is the size of the array.
Now, for l=0, I will calculate the sum while (l<r) which basically refers to the subsequences that will start from the 0th position in the array. Then, I will increment l and decrement r in order to come up with subsequences that start from the above position + 1 and on the right hand side, start from right-1.
Is there any better approach that I can use? Anything more efficient? I thought of sorting but we cannot sort numbers since that will change the order of the numbers.
To answer the question we first define S(i, j) to be the max sum of multlying the two sub-sequence items, for sub-array A[i...j] when the sub-sequence x starts at position i, and sub-sequence y ends on position j.
For example, if A=[1 7 4 0 9 4 0 1 8 8 2 4], then S(1, 2)=1*7=7 and S(2, 5)=7*9+4*0=63.
The recursive rule to compute S is: S(i, j)=max(0, S(i+1, j-1)+A[i]*A[j]), and the end condition is S(i, j)=0 iff i>=j.
The requested final answer is simply the maximum value of S(i, j) for all combinations of i=1..N, j=1..N, since one of the S(i ,j) values will correspond to the max x,y sub-sequences, and thus will be equal the maximum value for the whole array. The complexity of computing all such S(i, j) values is O(N^2) using dynamic programming, since in the course of computing S(i, j) we will also compute the values of up to N other S(i', j') values, but ultimately each combination will be computed only once.
def max_sum(l):
def _max_sub_sum(i, j):
if m[i][j]==None:
v=0
if i<j:
v=max(0, _max_sub_sum(i+1, j-1)+l[i]*l[j])
m[i][j]=v
return m[i][j]
n=len(l)
m=[[None for i in range(n)] for j in range(n)]
v=0
for i in range(n):
for j in range(i, n):
v=max(v, _max_sub_sum(i, j))
return v
WARNING:
This method assumes the numbers are non-negative so this solution does not answer the poster's actual problem now it has been clarified that negative input values are allowed.
Trick 1
Assuming the numbers are always non-negative, it is always best to make the sequences as wide as possible given the location where they meet.
Trick 2
We can change the sum into a standard convolution by summing over all values of i. This produces twice the desired result (as we get both the product of x with y, and y with x), but we can divide by 2 at the end to get the original answer.
Trick 3
You are now attempting to find the maximum of a convolution of a signal with itself. There is a standard method for doing this which is to use the fast fourier transform. Some libraries will have this built in, e.g. in Scipy there is fftconvolve.
Python code
Note that you don't allow the central value to be reused (e.g. for a sequance 1,3,2 we can't make x 1,3 and y 3,1) so we need to examine alternate values of the convolved output.
We can now compute the answer in Python via:
import scipy.signal
A = [1, 7, 4, 0, 9, 4, 0, 1, 8, 8, 2, 4]
print max(scipy.signal.fftconvolve(A,A)[1::2]) / 2

Making an array of random integers that add up to a certain number

I want to make an array of 7 integers, each of which is a random value between 2 and 5. That's easy, but I want to make it so the total sum of these integers must be 20. Any ideas?
Generate 6 random numbers.
Calculate the sum of these numbers.
if the sum is larger than 19 or smaller than 15: start over.
7th number is 20 - sum
Start with an array of seven twos. You now have a sum of 14. Add one to a random slot in the array six times, taking care to not overflow a value to more than five:
arr = {2, 2, 2, 2, 2, 2, 2}
n = 6
while n > 0:
m = random(7)
if arr[m] < 5:
arr[m]++
n--
Brute force: keep recalculating until you get an answer
import random
def random_sums_to(lower, top, n, sums_to):
a = [random.randint(lower, top) for _ in range(n)]
if sum(a) != sums_to:
return random_sums_to(lower, top, n, sums_to)
return a
print random_sums_to(2, 5, 7, 20)
If you need to make sure to get the exact same distribution at each position proceed as follows:
Calculate a list with all possible sequences
Pick one of these sequences randomly

Avoid loops in matlab

I am limited in the use of cycles in matlab and I have one task. I have the matrix 2xn with numbers and cell array 1xn. Each element in the first row point to a position of the array. I want to add every number from the second row of matrix to cell, which is pointed by corresponding number in the first row. In addition, I want the cells to be strings.
Let me clarify with example:
A = [[1 4 3 3 1 4 2], [7 4 3 5 6 5 4]]
I want to get array of cells: {'76', '4', '35', '45'}
How can I do this without using a for or while loop?
A = [1 4 3 3 1 4 2; 7 4 3 5 6 5 4]; %// data: 2 x n array
[~, ~, ii] = unique(A(1,:));
R = accumarray(ii(:),A(2,:),[],#(v) {fliplr(regexprep(num2str(v(:).'),'\s',''))}).';
The second line (unique) is used to remove possible gaps in first row. Otherwise those gaps would translate to the result of accumarray, which would then take up more memory uselessly.
The third line (accumarray) aggregates all values of second row of A that have the same value in the first row. The aggregation is done by the anonymous function, which converts numbers to string (num2str), removes spaces (regexprep), and changes orientation (fliplr and .') to match the desired output format.
EDIT:
Thanks to #chappjc's suggestion, the third line can be simplified to
R = accumarray(ii(:),A(2,:),[],#(v) {fliplr(num2str(v(:).','%d'))}).';
Alright, by just pointing at cellfun, arrayfun, cell2mat, cell indexing and array indexing I was arrogant. So, I try to make it up by actually using some of those in a more constructive solution:
%// Using array-indexing to find all matches with the current index in the first row,
%// then print their counterpart(s) into strings
fun = #(ii) sprintf('%d', A(2, A(1, :) == ii));
%// The following could also be 1:size(A, 2) or unique(A(1, :)) depending on the
%// general form of your problem.
range = min(A(1, :)) : max(A(1, :));
%// Using arrayfun to loop over all values in the first row
R = arrayfun(fun, range, 'UniformOutput', false)

Resources