EDIT To address hard-coded Table and SparseArray limits, and efficiency
As pointed out in the comments, hard-coded limits on the Table or SparseArray dimensions may not work in general. Besides being slow, the Table approach quickly eats up system memory for moderate values of max. Here is a variation on WReach's recursive scheme using ReplaceRepeated. With max=5000, it is about a factor of 4 slower than using For.
Clear[max, a4];
max = 5000;
a4 = ConstantArray[0, max];
ReplaceRepeated[{1, 1, 1, 1},
{
{x_, y_, z_, n_} /; (r = 2 (2 n^2 + (y - 2) (z - 2) + x (y + z - 2) + 2 n (x + y + z - 3)))
<= max :> (If[z <= y <= x, a4[[r]]++]; {x, y, z, n + 1}),
(* Stop *)
{x_, 1, 1, 1} :> Null,
(* Optimizations *)
{x_, y_, 1, 1} :> If[y < x, {x, y + 1, 1, 1}, {x + 1, 1, 1, 1}],
{x_, y_, z_, 1} :> If[z < y, {x, y, z + 1, 1}, {x, y + 1, 1, 1}],
{x_, y_, z_, _} :> If[z < y, {x, y, z + 1, 1},
If[y < x, {x, y + 1, 1, 1}, {x + 1, 1, 1, 1}]]
}
, MaxIterations -> Infinity]
(Array-based solutions)
As far as readability, Table comes to mind:
Clear[val, a1, max];
max = 100;
a1 = ConstantArray[0, max];
val := 2 (2 n^2 + (y - 2) (z - 2) + x (y + z - 2) + 2 n (x + y + z - 3));
Table[If[val <= max, a1[[val]]++], {x, 1, max}, {y, 1, x}, {z, 1, y}, {n, 1, max}];
a1==a
(* True (at least for max=100) *)
I think this fulfils your "clean" and "non-contrived" criteria, but it is definitely not efficient: I set max to 100 because I didn't feel like waiting more than a few minutes for the answer!
EDIT
Also using Table, but without the If:
Clear[max, vals, a2];
max = 100;
vals = Table[2 (2 n^2 + (y - 2) (z - 2) + x (y + z - 2) +
2 n (x + y + z - 3)), {x, 1, max}, {y, 1, x}, {z, 1, y}, {n, 1,
max}];
a2 = BinCounts[Flatten@vals, {1, max + 1, 1}]
EDIT for SparseArray
Here is an approach using SparseArray in place of Table to get vals in the above. It is somewhat more efficient than Table, but not as efficient as the For loop way:
Clear[max, val, vals, a3];
max = 100;
vals = SparseArray[{x_, y_, z_, n_} /; 2 (2 n^2 + (y - 2) (z - 2) + x (y + z - 2) +
2 n (x + y + z - 3)) <= max && z <= y <= x :> 2 (2 n^2 + (y - 2) (z - 2) + x (y + z - 2) + 2 n (x + y + z - 3)), {max, max, max, max}];
a3 = Normal@BinCounts[Flatten@vals, {1, max + 1, 1}]
a3==a
(* True *)
There is probably a way to make the condition more readable, but I haven't found it.
Consider the relative timings for max==100:
For loops
~ 0.006 s
Table
~ 162 s
SparseArray
~ 0.8 s
But even SparseArray becomes horribly slow for n = 200.
ListPlot[a]looks very familiar... – rm -rf♦ Feb 22 '12 at 20:06