Lets say I have an array of [1,2,3,4,5]
I want to attempt to traverse the array one less each time, while adding the numbers.
First time:
1+2+3+4+5 = 15
Second time:
2+3+4+5 = 14
Third time:
3+4+5 = 12
Fourth time:
4+5 = 9
Fifth time:
5 = 5
any help would be greatly appreciated!
Thank you so much.
-AbysssCoder
Since you tagged your question with MATLAB...
>> x = [1,2,3,4,5]; % define array
>> cumsum(x, 'reverse') % cumulative sum in reverse order
ans =
15 14 12 9 5
int[] arr = {1, 2, 3, 4, 5};
for (int i = 0; i < arr.length; i++) {
int sum = 0;
for (int j = i; j < arr.length; j++) {
sum += arr[j];
}
System.out.println(sum);
}
Something like this?
Related
let's say I have:
n = 14
n is the result of the following sums of integers:
[5, 2, 7] -> 5 + 2 + 7 = 14 = n
[3, 4, 5, 2] -> 3 + 4 + 5 + 2 = 14 = n
[1, 13] -> 1 + 13 = 14 = n
[13, 1] -> 13 + 1 = 14 = n
[4, 3, 5, 2] -> 4 + 3 + 5 + 2 = 14 = n
...
I would need a hash function h so that:
h([5, 2, 7]) = h([3, 4, 5, 2]) = h([1, 13]) = h([13, 1]) = h([4, 3, 5, 2]) = h(...)
I.e. it doesn't matter the order of the integer terms and as long as their integer sum is the same, their hash should also the same.
I need to do this without computing the sum n, because the terms as well as n can be very high and easily overflow (they don't fit the bits of an int), that's why I am asking this question.
Are you aware or maybe do you have an insight on how I can implement such a hash function?
Given a list/sequence of integers, this hash function must return the same hash if the sum of the integers would be the same, but without computing the sum.
Thank you for your attention.
EDIT: I elaborated on #derpirscher's answer and modified his function a bit further as I had collisions on multiples of BIG_PRIME (this example is in JavaScript):
function hash(seq) {
const BIG_PRIME = 999999999989;
const MAX_SAFE_INTEGER_DIV_2_FLOOR = Math.floor(Number.MAX_SAFE_INTEGER / 2);
let h = 0;
for (i = 0; i < seq.length; i++) {
let value = seq[i];
if (h > MAX_SAFE_INTEGER_DIV_2_FLOOR) {
h = h % BIG_PRIME;
}
if (value > MAX_SAFE_INTEGER_DIV_2_FLOOR) {
value = value % BIG_PRIME;
}
h += value;
}
return h;
}
My question now would be: what do you think about this function? Are there some edge cases I didn't take into account?
Thank you.
EDIT 2:
Using the above function hash([1,2]); and hash([4504 * BIG_PRIME +1, 4504 * BIG_PRIME + 2]) will collide as mentioned by #derpirscher.
Here is another modified of version of the above function, which computes the modulo % BIG_PRIME only to one of the two terms if either of the two are greater than MAX_SAFE_INTEGER_DIV_2_FLOOR:
function hash(seq) {
const BIG_PRIME = 999999999989;
const MAX_SAFE_INTEGER_DIV_2_FLOOR = Math.floor(Number.MAX_SAFE_INTEGER / 2);
let h = 0;
for (let i = 0; i < seq.length; i++) {
let value = seq[i];
if (
h > MAX_SAFE_INTEGER_DIV_2_FLOOR &&
value > MAX_SAFE_INTEGER_DIV_2_FLOOR
) {
if (h > MAX_SAFE_INTEGER_DIV_2_FLOOR) {
h = h % BIG_PRIME;
} else if (value > MAX_SAFE_INTEGER_DIV_2_FLOOR) {
value = value % BIG_PRIME;
}
}
h += value;
}
return h;
}
I think this version lowers the number of collisions a bit further.
What do you think? Thank you.
EDIT 3:
Even though I tried to elaborate on #derpirscher's answer, his implementation of hash is the correct one and the one to use.
Use his version if you need such an hash function.
You could calculate the sum modulo some big prime. If you want to stay within the range of int, you need to know what the maximum integer is, in the language you are using. Then select a BIG_PRIME that's just below maxint / 2
Assuming an int to be 4 bytes, maxint = 2147483647 thus the biggest prime < maxint/2 would be 1073741789;
int hash(int[] seq) {
BIG_PRIME = 1073741789;
int h = 0;
for (int i = 0; i < seq.Length; i++) {
h = (h + seq[i] % BIG_PRIME) % BIG_PRIME;
}
return h;
}
As at every step both summands will always be below maxint/2 you won't get any overflows.
Edit
From a mathematical point of view, the following property which may be important for your use case holds:
(a + b + c + ...) % N == (a % N + b % N + c % N + ...) % N
But yeah, of course, as in every hash function you will have collisions. You can't have a hash function without collisions, because the size of the domain of the hash function (ie the number of possible input values) is generally much bigger than the the size of the codomain (ie the number of possible output values).
For your example the size of the domain is (in principle) infinite, as you can have any count of numbers from 1 to 2000000000 in your sequence. But your codomain is just ~2000000000 elements (ie the range of int)
I have a simple 2D matrix like this in MATLAB:
A = [34 10;
23 10;
64 10];
What I need to do is to find max(A(:,1)), then while A(j,1) < max(A(:,1)) add rows like [A(j,1)+1 10] to the matrix, so I want to eventually get this:
A = [34 10;
35 10;
36 10;
37 10;
.
.
.
62 10;
63 10;
64 10;
.
23 10;
24 10;
25 10;
.
.
.
62 10
63 10
64 10
.
64 10];
I have written the following but it does not work:
for j = 1:size(A,1)
while A(j,1) < max(A(:,1))
A(end+1,:) = [A(j,1)+1 10];
end
end
Any ideas how I could do that?
You can try the following, for Matlab without loops:
my_max = max(A(:,1));
my_arrays = arrayfun(#(x) [x:my_max]', A(:,1), 'uni', 0);
my_expanded_column = cat(1,my_arrays{:});
my_output = [my_expanded_column, 10*ones(size(my_expanded_column))]
It first finds the maximum,
Then expands each entry to a range to the maximum,
Then combines all the ranges to one,
Then tacks on the second column of 10's.
Your while-loop gets stuck checking the same element over and over again (because you don't increment anything).
You could instead use a for-loop to count up from each element in A's first column. And make sure you add the rows to a new matrix, otherwise your loop will recursively expand A ad infinitum.
For example:
B = [];
index = 1; % keeps track of the last element of B
for j = 1:size(A,1)
for k = A(j,1):max(A(:,1))
B(index,:) = [k A(j,2)];
index = index + 1;
end
end
It's simple, I want to pick the biggest value of a line, make all other elements in a line equal to zero and then the position with the biggest value shall be transformed into 1.
This is the code:
float A [3][3];
A [0][0] = 1.1, A [0][1] = 3.2, A [0][2] = 1.3;
A [1][0] = 2.1, A [1][1] = 2.2, A [1][2] = 2.3;
A [2][0] = 3.1, A [2][1] = 3.2, A [2][2] = 3.3;
for (int i=0; i<3; i++) {
float biggest=-1000000;
int biggest_position=0;
for (int y=0; y<3; y++)
if (A [i][y]>biggest) {
biggest_position = y;
biggest = A[i][y];
cout << "biggest position" << biggest_position << endl;
}
for (int y=0; y<3; y++)
A [i][y] = 0;
A [i][biggest_position] = 1;
}
for (int i=0; i<3; i++)
for (int j=0; j<3; j++)
cout << A [i][j] << endl;
So what I need to do to rewrite properly this code in matlab language?
You can use max to find maximum, and create a all zero element matrix and put the max in first column of the matrix:
newA = zeros(size(A));
newA(:,1) = max(A,[],2);
Just do:
A = A==max(A); %array of zeros with only ones at the maximum of the columns of the array.
If you want the maximum of a row you transpose first using a '
A = (A'==max(A'))';
this may be what you want
a=[1,2,3;2,3,4;3,2,1;2,4,1]
[~,ap]= max(a,[],2);
atr=zeros(size(a))';
atr((1:size(a,1))*size(a,2)-size(a,2)+ap')=1;
atr'
and the result:
a =
1 2 3
2 3 4
3 2 1
2 4 1
ans =
0 0 1
0 0 1
1 0 0
0 1 0
it seems to be a more simple way by using matrix, you can try it
How can a structure i.e. 'settings' be filled more easily than with this code:
settings(1).exposure = 1;
settings(1).rebalancing = 0;
settings(2).exposure = 0;
settings(2).rebalancing = 0;
settings(3).exposure = 1;
settings(3).rebalancing = 1;
settings(4).exposure = 0;
settings(4).rebalancing = 1;
settings(5).exposure = 'benchmark';
settings(5).rebalancing = 0;
settings(6).exposure = 'benchmark';
settings(6).rebalancing = 1;
You can compress it using the struct function:
>> s = struct('exposure',{1,0,1,0,'benchmark','benchmark'},'rebalancing',{0,0,1,1,0,1});
>> s(6)
ans =
exposure: 'benchmark'
rebalancing: 1
The array literals can be replaced by any variable that contains your data, as long as all arrays are conforming in size.
you can create an array / matrix with [ 1 2 3 4 5 6]
then in a for loop, for each number ask an input
i=1:6;
for i:6;
settings(i).exposure=input(...);
settings(i).rebalancing=input(...);
end
I think you should be able with this. (its been sometime since I last used a computer with MatLab so I can't confirm)
I have a 3d matrix (3x3x3), and I need to extract 3d patches (2x2x2) and transform them in vectors.
In 2d, simply:
I=randi(5,3,3);
2d_patches=im2col(I,[2 2],'sliding');
What about 3d?
I=randi(5,3,3,3);
3d_patches= ???
im2col just works in 2d. In 3d I should recombine the vectors 1 and 7, 2 and 8, ...
Is there any fast function for this task?
I do not believe that there is any built-in way to do this. If you need it to be fast, it should be fairly simple to write your own mex-function in c and call it from Matlab.
Here is my (quick and dirty) solution:
im3col.c:
#include <mex.h>
void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] )
{
const mxArray *I = prhs[0];
double *indata = mxGetPr(I);
double *patchSize = mxGetPr(prhs[1]);
const int *size = mxGetDimensions(I);
int J = (int)patchSize[0], K = (int)patchSize[1], H = (int)patchSize[2];
int M = size[0], N = size[1], P = size[2];
int numPatches = (M - J + 1)*(N - K + 1)*(P - H + 1);
int out_rows = J*K*H, out_cols = numPatches;
mxArray *out = mxCreateDoubleMatrix( out_rows, out_cols, mxREAL );
double *outdata = mxGetPr(out);
int patch = 0;
for( int h_offset = 0; h_offset < P-H+1; h_offset++ ){
for( int k_offset = 0; k_offset < N-K+1; k_offset++ ){
for( int j_offset = 0; j_offset < M-J+1; j_offset++ ){
int row = 0;
for( int h = 0; h < H; h++ ){
for( int k = 0; k < K; k++ ){
for( int j = 0; j < J; j++ ){
outdata[patch*out_rows + row] =
indata[ (j_offset+j) + (k_offset+k)*M + (h_offset+h)*M*N ];
++row;
}}}
++patch;
}}}
plhs[0] = out;
}
Compile:
>> mex -O CFLAGS="\$CFLAGS -std=c99 -Wall" im3col.c
Test:
>> A(:,:,1) = [1,4,7;2,5,8;3,6,9]; A(:,:,2) = [10,13,16;11,14,17;12,15,18];
>> B = im3col(A, [2,2,1])
B =
1 2 4 5 10 11 13 14
2 3 5 6 11 12 14 15
4 5 7 8 13 14 16 17
5 6 8 9 14 15 17 18
>> A(:,:,1),A(:,:,2)
ans =
1 4 7
2 5 8
3 6 9
ans =
10 13 16
11 14 17
12 15 18
Here is the other direction:
(It is pretty slow and there is definitely a faster way)
function [img] = patch2im_2d_time(patch, size_img, size_patch, size_skip, border)
Nx = size_img(1);
Ny = size_img(2);
Nt = size_img(5);
psz1 = size_patch(1);
psz2 = size_patch(2);
psz3 = size_patch(3);
%Extract blocks. One could save a lot here.
patches = reshape(patch, [psz1 psz2 psz3 size(patch,2)]);
c = 1;
img2 = zeros(squeeze(size_img));
%Count for each pixel how many times we added smth to it.
add_count = zeros(size_img);
%The first three loops, loop through all the pixels in the image
for d=1:Nt-psz3+1
for j=1:Nx-psz2+1
for i=1:Ny-psz1+1
%Here we get the next patch. The next patch is always
%the patch that has the pixel at i,j,d at its top front corner.
current_patch = patches(:,:,:,c);
%counter for the next patch
c = c + 1;
%In this loop we add the patch values of each pixel in the
%patch to the image. i,j,d is the base. We add the offset
%ii jj and dd to it. This iteration takes psz^3 many
%iterations.
for dd=1:psz3
for ii=1:psz2
for jj=1:psz1
img2(i+ii-1,j+jj-1,d+dd-1) = img2(i+ii-1,j+jj-1,d+dd-1) + current_patch(ii,jj,dd);
add_count(i+ii-1,j+jj-1,d+dd-1) = add_count(i+ii-1,j+jj-1,d+dd-1) + 1;
end
end
end
end
end
end
img = flipud(rot90(img2 ./ add_count,1));
end
Remember that MATLAB uses col major.
%One possible way to use matlab to call im2col and reshape twice
%N = [row, col, num_frames]
[x_height, ~, num_frames] = size(N);
patchSize = 16;
patchTemporal = 10;
N = reshape(N, x_height, []);
N = im2col(N, [patchSize, patchSize], 'distinct');
N = reshape(N, [], num_frames);
N = im2col(N, [patchSize^2, patchTemporal], 'distinct');
% N = [patchSize^2 *patchTemporal x numPatches]
hi guys what about this solution. To obtain 3x3x3 ROIs from I suggest :
blkSize=3; % should be a odd value like 3,5,7,etc
r=floor(blkSize/2);
k=1;
for sliceNo=(r+1):(size(I,3)-r)
img= I(:,:,sliceNo-r:sliceNo+r);
noPix=(size(img,1)-2*r)*(size(img,2)-2*r);
neiblk=zeros(blkSize^3,noPix);
for blk=1:blkSize
neiblk(blkSize^2*(blk-1)+1:blkSize^2*blk,:)=im2col(img(:,:,blk),...
[blkSize,blkSize],'sliding');
end
ROIs(:,noPix*(k-1)+1:noPix*k)=neiblk;
k=k+1;
end