I propose these:
vals = {1, 2, 3, 4};
n = 4;
SparseArray[Array[Band[{#, 1}] -> vals[[#]] &, n], n] // Normal
Reverse @ PadRight @ NestList[Rest, Reverse @ vals, n-1]
PadLeft @ NestList[Most, vals, n-1] ~Reverse~ {1, 2}
UpperTriangularize[NestList[RotateRight, vals, n-1]] ~Reverse~ {1, 2}
With[{r = Reverse@vals}, PadLeft[r, n, 0, n - #] & ~Array~ n]
#@Partition[#@vals, n, 1, 1, 0] &[Reverse]
PadRight[#, n] & /@ NestList[Rest, Reverse @ vals, n - 1] // Reverse
Table[
v = Prepend[Most@v, vals[[i]]],
{v, {ConstantArray[0, n]}},
{i, n}
] // First
All produce:
{{1, 0, 0, 0}, {2, 1, 0, 0}, {3, 2, 1, 0}, {4, 3, 2, 1}}
Notes:
Something I've known for a while but didn't account for here is that PadLeft
/PadRight
on a ragged array of packed lists unpacks. My second and third methods have this problem. By using PadRight
on each packed vector these can be greatly improved for that specific case.
Timings
Alright, I believe we have enough options for the first timing comparison. Using my flavor of Timo's timeAvg
:
SetAttributes[timeAvg, HoldFirst]
timeAvg[func_] := Do[If[# > 0.3, Return[#/5^i]] & @@ Timing@Do[func, {5^i}], {i, 0, 15}]
And this (packed) data:
n = 1500;
vals = RandomInteger[9999, 1500];
The timings for my proposals:
SparseArray[Array[Band[{#, 1}] -> vals[[#]] &, n], n] // timeAvg
Reverse@PadRight@NestList[Rest, Reverse @ vals, n - 1] // timeAvg
PadLeft@NestList[Most, vals, n - 1] ~Reverse~ {1, 2} // timeAvg
UpperTriangularize[NestList[RotateRight, vals, n - 1]] ~Reverse~ {1, 2} // timeAvg
With[{r = Reverse@vals}, PadLeft[r, n, 0, n - #] & ~Array~ n] // timeAvg
#@Partition[#@vals, n, 1, 1, 0] &[Reverse] // timeAvg
PadRight[#, n] & /@ NestList[Rest, Reverse @ vals, n - 1] // Reverse // timeAvg
Table[
v = Prepend[Most@v, vals[[i]]],
{v, {ConstantArray[0, n]}},
{i, n}
] // First // timeAvg
1.669
0.1342
0.1778
0.0362
0.003744
0.008112
0.004992
0.003992
And other's proposals:
f[i_, j_] /; i < j := 0
f[i_, j_] := vals[[i - j + 1]]
Array[f, {n, n}] // timeAvg
Table[If[i >= j, vals[[i - j + 1]], 0], {i, n}, {j, n}] // timeAvg
NestList[PadLeft[#, n + 1][[ ;; -2]] &, vals, n - 1] // Transpose // timeAvg
NestList[ArrayPad[#, {-1, 1}] &, Reverse@vals, n - 1] // Reverse // timeAvg
Reverse /@ ListConvolve[ConstantArray[1, Length@vals], vals, 1, 0, Times, List] // timeAvg
LowerTriangularize@MapIndexed[RotateRight, ConstantArray[Reverse@vals, n]] // timeAvg
Array[vals[[#1 - #2 + 1]] UnitStep[#1 - #2] &, {n, n}] // timeAvg
1.981
1.576
0.010608
0.006864
0.2246
0.134
3.573
I expected Band
to perform better which is why I led with it, but it actually scales very poorly. Kuba's method is faster than any of my four original ones but it inspired my fifth method which is the fastest so far on this test. I'll update timings as more options come in and with more detailed tests.
panda-34 get's his own special section for these beautiful incantations; the fastest yet!
Reverse @ HankelMatrix @ Reverse @ vals // timeAvg
LowerTriangularize @ ToeplitzMatrix @ vals // timeAvg
0.002872
0.002496