# Generating a matrix using sublists A and B n times

I want to write a function that generates a square matrix from sublists. My sublists are

a = Range[0, x, 0.5]; b = Range[0.25, x + 0.25, 0.5];

Suppose x=2, then I can manually evaluate {a,b,a,b,a} to generate an 5x5 matrix. I want to make the matrix automatically, of course, but without using a loop.

I've tried different ways to do it, with Nest, Range and Table, but I can't make it work.

Do I absolutely have to use a loop?

Perhaps this:

x = 2;
a = Range[0, x, 0.5];
b = Range[0.25, x + 0.25, 0.5];

PadRight[#, Length@#[[1]], #] & @ {a, b}


Could also be written:

PadRight[{a,b}, Length@a, {a,b}]


### Performance

There is a reason to use the form I proposed over that which Heike gave. If the first argument of PadRight is a packed array, and the padding list is packable (but not necessarily packed) the result will also be packed, and it is produced more quickly than if it were not packed.

foo = Range[5]; (* packed array *)

(r1 = PadRight[{},  5*^6, foo];) // RepeatedTiming
(r2 = PadRight[foo, 5*^6, foo];) // RepeatedTiming

DeveloperPackedArrayQ /@ {r1, r2}
Divide @@ ByteCount /@ {r1, r2} // N

{0.047, Null}

{0.0096, Null}

{False, True}

2.99999


So using the list to pad as the seed instead of {} can result in five times better speed and three times better memory consumption.

However as Karsten 7. notes this doesn't actually help with the question example. In either case the vector elements are kept packed but the outer list is not:

Needs["Developer"]

PackedArrayQ /@ PadRight[#,  Length@#[[1]], #] &@{a, b}
PackedArrayQ /@ PadRight[{}, Length@#[[1]], #] &@{a, b}

{True, True, True, True, True}
{True, True, True, True, True}


So while in principle it is better to pad the input list rather than {} as some cases greatly benefit from it, this case does not.

• The version listed in Heike's answer is slightly shorter than (and not too different from) the one given here... – J. M.'s technical difficulties Feb 11 '12 at 23:38
• I ran AbsoluteTiming[] on every answer given, and this is the one that was the fastest on my system (with x=35). I felt like I had to choose, and well.. I accepted this answer. The difference between Heike's answer and this one is that Mr.Wizard's is a pure function, a concept that I had not encountered before. – CHM Feb 12 '12 at 2:38
• Unfortunately {a,b} is not a packed array. I tried replacing {a,b} with ab defined as ab = DeveloperToPackedArray[{a, b}];, but PadRight[ab, Length@a, ab] // DeveloperPackedArrayQ is False. Is there any way to get the result as a packed array? – Karsten 7. Jul 29 '15 at 22:01
• @Karsten It seems that the individual elements (a, b) are packed but the outer list is not, in either case. I amended my answer to note this. – Mr.Wizard Jul 29 '15 at 22:24

Since b is a+0.25, you could use Outer like this:

Outer[Plus, PadRight[{}, Length[a], {0, 0.25}], a]


You could also create the list of 0s and 0.25s using Riffle as in the other answers

(you guys are so fast! It makes iPad use a real handicap :)

• It works now, thanks. – CHM Feb 11 '12 at 23:13

You could do something like

mat[x_] := Module[{a = Range[0, x, .5], b = Range[.25, x + .25, .5]},
Riffle[ConstantArray[a, x + 1], {b}]]


Then mat[2] gives

{{0., 0.5, 1., 1.5, 2.}, {0.25, 0.75, 1.25, 1.75, 2.25}, {0., 0.5, 1.,
1.5, 2.}, {0.25, 0.75, 1.25, 1.75, 2.25}, {0., 0.5, 1., 1.5, 2.}}


Edit

Perhaps more elegant. This should also work if x isn't an integer.

mat[x_] := Module[{a = Range[0, x, .5], b = Range[.25, x + .25, .5]},
PadRight[{}, Floor[2 x + 1], {a, b}]]

• The function is defined as f[x_Integer] :) – CHM Feb 11 '12 at 22:44
• @Mr.Wizard I think you owe me 15 rep ;-) – Heike Feb 11 '12 at 23:46
• Heike I would have deleted my answer but CHM already Accepted it. I have to leave right now but I think "what to do in this situation" is worthy of a Meta post. Sorry. :-/ – Mr.Wizard Feb 11 '12 at 23:55
• @Mr. Wizard: you do know that moderators are capable of deleting accepted answers, no? – J. M.'s technical difficulties Feb 12 '12 at 0:14
• @Mr. Wizard, as you wish. The situation just doesn't sit well with me, but I leave this to your judgment. – J. M.'s technical difficulties Feb 12 '12 at 4:03

One possibility is this:

Riffle[
ConstantArray[a, Ceiling[Length[a]/2]],
ConstantArray[b, Floor[Length[a]/2]]
]

• @CHM Actually you could replace the second ConstantArray[...] by {b} to simplify things a bit. – Szabolcs Feb 11 '12 at 22:56
• Floor[Length[a]/2] is more conventionally written as Quotient[Length[a], 2]. – J. M.'s technical difficulties Feb 11 '12 at 22:59
• @J.M. Well, conventions change from place to place so it depends who you ask :-) I use that form as well sometimes, but here what I really needed was the Ceiling, and the Floor is more symmetrical with that. Also, I realized the Floor part wasn't necessary as a simple {b} would do as in @Heike's answer ... – Szabolcs Feb 11 '12 at 23:08
• This is the method I was thinking of, or at least close enough that I don't have to bother putting an answer together. – rcollyer Feb 12 '12 at 1:54

Here is one way without a loop:

Take[Flatten[ConstantArray[{a, b}, {Ceiling[Length[a]/2]}], 1], Length[a]]


You could also use Riffle, I guess.

• @CHM You mean I used loops for this kind of stuff in the book ?! I thought better of myself. – Leonid Shifrin Feb 11 '12 at 22:44
• Quite the opposite - you suggest NOT to use loops, and make use of Mathematica's functional programming capabilities instead. As I'm learning to use Mathematica, I'd rather learn to code efficiently. – CHM Feb 11 '12 at 22:45
• @CHM Well, that's a relief. I started thinking I did use loops, which would mean that I wasn't in the right mind when writing that part. – Leonid Shifrin Feb 11 '12 at 22:48
• @CHM In fact, today is an anniversary - it is exactly 3 years that I released the book to the general audience (it was written one year prior to that, but I did not have a web version). – Leonid Shifrin Feb 11 '12 at 22:51
• Congratulations on being first to 5000! :-) – Mr.Wizard Feb 12 '12 at 4:32

I find using Band in a SparseArray interesting.

mat[x_] :=
Block[{a = Range[0, x, .5],
b = Range[.25, x + .25, .5], ln},
ln = Length[a];
SparseArray[Band[{1, 1}, {ln, ln}] -> {a, b}, {ln, ln}]
]


You've gotten several good answers already. Another way of doing it is to use MapIndexed as:

MapIndexed[If[EvenQ@First@#2, b, a] &, a];


This should be reasonably fast, but certainly not as fast as the PadRight answer. In the same vein, you can use related conditional constructs, Switch and Which as:

 MapIndexed[Switch[EvenQ@First@#2, True, b, False, a] &, a];
MapIndexed[Which[Mod[#2, 2] == {1}, a, Mod[#2, 2] == {0}, b] &, a];


Or ...

Using ConstantArray:

 mat0 := Most@Flatten[#, 1] & /@
({#, .25 + #} & /@ ConstantArray[#, Ceiling[(Length@#)/2]]&@
Range[0, #, .5] &) ;
mat0@2.2
(* gives *)


{{0., 0.5, 1., 1.5, 2.}, {0.25, 0.75, 1.25, 1.75, 2.25}, {0., 0.5, 1., 1.5, 2.}, {0.25, 0.75, 1.25, 1.75, 2.25}, {0., 0.5, 1., 1.5, 2.}}

Using Table:

 mat2:=Most@Flatten[#, 1] & /@ (Transpose /@
Table[{#, .25 + #} & /@ #, {Ceiling[(Length@#1)/2]}] &@ Range[0, #, .5] &)


Using NestList:

 mat3:=Most@Flatten[#, 1] & /@
(NestList[Join, {#1, #2}, Floor[(Length@#1)/2]] & @@ {#, .25 + #} &
@Range[0, #, .5] &)


Using Table again (less cluttered and more general):

 mat4:= Table[{#2, #1}[[1 + Mod[i, 2]]], {i, #3}] &;
mat5 := Table[{#1, #2}[[1 + Mod[i, 2]]], {i, 0, #3 - 1}] &;
mat4[{a, b, c, d}, {e, f, g}, 5]
(* and  *)
mat5[{a, b, c, d}, {e, f, g}, 5]
(* both give *)

{{a, b, c, d}, {e, f, g}, {a, b, c, d}, {e, f, g}, {a, b, c, d}}

• Nice. Clearly, my methods using Table and Nest(List) weren't as involved as yours, but they didn't work either. – CHM Feb 12 '12 at 2:17

Let me join. This variant avoids explicit a and b initialization.

x = 2; n = 2 x + 1;
SparseArray[{
{i_, j_} /; OddQ@i -> 0.5 (j - 1),
{i_, j_} /; EvenQ@i -> 0.5 j - 0.25},
{n, n}] // Normal

(* ==>
{{0, 0.5, 1., 1.5, 2.},
{0.25, 0.75, 1.25, 1.75, 2.25},
{0, 0.5, 1., 1.5, 2.},
{0.25, 0.75, 1.25, 1.75, 2.25},
{0, 0.5, 1., 1.5, 2.}} *)