# How can I fill in a matrix at every iteration of a Do loop?

I have a matrix whose dimensions are 26x26x3. For my assignment I have written a program which is using a Do loop (maxx=maxy=10,maxz=2):

 Do[
n = 0;
h=0.4;
k = Table[
If[a <= #1 <= a + h && b <= #2 <= b + h && c <= #3 <= c + h & @@ pts[[w, t]], 1, 0],
{w, 1, Length[pts]},
{t, 1, Length[pts[[w]]]}
];
pls = Plus @@@ k;
For[i = 1, i <= Length[pls], i++, If[pls[[i]] > 0, n++]];
n,
{a, 1, maxx, h}, {b, 1, maxy, h}, {c, 1, maxz, h}
]


At every iteration I get a new value for n and I have to assign it to the correct position of my matrix as efficiently and fast as possible. I don't have a counter. So, I am a bit confused. How can I solve this issue?

On the other hand, can I create a matrix by saving n at the end of the Do loop?

Any help is appreciated.

-
What would the correct position be? –  ssch Jan 6 '13 at 16:06
@ssch Correct position : For example, first n will be positioned in the matrix at {1,1,1}; second n at {1,1,2} third n at {1,1,3} then y axes will change and fourth n will be positioned at {1,2,1} and so on.. –  cesm Jan 6 '13 at 16:19
Well with those values of h and maxx,maxy,maxz you'll just get 1587 values of n, so at best your result will be a 23*23*3 matrix. I'm not sure I understand what you are doing. Are you for each interval $[a,a+h] \times [b,b+h] \times [c,c+h]$ counting how many rows have at least one element inside? What dimensions do you expect for the resulting matrix? –  ssch Jan 6 '13 at 16:42
Could you make a small example matrix and the result you expect from that? –  ssch Jan 6 '13 at 16:43
@ssch Yes, you are right. The dimensions will be 23x23x3. Thanks. Is it possible to write a program that the values of n when c change will be assigned to values of z dimensions on that matrix? And the same for y and x axes. –  cesm Jan 6 '13 at 19:20

I think this does what you require:

Total[Unitize[BinCounts[#, {1, maxx + h, h}, {1, maxy + h, h}, {1, maxz + h, h}]] & /@ pts]

-
Ah BinCounts, I knew there was some command I was forgetting :) –  ssch Jan 6 '13 at 18:27
Ohh, thanks! This does what I want at one line :) –  cesm Jan 6 '13 at 20:05

I'm still not quite sure what output you expect, but at least this might be a way forward:

maxx = 10;
maxy = 10;
maxz = 2;
h = 0.4;
pts = RandomReal[{1, 10}, {26, 26, 3}];


You can start by replacing Do with Table to store your calculated n values

AbsoluteTiming[out=Table[(* Same stuff as in your Do *)];]
(* 8.5 seconds *)
out//Dimensions
(* {23,23,3} *)


You can replace the whole thing with:

AbsoluteTiming[out = Table[
Count[
MemberQ[#,_?(a<=#[[1]]<=a+h&&b<=#[[2]]<=b+h&&c<=#[[3]]<=c+h&)]&/@pts
,True]
, {a, 1, maxx, h}, {b, 1, maxy, h}, {c, 1, maxz, h}];]
(* 5.2 s *)


That counts (Count[...,True]) how many rows have at least one (MemberQ) good element.

Some speed increase can be gained by compiling the pattern test for MemberQ

inInterval = Compile[{a, b, c, h, {pt, _Real, 1}},
a <= pt[[1]] <= a + h && b <= pt[[2]] <= b + h && c <= pt[[3]] <= c + h
]
AbsoluteTiming[out2 = Table[
Count[MemberQ[#, _?(inInterval[a, b, c, h, #] &)] & /@ pts, True]
,{a, 1, maxx, h}, {b, 1, maxy, h}, {c, 1, maxz, h}];]
(* 3.5 s *)


check Count and MemberQ

3.5s still seems quite slow for this problem I expect someone to come up with a quicker solution :)

-

Here a illustrative example of assigning values, retaining your Do loop structure. It just has an incrementing count at the place where you could add your own calculation:-

maxx = 4; maxy = 3; maxz = 2;
k = Table[{a, b, c}, {a, 1, maxx}, {b, 1, maxy}, {c, 1, maxz}];
count = 1;
Do[k[[a, b, c]] = count++, {a, 1, maxx}, {b, 1, maxy}, {c, 1, maxz}]
MatrixForm[k]


-
But then you're disregarding the stepsize h, you could also just replace the Do with Table in the original code and get a matrix –  ssch Jan 6 '13 at 16:45
I assumed the OP specifically wanted to use Do. However, Do doesn't seem to support step size for multiple dimensions. Also, I couldn't see how a step size of 0.4 would work for stepping through a matrix. –  Chris Degnen Jan 6 '13 at 16:59