How to use a nested for loop to create a 1D array of integer pairs on a range? - arrays

In bash, I am trying to create 1-D array that contains all possible integer pairs on a range from a low value to a high value (i.e. 1 to 2)
I've tried using a nested for loop, however the out put I get is the array of the correct size, but all values are the high value (in this case 2)
I've tried nested for loops, however the array I am creating is not the correct size nor does it contain the correct combinations.
for (( i=$low; i<=$high; i++ ))
do
range_array[i]=$i
done
range=${#range_array[#]}
range_squared=$(( $range*$range))
new_range=$(( 2*$range_squared))
for (( i = $low; i <= $high; i++ ));do
for (( j = 1; j <= $new_range; j++ )) do
combo_array[j]=$i
done
done
echo "the following is the combo array"
echo ${combo_array[#]}
I expect the combo_array to be:
1 1 1 2 2 1 2 2
instead it is
2 2 2 2 2 2 2 2

That's too much work for such a trivial task. Here is a simple and working one:
combo_array=()
for ((i=low; i<=high; ++i)); do
for ((j=low; j<=high; ++j)); do
combo_array+=("$i" "$j")
done
done
echo "${combo_array[#]}"
Given low=6 and high=9, it outputs
6 6 6 7 6 8 6 9 7 6 7 7 7 8 7 9 8 6 8 7 8 8 8 9 9 6 9 7 9 8 9 9

Related

Equalize to zero a different element of a matrix for each row without loop

I have an IxS matrix called numerateur and I would like to set one element per row to zero. However, the column to which this element belongs changes for each row. I can do it with a loop but would like to use a more efficient method.
You can find my loop below:
choice is an Ix1 vector containing, for each row, the column number of the element I want to set to zero in numerateur.
for i = 1:I
rank1 = choice(i);
numerateur(i,rank1) = 0;
end
You need to convert the column indices to linear indices:
ind = (1:size(numerateur,1)) + (choice(:).'-1)*size(numerateur,1);
numerateur(ind) = 0;
Example:
>> numerateur = randi(9,5,7)
numerateur =
8 7 8 3 2 8 4
7 8 6 3 6 1 3
8 9 5 5 5 9 5
4 4 2 7 4 9 9
1 6 7 3 8 7 9
>> choice = [2; 3; 6; 5; 1];
>> ind = (1:size(numerateur,1)) + (choice(:).'-1)*size(numerateur,1);
>> numerateur(ind) = 0;
>> numerateur
numerateur =
8 0 8 3 2 8 4
7 8 0 3 6 1 3
8 9 5 5 5 0 5
4 4 2 7 0 9 9
0 6 7 3 8 7 9
Use implicit expansion to find logical indices:
numerateur(choice == 1:size(numerator,2)) = 0;
Alternatively you can use sparse matrix to generate logical indices:
numerateur(sparse(1:I,choice,true,I,S)) = 0;

Loop a 2D array vertically and choose one from each line

How to loop a 2D array, such as
1 2 3 4
5 6 7 8
9 10 11 12
choose one from each line everytime, left first. The expected order for the example is:
1 5 9
2 5 9
1 6 9
1 5 10
2 6 9
2 5 10
1 6 10
2 6 10
....
Thanks.
you can try two for loops
$a[$row][$column];
for($i=0; $i <$row; i++) {
for($j=0; $j<$column;$j++){
echo $a[$j][$i];
}
}
you can indent after 1 loop

MATLAB: how to pass in the diagonal of a matrix as an argument in another matrix?

Let c be 2D array, and x and y be 1D arrays of the same length (for instance, let's have x=1:7 and y=3:9).
I need to find a way to pass in arguments from x and y in the way I will describe below.
If I put simply c(x,y) it will give a 7 by 7 matrix. I don't want that.
Instead, I want to pass in the diagonal of the [x y] matrix: ((x(1), y(1)), (x(2), y(2))...(x(7), y(7)). Is there a way to do this without a for loop or any iterative statement?
You are looking for sub2ind function
res = c( sub2ind(size(c), x, y ) )
There's an easier way. If you're looking for a diagonal, use diag. If you have a matrix c:
c =
5 8 4 2 9 1 6 1 1
9 8 7 5 9 3 2 7 5
2 3 9 10 2 1 4 2 2
3 2 9 2 4 4 7 2 4
3 9 10 8 7 5 2 1 8
5 6 3 7 6 1 10 5 2
6 1 7 3 10 8 2 4 2
you can find the main diagonal by using diag with no extra arguments:
>> diag(c)
ans =
5
8
9
2
7
1
2
The second argument, though, indicates which diagonal you want as an offset from the main diagonal. So the default diagonal is equal to 0. If you want the diagonal starting at c(1,3), that's 2 above the main diagonal, so
>> diag(c,2)
ans =
4
5
2
4
2
5
2
Similarly, if you want the diagonal starting at c(4,1), the offset is -3:
>> diag(c,-3)
ans =
3
9
3
3

Array processing, shapes

I have a square 2d array of values, where each row is identical, and where each element of row is one bigger than the last. For example:
1 2 3 4 5 6 7
1 2 3 4 5 6 7
1 2 3 4 5 6 7
1 2 3 4 5 6 7
1 2 3 4 5 6 7
1 2 3 4 5 6 7
1 2 3 4 5 6 7
I want to filter them, such that I can make a diamond as such:
1
1 2 3
1 2 3 4 5
1 2 3 4 5 6 7
1 2 3 4 5
1 2 3
1
Notice how the first part of the array is used, no matter how many elements are to be printed on that line. Also, spacing doesn't matter. I spaced them to show the diamond.
I know how to filter the top right "chunk" out, using j-i<(j/2). This will convert the original square into:
1
1 2 3
1 2 3 4 5
1 2 3 4 5 6 7
1 2 3 4 5 6 7
1 2 3 4 5 6 7
1 2 3 4 5 6 7
How can I get the bottom right "chunk" to filter out also? What additional condition can I impose on the values?
Presuming you have found out and stored the length of the "side" of the square already then you could use something like below. However, if your square has an even length then it will not work (can't produce a diamond in this way from an even side length square).
The following is pseudo-code so you will need to adapt it for your language. I've also used 0-indexed arrays and presumed square is a 2D array.
for (i=0, i<length, i++)
{
for (j=0, j<Length, j++)
{
if (i < length/2)
{
if (j < length/2 AND j <= i)
print square[i][j]
}
}
else
{
if (j < length/2 AND j <= (length - i))
{
print square[i][j]
}
}
}
print newline
}

Matlab- Combinations for subsets of a set

Hi may I know how i can perform this using matlab?
I tried nchoosek but only works on 1 type of combination. I would like to output all together in array
Let S={a,b,c,d,e}
I would like to get combinations as such which start from 3 combinations:
the 3-combinations : {a,b,c} , {a,b,d} , {a,b,e} , {a,c,d} , {a,c,e} , {a,d,e}
the 4-combinations : {a,b,c,d} , {a,b,c,e} , {a,c,d,e}
the 5-combinations : {a,b,c,d,e}
So the output would be like this:
{a,b,c} {a,b,d} {a,b,e} {a,c,d} {a,c,e} {a,d,e}{a,b,c,d} {a,b,c,e} {a,c,d,e}{a,b,c,d,e}
Thanks
You can use a loop there or arrayfun which is just a compact way to express such a loopy approach and not a vectorized approach -
combs = arrayfun(#(x) nchoosek(S,x),3:numel(S),'Uniform',0)
The output would be a cell array with each cell representing values for each combination. So, when you run the code, you would get -
>> combs{1}
ans =
2 7 4
2 7 1
2 7 9
2 4 1
2 4 9
2 1 9
7 4 1
7 4 9
7 1 9
4 1 9
which would be your 3-combinations set.
>> combs{2}
ans =
2 7 4 1
2 7 4 9
2 7 1 9
2 4 1 9
7 4 1 9
would be your 4-combinations set and so on.

Resources