# 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}]

-
The version listed in Heike's answer is slightly shorter than (and not too different from) the one given here... –  Ｊ. Ｍ. 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

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? –  Ｊ. Ｍ. 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. –  Ｊ. Ｍ. 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]. –  Ｊ. Ｍ. 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.}} *)

-