Find all ascending triplets in array - arrays

I'm trying to exctract all the ascending triplets in an array of arbitrary dimension. For example if i have an array like [1 2 3 4] i'd like to obtain [1 2 3] , [1 2 4] , [2 3 4]
Here's a simple "graphical" example with 5 elements:
The arrows are the indexes used to iterate, each step is a found triplet.
So far i've just implemented a simple sorting algorithm, which will give me the ordered array.
Once i have the ordered array, I iterate with 3 possible pointers (or just indexes) increasing the pointer starting at the third element until it reaches the end of the array.
Once it reaches the end, i'll increase the second pointer and reset the third to the position right next to the pointer 2 and so on.
array = [ 3 2 1 5 ];
array = sort(array);
//Now i should iterate over the 3 indexes, but i'm totally lost about how to place them
for i=1:length(array-2)
for j=2:length(array-1)
for k=3:length(array)
//storing triplet
end
end
end
Right now i'm able to iterate over the array, and i can extract all the triplets until the k index reaches the end of the array.
The problem is once i reach for the end, i have to increment the j index starting point and reset the k index to be right next to the second index.
To make it clear: right now once k reaches the end, it will start again from 3 and j will also be 3, but i need them to be j = 3 and k = 4 after the first iteration of k is completed and so on (this is valid also for j compared to i , look at the image for a clearer explanation).
How do i fix the indexes in order to extract the triplets correctly?

Seems to me like your inner iterations start one after your outer one:
for j=(i+1):length(array-1)
for k=(j+1):length(array-1)
Generalizing the first loop to the rest.

const arrayTotal = [3, 2, 1, 5];
let combinationArray = [];
arrayTotal.sort();
for (let i = 0; i < (arrayTotal.length - 2); i++) {
for (let j = (i + 1); j < (arrayTotal.length - 1); j++) {
for (let k = (j + 1); k < arrayTotal.length; k++) {
combinationArray.push([arrayTotal[i], arrayTotal[j], arrayTotal[k]])
}
}
}
console.log(combinationArray);

Related

Trouble understanding one line in Insertion Sort (Python 3)

I was looking through the other threads concerning the Insertion Sort but didn't find the answer that relates to the specific part of it which I do not understand.
My full Insertion Sort algorithm can be seen below. It works as intended, but I cannot figure out the purpose of that last line.
array[position] = value
Let me explain through an example:
When the 'for' loop starts, index = 1.
=> value = array[1] = 3
=> position = 1
=> Since 4 > 3, the item at index 1, is swapped with the item at index 0.
=> position -= 1
=> position = 0
We now get to the line which confuses me:
array[0] = value
=> value = array[index] = array[0] = 3
However, when the 'for' loop goes through its second iteration, index = 2.
And so immediately value = array[2] and position = 2 ?
Even though I know that this last line of code is necessary I just cannot see what purpose it serves.
Could someone please explain to me this final logical step?
Thank you in advance for your time and help.
array = [4,3,5,6,12,9,8,6]
for index in range (1, len(array)):
value = array[index]
position = index
while position > 0 and array[position - 1] > value:
array[position] = array[position - 1]
position -= 1
array[position] = value
The position variable represents (at the end) where you will eventually insert the number. Without the last line, you are not inserting the number at 'position' at the correct place (it will result in the 1 index after). Below is my code for insertion sort.
def insertionSort(arr):
length = len(arr)
for i in range(1, length):
currNum = arr[i]
j = i - 1
while j >= 0 and currNum < arr[j]:
arr[j + 1] = arr[j]
j -= 1
arr[j+1] = currNum
return arr
You wouldn't have really swapped the numbers without that line, would you?
index 1:
-> [4,3,5,6,12,9,8,6] (enters while loop)
-> [4,4,5,6,12,9,8,6] ("pushes" 4 to position 1)
-> <waits for while loop to finish>
-> [3,4,5,6,12,9,8,6] (assigns 3 to position 0 since there are no other elements > 3)
index 2:
...
I think is not really needed at start in for loop, because it was used to index inside the loop. Looks the picture

How do I combine the coordinate pairs of an array into a single index?

I have an array
A = [3, 4; 5, 6; 4, 1];
Is there a way I could convert all coordinate pairs of the array into linear indices such that:
A = [1, 2, 3]'
whereby (3,4), (5,6), and (4,1) are represented by 1, 2, and 3, respectively.
Many thanks!
The reason I need is because I need to loop through array A such that I could make use of each coordinate pairs (3,4), (5,6), and (4,1) at the same time. This is because I will need to feed each of these pairs into a function so as to make another computation. See pseudo code below:
for ii = 1: length(A);
[x, y] = function_obtain_coord_pairs(A);
B = function_obtain_fit(x, y, I);
end
whereby, at ii = 1, x=3 and y=4. The next iteration takes the pair x=5, y=6, etc.
Basically what will happen is that my kx2 array will be converted to a kx1 array. Thanks for your help.
Adapting your code, what you want was suggested by #Ander in the comments...
Your code
for ii = 1:length(A);
[x, y] = function_obtain_coord_pairs(A);
B = function_obtain_fit(x, y, I);
end
Adapted code
for ii = 1:size(A,1);
x = A(ii, 1);
y = A(ii, 2);
B = function_obtain_fit(x, y, I); % is I here supposed to be ii? I not defined...
end
Your unfamiliarly with indexing makes me think your function_obtain_fit function could probably be vectorised to accept the entire matrix A, but that's a matter for another day!
For instance, you really don't need to define x or y at all...
Better code
for ii = 1:size(A,1);
B = function_obtain_fit(A(ii, 1), A(ii, 2), I);
end
Here is a corrected version for your code:
A = [3, 4; 5, 6; 4, 1];
for k = A.'
B = function_obtain_fit(k(1),k(2),I)
end
By iterating directly on A you iterate over the columns of A. Because you want to iterate over the rows we need to take A.'. So if we just display k it is:
for k = A.'
k
end
the output is:
k =
3
4
k =
5
6
k =
4
1

Given two arrays A and B, how to get B values which are the closest to A

Suppose I have two arrays ordered in an ascending order, i.e.:
A = [1 5 7], B = [1 2 3 6 9 10]
I would like to create from B a new vector B', which contains only the closest values to A values (one for each).
I also need the indexes. So, in my example I would like to get:
B' = [1 6 9], Idx = [1 4 5]
Note that the third value is 9. Indeed 6 is closer to 7 but it is already 'taken' since it is close to 4.
Any idea for a suitable code?
Note: my true arrays are much larger and contain real (not int) values
Also, it is given that B is longer then A
Thanks!
Assuming you want to minimize the overall discrepancies between elements of A and matched elements in B, the problem can be written as an assignment problem of assigning to every row (element of A) a column (element of B) given a cost matrix C. The Hungarian (or Munkres') algorithm solves the assignment problem.
I assume that you want to minimize cumulative squared distance between A and matched elements in B, and use the function [assignment,cost] = munkres(costMat) by Yi Cao from https://www.mathworks.com/matlabcentral/fileexchange/20652-hungarian-algorithm-for-linear-assignment-problems--v2-3-:
A = [1 5 7];
B = [1 2 3 6 9 10];
[Bprime,matches] = matching(A,B)
function [Bprime,matches] = matching(A,B)
C = (repmat(A',1,length(B)) - repmat(B,length(A),1)).^2;
[matches,~] = munkres(C);
Bprime = B(matches);
end
Assuming instead you want to find matches recursively, as suggested by your question, you could either walk through A, for each element in A find the closest remaining element in B and discard it (sortedmatching below); or you could iteratively form and discard the distance-minimizing match between remaining elements in A and B until all elements in A are matched (greedymatching):
A = [1 5 7];
B = [1 2 3 6 9 10];
[~,~,Bprime,matches] = sortedmatching(A,B,[],[])
[~,~,Bprime,matches] = greedymatching(A,B,[],[])
function [A,B,Bprime,matches] = sortedmatching(A,B,Bprime,matches)
[~,ix] = min((A(1) - B).^2);
matches = [matches ix];
Bprime = [Bprime B(ix)];
A = A(2:end);
B(ix) = Inf;
if(not(isempty(A)))
[A,B,Bprime,matches] = sortedmatching(A,B,Bprime,matches);
end
end
function [A,B,Bprime,matches] = greedymatching(A,B,Bprime,matches)
C = (repmat(A',1,length(B)) - repmat(B,length(A),1)).^2;
[minrows,ixrows] = min(C);
[~,ixcol] = min(minrows);
ixrow = ixrows(ixcol);
matches(ixrow) = ixcol;
Bprime(ixrow) = B(ixcol);
A(ixrow) = -Inf;
B(ixcol) = Inf;
if(max(A) > -Inf)
[A,B,Bprime,matches] = greedymatching(A,B,Bprime,matches);
end
end
While producing the same results in your example, all three methods potentially give different answers on the same data.
Normally I would run screaming from for and while loops in Matlab, but in this case I cannot see how the solution could be vectorized. At least it is O(N) (or near enough, depending on how many equally-close matches to each A(i) there are in B). It would be pretty simple to code the following in C and compile it into a mex file, to make it run at optimal speed, but here's a pure-Matlab solution:
function [out, ind] = greedy_nearest(A, B)
if nargin < 1, A = [1 5 7]; end
if nargin < 2, B = [1 2 3 6 9 10]; end
ind = A * 0;
walk = 1;
for i = 1:numel(A)
match = 0;
lastDelta = inf;
while walk < numel(B)
delta = abs(B(walk) - A(i));
if delta < lastDelta, match = walk; end
if delta > lastDelta, break, end
lastDelta = delta;
walk = walk + 1;
end
ind(i) = match;
walk = match + 1;
end
out = B(ind);
You could first get the absolute distance from each value in A to each value in B, sort them and then get the first unique value to a sequence when looking down in each column.
% Get distance from each value in A to each value in B
[~, minIdx] = sort(abs(bsxfun(#minus, A,B.')));
% Get first unique sequence looking down each column
idx = zeros(size(A));
for iCol = 1:numel(A)
for iRow = 1:iCol
if ~ismember(idx, minIdx(iRow,iCol))
idx(iCol) = minIdx(iRow,iCol);
break
end
end
end
The result when applying idx to B
>> idx
1 4 5
>> B(idx)
1 6 9

Ruby Input Array, Output Array without duplicates

# creating empty array (array1)
array1 = []
i = 0
# taking 10 numbers from user and storing them in the array
while array1.size < 10
print "Enter a number: "
array[i] = gets.chomp.to_i
i += 1
end
# pushing only the unique elements into a new array (array2)
k = 0
j = 0
array2 = []
while k < array1.size
if array1[k] != array1[j]
if array2.include? (array1[k])
puts "Element already exists"
else
array2.push(array1[k])
end
j += 1
end
k += 1
end
puts array2
It only works in some situations, but at all times, the first element that is unique is not being added to the new array for some reason, should I be starting j or k at 1, rather than 0?
I know that i can use .uniq and turn the array into a set and then back to an array, or just intersect the array with &, but i wanted to make it without ruby "shortcuts", any advice?
Sure.
k and j are both equal to 0 at startup.
So array1[k] == array1[j] is true, and you get k+=1.
k is now 1, and you missed the first element of array1.
Nothing specially Rubyish about this solution :
array2 = []
array1 = [1, 2, 3, 3, 2, 4, 5, 6]
i=0
while i<array1.size do
element = array1[i]
if !array2.include?(element) then
array2.push(element)
end
i += 1
end
puts array2.inspect

Gnuplot: Nested “plot” iteration (“plot for”) with dependent loop indices

I have recently attempted to concisely draw several graphs in a plot using gnuplot and the plot for ... syntax. In this case, I needed nested loops because I wanted to pass something like the following index combinations (simplified here) to the plot expression:
i = 0, j = 0
i = 1, j = 0
i = 1, j = 1
i = 2, j = 0
i = 2, j = 1
i = 2, j = 2
and so on.
So i loops from 0 to some upper limit N and for each iteration of i, j loops from 0 to i (so i <= j). I tried doing this with the following:
# f(i, j, x) = ...
N = 5
plot for [i=0:N] for [j=0:i] f(i, j, x) title sprintf('j = %d', j)
but this only gives five iterations with j = 0 every time (as shown by the title). So it seems that gnuplot only evaluates the for expressions once, fixing i = 0 at the beginning and not re-evaluating to keep up with changing i values. Something like this has already been hinted at in this answer (“in the plot for ... structure the second index cannot depend on the first one.”).
Is there a simple way to do what I want in gnuplot (i.e. use the combinations of indices given above with some kind of loop)? There is the do for { ... } structure since gnuplot 4.6, but that requires individual statements in its body, so it can’t be used to assemble a single plot statement. I suppose one could use multiplot to get around this, but I’d like to avoid multiplot if possible because it makes things more complicated than seems necessary.
I took your problem personally. For your specific problem you can use a mathematical trick. Remap your indices (i,j) to a single index k, such that
(0,0) -> (0)
(1,0) -> (1)
(1,1) -> (2)
(2,0) -> (3)
...
It can be shown that the relation between i and j and k is
k = i*(i+1)/2 + j
which can be inverted with a bit of algebra
i(k)=floor((sqrt(1+8.*k)-1.)/2.)
j(k)=k-i(k)*(i(k)+1)/2
Now, you can use a single index k in your loop
N = 5
kmax = N*(N+1)/2 + N
plot for [k=0:kmax] f(i(k), j(k), x) title sprintf('j = %d', j(k))

Resources