Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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?

share|improve this question
add comment

9 Answers 9

up vote 9 down vote accepted

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}]
share|improve this answer
3  
The version listed in Heike's answer is slightly shorter than (and not too different from) the one given here... –  J. M. Feb 11 '12 at 23:38
2  
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
add comment

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.

share|improve this answer
    
@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
1  
@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
show 2 more comments

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}]]
share|improve this answer
1  
The function is defined as f[x_Integer] :) –  CHM Feb 11 '12 at 22:44
1  
@Mr.Wizard I think you owe me 15 rep ;-) –  Heike Feb 11 '12 at 23:46
1  
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
1  
@Mr. Wizard: you do know that moderators are capable of deleting accepted answers, no? –  J. M. Feb 12 '12 at 0:14
1  
@Mr. Wizard, as you wish. The situation just doesn't sit well with me, but I leave this to your judgment. –  J. M. Feb 12 '12 at 4:03
show 8 more comments

One possibility is this:

Riffle[
 ConstantArray[a, Ceiling[Length[a]/2]], 
 ConstantArray[b, Floor[Length[a]/2]]
]
share|improve this answer
    
@CHM Actually you could replace the second ConstantArray[...] by {b} to simplify things a bit. –  Szabolcs Feb 11 '12 at 22:56
1  
Floor[Length[a]/2] is more conventionally written as Quotient[Length[a], 2]. –  J. M. 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
add comment

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 :)

share|improve this answer
    
It works now, thanks. –  CHM Feb 11 '12 at 23:13
add comment

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}}
share|improve this answer
    
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
add comment

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}]
  ]
share|improve this answer
add comment

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];
share|improve this answer
add comment

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.}} *)
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.