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.
diamond[n_Integer] := 
 Table[1, {#}] & /@ (Range[n]~ Join~Range[n - 1, 1, -1])

diamond[5] // MatrixForm

enter image description here

How could a more functional, "tablefree", solution look like?

EDIT

Thanks for the nice comments and answers so far :)

But I'm looking for a 1-2-3-4-3-2-1 or 1-2-3-4-5-4-3-2-1 sequence which DiamondMatrix doesn't seem to offer.

share|improve this question
    
@Öskå Thanks, but it's not "ragged", but filled with zeroes –  eldo Aug 10 at 19:09
    
@eldo I believe number of roms should equal 2n-1. most of answerer did not consider this issue. –  Algohi Aug 10 at 19:46
    
@Algohi You posted an answer approx 20 minutes ago which gave what I expected. Why did you delete it? Please repost! –  eldo Aug 10 at 19:49
4  
DeleteCases[0] /@ DiamondMatrix[10] ? –  Szabolcs Aug 10 at 20:02
    
@eldo, I was having some problems with pc and then kguler did something similar and I did not want to repeat. –  Algohi Aug 10 at 23:06

11 Answers 11

up vote 4 down vote accepted

Not much to add to the existing answers except that my favorite method to convert lists of natural numbers to all ones is x^0 therefore:

f[n_] := Range[n - Abs @ Range[1-n, n-1]]^0

Also I don't believe anyone has yet used Diagonal:

f2[n_] := With[{m = BoxMatrix[(n - 1)/2]}, Array[m ~Diagonal~ # &, 2 n - 1, 1 - n]]
share|improve this answer
    
Your first solution clearly shows why everybody (including myself) should respect the 48-hours-rule before accepting :) –  eldo Aug 11 at 22:35
    
@eldo Not that I expect you to but you can change the Accept if you wish. I agree however that it's best not to Accept too quickly as I believe it reduces interest in your Question. –  Mr.Wizard Aug 11 at 23:11
    
My "mathematical conscience" tells me that I must change the acceptance because of your first solution. –  eldo Aug 11 at 23:26
    
@eldo Well, thank you. :-) –  Mr.Wizard Aug 11 at 23:28
1  
Since in this case there are no negative numbers, I would use UnitStep to get the ones –  RunnyKine Aug 12 at 0:29

I know I'm a little bit late to the party but here's a way to generate the ragged diamond using DiamondMatrix directly:

(* Generate double diamond surrounded by zeros using DiamondMatrix*)
diamondWithin = DiamondMatrix[{4, 5}, {9, 10}];
(* Trim the zeros and resulting empty lists (if any) *)
trimZero = diamondWithin //. {0 :> Sequence[], {} :> Sequence[]};
(* Half the number of 1's in each row *)
goalDiamond = trimZero /. {x__, x__} :> {x};

(* Display *)
{diamondWithin // MatrixForm[# /. {1 :> Style[1, Red]}] &, 
  MatrixForm@trimZero, MatrixForm@goalDiamond} // 
 TableForm[{#}, 
   TableHeadings -> { 
     None, {"diamondWithin", "trimZero", "goalDiamond"}}, 
   TableAlignments -> Center] &

Mathematica graphics


One-liner

DiamondMatrix[{4, 5}, {9, 10}] //.
{0 :> Sequence[], {} :> Sequence[]} /.
{x__, x__} :> {x} // MatrixForm

A note about DiamondMatrix

I found the documentation of this function very vague. The only useful thing I could find was the last example where the function was used like so: DiamondMatrix[{a, b}, {c, d}]. After playing around with changing the values of these variables, it seems to me that changing a and b will affect the height and width (in that order) of the inner diamond, while changing c and d will change the height and width of the entire matrix that contains the diamond.

I'd built a Manipulate to experiment with using the function to create the desired matrix. Note that an odd-width/height matrix will contain only odd-width/height diamond (try it out and you'll see). In this case, the double diamond has a width of 10 (even) and height of 9 (odd). Compare these dimensions to just 5 and 9 in the original diamond.

Therefore, I will choose a large matrix with odd height and even width, say 17 x 14, by changing c and d. I then changed a and b to get the desired dimension of the inner double diamond (9 x 10; note that 9 and 17 are both odd, while 10 and 14 both even).

After that you can choose to resize the overall matrix down to a smaller size by lowering c and d (but it really doesn't matter since post-processing will remove anything surrounding the diamond anyway).

Lastly, note that previous answers that involved DiamondMatrix did not generate truly "ragged" diamonds, but rather 1, 3, 5, and so on, diamonds.

Manipulate[Module[{m, displaym, diamond, mh, mw, dh, dw},
  m = DiamondMatrix[{a, b}, {c, d}];
  displaym = 
   m /. {1 :> Style[1, Red], 0 :> Style[0, Lighter[Gray, 0.7]]};
  diamond = DeleteCases[m, 0, {2}] // DeleteCases[#, {}, {1}] &;
  {mh, mw} = Dimensions@m;
  {dh, dw} = {Length@diamond, Max[Length /@ diamond]};

  (* Evaluate mExtract in another cell after you're done manipulating to get the matrix*)
  mExtract = m;

  (* Display *)
  {{Style[
      "DiamondMatrix[" <> ToString@{a, b} <> ", " <> ToString@{c, d} <>
        "]", Blue], SpanFromLeft},
    {Style["Diamond:", Red], 
     Grid@Transpose@{Style[#, Red] & /@ {"Height", "Width"}, 
        Style[#, Red] & /@ {dh, dw}}, "Matrix:", 
     Grid@Transpose@{{"Height", "Width"}, {mh, mw}}},
    {MatrixForm@displaym, SpanFromLeft}} // 
   Grid[#, Frame -> All, Spacings -> {1, 1}, 
     Dividers -> {{2 -> False, 4 -> False}, Automatic}] &],

 {{a, 5}, 1, 10, 1}, {{b, 5}, 1, 10, 1}, {{c, 10}, 1, 20, 1}, {{d, 10}, 1, 20, 1}]

Mathematica graphics


Another way to use DiamondMatrix

The diamond matrices in @Szabolcs and @paw's answers generate 1,3,5-diamonds and not 1,2,3-diamond like you wanted. However, a little modification of that matrix will generate the desired diamond.

This is done by observing that a row in a 1,3,5-diamond (let's say the row of length 5) differs from the corresponding row in a 1,2,3-diamond (that means the row of length 3) by half of Length[row in 1,3,5-diamond] - 1. In other words, 1 + 2 = 3, but 1 + 2(2) = 5.

diamond135 = DeleteCases[DiamondMatrix[4], 0, {2}];
diamond135 // MatrixForm

Mathematica graphics

diamond123 = diamond135 /. x : {1 ..} :> ConstantArray[1, Length@x - (Length@x - 1)/2];
diamond123 // MatrixForm

Mathematica graphics


One-liner

DiamondMatrix[4] /. {0 :> Sequence[]} /.
  x : {1 ..} :> ConstantArray[1, Length@x - (Length@x - 1)/2] // MatrixForm
share|improve this answer
    
Thank you very much. It's not only fun playing with but also instructive :) –  eldo Aug 11 at 15:42
    
Thanks! Glad you liked it. I added to my answer another way of using DiamondMatrix. –  seismatica Aug 11 at 20:23

Defining a helper function for tidiness:

diamondcounts[n_] := Range[n] ~Join~ Range[n - 1, 1, -1]

You could use ConstantArray and Map

ConstantArray[1, #] & /@ diamondcounts[n]

But personally I think Table is a rather nice choice here:

Table[1, {i, diamondcounts[n]}, {i}]
share|improve this answer
    
I like Table[1, {i, diamondcounts[n]}, {i}]. But why does it function? The i is nowhere defined, is it? –  eldo Aug 10 at 21:05
1  
@eldo, i is just the iterator variable. In the outer loop it acquires values from diamondcounts[n] and then the inner loop runs i times. –  Simon Woods Aug 11 at 8:48

Using ArrayPad to reflect a pyramid matrix:

diamond[n_] := ArrayPad[ConstantArray[1, #] & /@ Range[n], {{0, n - 1}}, "Reflected"]
diamond[5] // MatrixForm

matrix

share|improve this answer
    
+1 Clever use of ArrayPad –  Simon Woods Aug 10 at 20:17

Here are two different methods based on Array:

diamond[n_] := With[{a = ConstantArray[1, #] &}, Array[a, n]~ Join ~Reverse@Array[a, n - 1]]

OR

diamond[n_]:= Array[Array[1 &, #] &, {n}] ~ Join ~ Reverse[Array[Array[1 &, #] &, {n-1}]]

diamond[5] // MatrixForm

Mathematica graphics

share|improve this answer
    
I get with diamond[n_] := Array[ConstantArray[1, #] &, n]~Join~ Reverse@Array[ConstantArray[1, #] &, n - 1] an error message: "SetDelayed::write: Tag Function in ((ConstantArray[1,#1]&)/@Join[Range[t],{#1+1},Reverse[Range[#1]]]&)[n_] is Protected." –  eldo Aug 10 at 21:19
    
@eldo, I don't know why you would get that. It works fine for me. Maybe start a new kernel. –  RunnyKine Aug 10 at 21:21
    
Thanks, now it works. A little bit strange though, because before my first attempt I executed Clear["Global*"]` –  eldo Aug 10 at 21:27
    
@eldo. Good, glad it works. –  RunnyKine Aug 10 at 21:27
    
Since I would like to accept this answer please reformulate: diamond[n_] := With[{a = ConstantArray[1, #] &}, Array[a, n]~Join~Reverse@Array[a, n - 1]] –  eldo Aug 10 at 21:43

Here is a FoldList approach:

diamond[n_] := Rest@FoldList[ConstantArray[1, #2] &, 0, Range[n]~Join~Range[n - 1, 1, -1]]

Then:

diamond[6] // MatrixForm

Mathematica graphics

share|improve this answer
diamond[n_] := 1 & /@ Range[#] & /@ (Range[n]~Join~Reverse@Range[n - 1]);

or

diamond[n_] := Array[1 &, n - Abs[#]] & /@ Range[1 - n, n - 1];

diamond[10]//MatrixForm

enter image description here

share|improve this answer

Investigating your answers I found some more possibilities:

A helper function

PeekRange[n_] := With[{r = Range @ n}, r ~ Join ~ Reverse @ Most @ r]

Partition:

diamond1[n_] := Partition[ConstantArray[1, n], n, 1, {-1, 1}, {}]

ListConvolve:

diamond2[n_] := ConstantArray @@@ ListConvolve[{1}, PeekRange @ n, 1, 0, List]

ArrayReshape:

diamond3[n_] := Map[Flatten[ArrayReshape[ConstantArray[1, n], {#, 1}]] &, PeekRange @ n]

ReplaceList:

diamond4[n_] := 
 Map[First, #]~Join~Rest@Map[Last, #] &[
  ReplaceList[ConstantArray[1, n + 1], {x__, y__} :> {{x}, {y}}]]

All give with n = 5

enter image description here

share|improve this answer
    
@Öska Thanks, will remember to give links in the future :) –  eldo Aug 11 at 15:47
    
It's just a good thing to give links while enumerating the functions IMO :) –  Öskå Aug 11 at 15:49

Many ways possible

diamond = Function[ConstantArray[1, #] & /@ Join[Range@t, {# + 1}, Reverse@Range@#] // MatrixForm]
diamond@5

more or less complicate, with SparseArray

diamond = 
 Function[SparseArray[{i_, j_} /; i >= j -> 1, {#, #}]~Join~
      Reverse@SparseArray[{i_, j_} /; i >= j -> 1, {#, #}] // Normal //
     ReplaceAll[#, 0 -> Sequence[]] & // 
   Column[#, Alignment -> Center] &]

diamond@5

or just pure "1"

diamond = 
 Function[Array[Row@Array[" 1 " &, #] &, {# + 1}]~Join~
    Reverse@Array[Row@Array[" 1 " &, #] &, {#}] // 
   Column[#, Alignment -> Center] &]
diamond@5

without function

a = Array[1 &, #] &;
Array[a, {6}]~Join~ Reverse@Array[a, {5}] // MatrixForm
Array[a, {6}]~Join~ Reverse@Array[a, {5}] // 
 Column[#, Alignment -> Center] &

or a squareDiamond (did it also)

DiamondMatrix@10 /. (0 -> Sequence[]) // MatrixForm

and more and more ...

diamondMatrix

share|improve this answer
foo = Composition[Sign, Range, Range];
bar = Composition[Reverse, Most, foo];
dmnd0 = Join @@ Through[{foo, bar}[#]] &;

dmnd1 = With[{m = Unitize @ Range[Range[#]]}, Join @@ {m, Reverse @ Most @ m}] &
(* or Sign instead of Unitize *)

dmnd2 = With[{r = Join[Range[0, #-1], Range[#-2, 0, -1]]}, ArrayPad[{1}, {0, #}, 1]& /@ r] &

dmnd3 = Join @@ {#, Reverse[Most@#]} &@NestList[Append[#1, 1] &, {1}, # - 1] &

dmnd4 = Join @@{Reverse[Rest@#], #} &@ NestList[Drop[#, 1] &, Array[1 &, {#}], # - 1] &

dmnd0[5] //MatrixForm

enter image description here

dmnd0[5] == dmnd1[5] == dmnd2[5] == dmnd3[5] == dmnd4[5]
(* True *)
share|improve this answer

How about

DeleteCases[#, 0] & /@ DiamondMatrix[10]

it's about 3 times as fast then what Öska suggested.

share|improve this answer

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.