Apologies for the clumsy wording, I am struggling on how to describe this problem.
My goal is to write a function that takes in three variables and outputs a 2D array with this pattern:
var foo = function(x, y, z) {
array = [
[x + 8, y + 16, z + 35],
[x + 6, y + 8, z + 30],
[x + 4, y + 4, z + 20],
[x + 2, y + 2, z + 10],
[x , y , z ],
[x - 2, y + 2, z - 10],
[x - 4, y + 4, z - 20],
[x - 6, y + 8, z - 30],
[x - 8, y + 16, z - 35]
]
return array;
}
Obviously, this way of writing the function seems pretty inefficient.
One way I tried to solve this is with a loop. But my solution introduces three arrays and is also pretty inelegant.
var x_mod = [8, 6, 4, 2, 0, -2, -4, -6, -8];
var y_mod = [16, 8, 4, 2, 0, 2, 4, 8, 16];
var z_mod = [35, 30, 20, 10, 0, -10, -20, -30, -35];
for(let i = 0; i < 9; i++) {
array[i] = [x + x_mod[i], y + y_mod[i], z + z_mod[i]);
}
Is there a better way of writing this algorithm? I would also appreciate any clues as to what this kind of problem is called, or what I should study to solve it.
Thank you!
EDIT
This is an example of the kind of optimization I was thinking of.
The following function
var bar = function(x, y, z) {
array = [
[x + 1, y + 2, z + 3],
[x + 2, y + 4, z + 6],
[x + 3, y + 6, z + 9]
]
return array;
}
could also be written in the following way:
var bar = function(x, y, z) {
array = [];
for(var i = 1; i < 4; i++)
array[i] = [x + i, x + i*2, x + i*3];
return array;
}
This is the kind of "optimization" that I wanted to apply to my original problem. Again, I apologize that I lack the vocabulary to adequately describe this problem.
Is this what you are looking for (in c# code).
static class Program
{
static void Main(string[] args)
{
var m_2 = GenerateMatrix(2, 0.0, 0.0, 0.0);
// result:
// | 2.0 2.0 10.0 | + span = 2
// | 0.0 0.0 0.0 | +
// | -2.0 -2.0 -10.0 |
var m_3 = GenerateMatrix(3, 0.0, 0.0, 0.0);
// result:
// | 4.0 4.0 20.0 | +
// | 2.0 2.0 10.0 | | span = 3
// | 0.0 0.0 0.0 | +
// | -2.0 -2.0 -10.0 |
// | -4.0 -4.0 -20.0 |
var m_5 = GenerateMatrix(5, 0.0, 0.0, 0.0);
// result:
// | 8.0 16.0 40.0 | +
// | 6.0 8.0 30.0 | |
// | 4.0 4.0 20.0 | | span = 5
// | 2.0 2.0 10.0 | |
// | 0.0 0.0 0.0 | +
// | -2.0 -2.0 -10.0 |
// | -4.0 -4.0 -20.0 |
// | -6.0 -8.0 -30.0 |
// | -8.0 -16.0 -40.0 |
}
static double[][] GenerateMatrix(int span, double x, double y, double z)
{
var result = new double[2*(span-1)+1][];
result[span-1] = new double[] { x, y, z };
for (int i = 0; i < span-1; i++)
{
result[span-2-i] = new double[] { x+2*(i+1), y + (2<<i), z + 10*(i+1) };
result[span+i] = new double[] { x-2*(i+1), y - (2<<i), z - 10*(i+1) };
}
return result;
}
I am using the following rules (use counter=1..span-1). Set the rows symmetrically from the middle since they follow the same pattern with only + or - as a difference:
x values are multiples of twos, x+2*counter and x-2*counter
y values are power of twos, pow(2,counter)=2<<counter
z values are multiples of tens, x+10*counter and x-10*counter
While I think that your first definition is the best, formulas might be defined:
diff = (4 - i)
ad = abs(diff)
x + diff * 2
y + (1 << abs(ad)) - trunc((4 - ad) / 4)
//using bit shift to compose power of two if possible
z + 10 * diff - 5 * trunc(diff / 4)
//rounding towards zero!
Python check:
import math
for i in range(0, 9):
diff = (4 - i)
ad = abs(diff)
print(i, diff * 2, (1 << abs(ad)) - (4 - ad) // 4, 10 * diff - 5 * math.trunc(diff / 4))
0 8 16 35
1 6 8 30
2 4 4 20
3 2 2 10
4 0 0 0
5 -2 2 -10
6 -4 4 -20
7 -6 8 -30
8 -8 16 -35
you can use recursive approach for your solution:
var your_array = []
function myFun(x, y, z, count){
//base case
if(count = 4)
return;
// head recursion
temp = [];
temp.push(x); temp.push(y); temp.push(z);
your_array.push(temp);
myFun(x-2, y/2, z-10, count+1)
//tail recursion
temp = []
temp.push(x); temp.push(y); temp.push(z);
your_array.push(temp);
}
Related
I've written a function in matlab which generates a matrix using a loop. I was wondering if it is possible to generate the same results without a loop. X can either be a 1 x 50, 2 x 50, 3 x 50, etc... the values range from 1 to 50 incrementally for each column per row.
For example
1 x 1 = 1,
2 x 1 = 1,
3 x 1 = 1,
1 x 2 = 2,
2 x 2 = 2,
3 x 2 = 2,
.....................
1 x 50 = 50,
2 x 50 = 50,
3 x 50 = 50,
My function:
function [i] = m(x)
[a, b] = size(x);
i = zeros(a, b);
for c = 1 : a
i(c, :) = (1:size(x,2));
end
end
Thanks.
Try this:
N = 3;
M = 50;
x = repmat((1:N)',M,1);
y = reshape(repmat((1:M)',1,N)',N*M,1);
%z = x.*y
z = strcat(num2str(x),'x',num2str(y),'=',num2str(x.*y))
This will give the same format in your question.
Use repmat:
output = repmat(1:size(x,2), size(x,1), 1);
Some alternatives are
output = ones(size(x,1),1)*(1:size(x,2));
and
output = cumsum(ones(size(x)),2);
One alternate to repmat(Luis's answer) is bsxfun
out = bsxfun(#times,ones(size(x,1),1),1:size(x,2))
Given an array {1,3,5,7}, its subparts are defined as {1357,135,137,157,357,13,15,17,35,37,57,1,3,5,7}.
I have to find the sum of all these numbers in the new array. In this case sum comes out to be 2333.
Please help me find a solution in O(n). My O(n^2) solution times out.
link to the problem is here or here.
My current attempt( at finding a pattern) is
for(I=0 to len) //len is length of the array
{
for(j=0 to len-i)
{
sum+= arr[I]*pow(10,j)*((len-i) C i)*pow(2,i)
}
}
In words - len-i C i = (number of integers to right) C weight. (combinations {from permutation and combination})
2^i = 2 power (number of integers to left)
Thanks
You can easily solve this problem with a simple recursive.
def F(arr):
if len(arr) == 1:
return (arr[0], 1)
else:
r = F(arr[:-1])
return (11 * r[0] + (r[1] + 1) * arr[-1], 2 * r[1] + 1)
So, how does it work? It is simple. Let say we want to compute the sum of all subpart of {1,3,5,7}. Let assume that we know the number of combinatiton of {1,3,5} and the sum of subpart of {1,3,5} and we can easily compute the {1,3,5,7} using the following formula:
SUM_SUBPART({1,3,5,7}) = 11 * SUM_SUBPART({1,3,5}) + NUMBER_COMBINATION({1,3,5}) * 7 + 7
This formula can easily be derived by observing. Let say we have all combination of {1,3,5}
A = [135, 13, 15, 35, 1, 3, 5]
We can easily create a list of {1,3,5,7} by
A = [135, 13, 15, 35, 1, 3, 5] +
[135 * 10 + 7,
13 * 10 + 7,
15 * 10 + 7,
35 * 10 + 7,
1 * 10 + 7,
3 * 10 + 7,
5 * 10 + 7] + [7]
Well, you could look at at the subparts as sums of numbers:
1357 = 1000*1 + 100*3 + 10*5 + 1*7
135 = 100*1 + 10*3 + 1*5
137 = 100*1 + 10*3 + 1*7
etc..
So, all you need to do is sum up the numbers you have, and then according to the number of items work out what is the multiplier:
Two numbers [x, y]:
[x, y, 10x+y, 10y+x]
=> your multiplier is 1 + 10 + 1 = 12
Three numbers [x, y, z]:
[x, y, z,
10x+y, 10x+z,
10y+x, 10y+z,
10z+x, 10z+y,
100x+10y+z, 100x10z+y
.
. ]
=> you multiplier is 1+10+10+1+1+100+100+10+10+1+1=245
You can easily work out the equation for n numbers....
If you expand invisal's recursive solution you get this explicit formula:
subpart sum = sum for k=0 to N-1: 11^(N-k) * 2^k * a[k]
This suggests the following O(n) algorithm:
multiplier = 1
for k from 0 to N-1:
a[k] = a[k]*multiplier
multiplier = multiplier*2
multiplier = 1
sum = 0
for k from N-1 to 0:
sum = sum + a[k]*multiplier
multiplier = multiplier*11
Multiplication and addition should be done modulo M of course.
I am attempting to multiply several matrices using a loop in C. I obtain the expected answer in R, but cannot obtain the expected answer in C. I suspect the problem is related to the += function which seems to double the value of the product after the first iteration of the loop.
I am not very familiar with C and have not been able to replace the += function with one that will return the expected answer.
Thank you for any advice.
First, here is the R code that returns the expected answer:
B0 = -0.40
B1 = 0.20
mycov1 = exp(B0 + -2 * B1) / (1 + exp(B0 + -2 * B1))
mycov2 = exp(B0 + -1 * B1) / (1 + exp(B0 + -1 * B1))
mycov3 = exp(B0 + 0 * B1) / (1 + exp(B0 + 0 * B1))
mycov4 = exp(B0 + 1 * B1) / (1 + exp(B0 + 1 * B1))
trans1 = matrix(c(1 - 0.25 - mycov1, mycov1, 0.25 * 0.80, 0,
0, 1 - 0.50, 0, 0.50 * 0.75,
0, 0, 1, 0,
0, 0, 0, 1),
nrow=4, ncol=4, byrow=TRUE)
trans2 = matrix(c(1 - 0.25 - mycov2, mycov2, 0.25 * 0.80, 0,
0, 1 - 0.50, 0, 0.50 * 0.75,
0, 0, 1, 0,
0, 0, 0, 1),
nrow=4, ncol=4, byrow=TRUE)
trans3 = matrix(c(1 - 0.25 - mycov3, mycov3, 0.25 * 0.80, 0,
0, 1 - 0.50, 0, 0.50 * 0.75,
0, 0, 1, 0,
0, 0, 0, 1),
nrow=4, ncol=4, byrow=TRUE)
trans4 = matrix(c(1 - 0.25 - mycov4, mycov4, 0.25 * 0.80, 0,
0, 1 - 0.50, 0, 0.50 * 0.75,
0, 0, 1, 0,
0, 0, 0, 1),
nrow=4, ncol=4, byrow=TRUE)
trans2b <- trans1 %*% trans2
trans3b <- trans2b %*% trans3
trans4b <- trans3b %*% trans4
trans4b
#
# This is the expected answer
#
# [,1] [,2] [,3] [,4]
# [1,] 0.01819965 0.1399834 0.3349504 0.3173467
# [2,] 0.00000000 0.0625000 0.0000000 0.7031250
# [3,] 0.00000000 0.0000000 1.0000000 0.0000000
# [4,] 0.00000000 0.0000000 0.0000000 1.0000000
#
Here is my C code. The C code is fairly long because I do not know C well enough to be efficient:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
char quit;
int main(){
int i, j, k, ii, jj, kk ;
double B0, B1, mycov ;
double trans[4][4] = {0} ;
double prevtrans[4][4] = {{1,0,0,0},
{0,1,0,0},
{0,0,1,0},
{0,0,0,1}};
B0 = -0.40 ;
B1 = 0.20 ;
for (i=1; i <= 4; i++) {
mycov = exp(B0 + B1 * (-2+i-1)) / (1 + exp(B0 + B1 * (-2+i-1))) ;
trans[0][0] = 1 - 0.25 - mycov ;
trans[0][1] = mycov ;
trans[0][2] = 0.25 * 0.80 ;
trans[0][3] = 0 ;
trans[1][0] = 0 ;
trans[1][1] = 1 - 0.50 ;
trans[1][2] = 0 ;
trans[1][3] = 0.50 * 0.75 ;
trans[2][0] = 0 ;
trans[2][1] = 0 ;
trans[2][2] = 1 ;
trans[2][3] = 0 ;
trans[3][0] = 0 ;
trans[3][1] = 0 ;
trans[3][2] = 0 ;
trans[3][3] = 1 ;
for (ii=0; ii<4; ii++){
for(jj=0; jj<4; jj++){
for(kk=0; kk<4; kk++){
trans[ii][jj] += trans[ii][kk] * prevtrans[kk][jj] ;
}
}
}
prevtrans[0][0] = trans[0][0] ;
prevtrans[0][1] = trans[0][1] ;
prevtrans[0][2] = trans[0][2] ;
prevtrans[0][3] = trans[0][3] ;
prevtrans[1][0] = trans[1][0] ;
prevtrans[1][1] = trans[1][1] ;
prevtrans[1][2] = trans[1][2] ;
prevtrans[1][3] = trans[1][3] ;
prevtrans[2][0] = trans[2][0] ;
prevtrans[2][1] = trans[2][1] ;
prevtrans[2][2] = trans[2][2] ;
prevtrans[2][3] = trans[2][3] ;
prevtrans[3][0] = trans[3][0] ;
prevtrans[3][1] = trans[3][1] ;
prevtrans[3][2] = trans[3][2] ;
prevtrans[3][3] = trans[3][3] ;
}
printf("To close this program type 'quit' and hit the return key\n");
printf(" \n");
scanf("%d", &quit);
return 0;
}
Here is the final matrix returned by the above C code:
0.4821 3.5870 11.68 381.22
0 1 0 76.875
0 0 5 0
0 0 0 5
This line
trans[ii][jj] += trans[ii][kk] * prevtrans[kk][jj] ;
is not right. You're modifying trans in place while you are still using it to compute the resultant matrix. You need another matrix to store the result of the multiplication temporarily. And then use:
// Store the resultant matrix in temp.
for (ii=0; ii<4; ii++){
for(jj=0; jj<4; jj++){
temp[ii][jj] = 0.0;
for(kk=0; kk<4; kk++){
temp[ii][jj] += trans[ii][kk] * prevtrans[kk][jj] ;
}
}
}
// Transfer the data from temp to trans
for (ii=0; ii<4; ii++){
for(jj=0; jj<4; jj++){
trans[ii][jj] = temp[ii][jj];
}
}
I have 5 columns x, y, r, g, b with values of line number, column number, red, green and blue. The lines of this n by 5 matrix are not in a particular order, however they are consistent with image(x,y) and the r,g,b.
I would like to do something like I=uint8(zeros(480,640,3) and just change those rgb values based on the n by 5 mat.
Something along the lines of I(mat(:,1), mat(:,2), 1)=mat(:,3) for red etc
The following uses the concept of linear indexing and the versatile bsxfun function:
m = 640; %// number of rows
n = 480; %// number of columns
I = zeros(m, n, 3, 'uint8'); %// initiallize directly as uint8
I(bsxfun(#plus, x(:)+(y(:)-1)*m, (0:2)*m*n)) = [r(:) g(:) b(:)]; %// fill values
Small example: for
m = 2;
n = 3;
x = [1 2 1];
y = [1 1 2];
r = [ 1 2 3];
g = [11 12 13];
b = [21 22 23];
the code produces
I(:,:,1) =
1 3 0
2 0 0
I(:,:,2) =
11 13 0
12 0 0
I(:,:,3) =
21 23 0
22 0 0
An alternative:
INDr = sub2ind([480, 640, 3], mat(:, 1), mat(:,2), ones([numel(mat(:,3)), 1]));
INDg = sub2ind([480, 640, 3], mat(:, 1), mat(:,2), 2*ones([numel(mat(:,3)), 1]));
INDb = sub2ind([480, 640, 3], mat(:, 1), mat(:,2), 3*ones([numel(mat(:,3)), 1]));
I=uint8(zeros(480,640, 3));
I(INDr)=mat(:,3);
I(INDg)=mat(:,4);
I(INDb)=mat(:,5);
Note that in Matlab, the convention between axes is different between images and arrays.
I have vectors m, x, y & I want m1, x1, y1 as commented below:
% given
m = [-4 -3 -2 2 3 4];
x = [2 5 6 7 9 1];
y = [10 23 34 54 27 32];
% required
% m1 = [2 3 4]; % only +ve value from m
% x1 = [13 14 3]; % adding numbers(in x) corres. to -ve & +ve value in m & putting below 2, 3, 4 respectively
% y1 = [88 50 42]; % adding numbers(in y) corres. to -ve & +ve value in m & putting below 2, 3, 4 respectively
m1 = m(m > 0) % this gives me m1 as required
Any hint for x1, y1 will be very helpful.
Assuming m is built as [vectorNegativeReversed, vectorPositiveOriginal] the solution can be quite straightforward:
p = numel(m)/2;
m1 = m(p+1:end)
x1 = x(p+1:end) + x(p:-1:1)
y1 = y(p+1:end) + y(p:-1:1)
What about some flippy action:
m = [-4 -3 -2 2 3 4];
x = [2 5 6 7 9 1];
y = [10 23 34 54 27 32];
idx = find( (m > 0) );
xdi = find( ~(m > 0) );
m1 = m(idx)
x1 = fliplr( x(xdi) ) + x(idx)
y1 = fliplr( y(xdi) ) + y(idx)
returning:
m1 =
2 3 4
x1 =
13 14 3
y1 =
88 50 42