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.
n = 10;

board = ConstantArray[0, {n, n}];

diag1[x0_, y0_] :=
 Module[{x = x0, y = y0},
  While[{x != 1 || y != 1},
   x--;
   y--
   ];
  While[{x != n + 1 || y != n + 1},
   board[[x, y]]++;
   x++;
   y++
   ]
  ]

I have an n by n matrix of all zeroes. On a given coordinate in the matrix, I need to increase everything in its major diagonal by one. A runchart of this works fine. All that this does, is increase the (x-1,y-1) by one. I believe that the while loops are only executing the statements once, but I can't be sure.

share|improve this question
    
Just edited the title of your question. Please re-edit if I missed your point. –  eldo Jul 11 at 21:39

4 Answers 4

up vote 3 down vote accepted

Your definition uses While incorrectly, in that the first argument should evaluate to True when you want to keep looping. The braces you wrap around the first argument mean that instead of True or False you'll get {True} or {False}. While has to see plain True; anything else is treated like False.

Also, your conditions should be conjunctions, not disjunctions. Here is a working edit:

diag1[x0_, y0_] :=
 Module[{x = x0, y = y0},
  While[x != 1 && y != 1,
   x--;
   y--
   ];
  While[x != n + 1 && y != n + 1,
   board[[x, y]]++;
   x++;
   y++
   ]
  ]

Here's another way that I think is a bit more idiomatic for Mathematica (and which includes some input-checking as well as the state-mutating aspect of your example definition):

ClearAll@diag1;
SetAttributes[diag1, HoldFirst];
diag1[m_Symbol /; MatrixQ@m, r_, c_] /;
  (1 <= r <= #1 && 1 <= c <= #2 & @@ Dimensions@m) :=
 m += SparseArray[Band[{r, c} - Min[r, c] + 1] -> 1, Dimensions@m]

board = ConstantArray[0, {10, 6}];
diag1[board, 8, 2];
diag1[board, 6, 5];
diag1[board, 1, 5];
board // MatrixForm
share|improve this answer
    
Can you please explain why the choice of ands instead of ors? I do not need both conditions to be true, I just want whichever becomes true first. Wouldn't that be an or? Also I tried modifying my statement to your first one and it does not work as intended. Instead I am getting the same issue. –  ibayibay1 Jul 12 at 3:47
    
@ibayibay1 You want && because you want to 'back up' x and y as long as neither x nor y equal 1. As soon as one of them equals 1, you're at a top-left edge and you want to stop the loop. Likewise for the second loop, but for the bottom-right edge. I think your intuition toward || was originally pointing you to the equivalent !(x == 1 || y == 1) (via De Morgan) for the first loop. Re it not working as intended, I've tested it again and it works correctly. If you're still stuck, show me your input (including diag1 definition) and your output. –  billisphere Jul 12 at 18:23
    
I got it working. I was using while instead of While. Simple mistake. Thank you though. –  ibayibay1 Jul 13 at 7:38
    
@ibayibay1 That's alright, I've been bitten by casing bugs when using other languages, too. But, I should definitely offer an apology to you here: I edited while in your original question to While and failed to mention this change to you, as I incorrectly assumed it was just a typo during the question write-up and not a typo from your actual definition (and thus an integral part of the question). Sorry for the oversight. (and from this I learn to be more careful in future edits) –  billisphere Jul 13 at 17:33
    
No problem man. Out of curiosity, why does while have a font change to blue, but While does not? That originally made me think while was correct. –  ibayibay1 Jul 14 at 17:53

Update: Setting only the major diagonal to 1 (original post set both diagonals to 1):

 ClearAll[diagsF2, saF2];
 diagsF2 = Module[{ind = {#, #2}},(Band[ind, Automatic, # {1, 1}] ->1) & /@ {1, -1}] &;
 saF2 = SparseArray[diagsF2[#1, #2], {#3, #4}] &;

 saF2[2, 3, 5, 5] // Normal
 (* {{0,1,0,0,0},{0,0,1,0,0},{0,0,0,1,0},{0,0,0,0,1},{0,0,0,0,0}} *)
 saF2[3, 5, 5, 5] // Normal
 (* {{0,0,1,0,0},{0,0,0,1,0},{0,0,0,0,1},{0,0,0,0,0},{0,0,0,0,0}} *)

 Row[MatrixForm /@ {saF2[2, 3, 5, 5], saF2[3, 5, 5, 5],  saF2[4, 2, 5, 5]}]

enter image description here

board = ConstantArray[0, {10, 6}]; (* @billisphere's example *)
Fold[Composition[Unitize, Plus], board, 
     saF2[##, 10, 6] & @@@ {{8, 2}, {6, 5}, {1, 5}}] // MatrixForm

enter image description here


Original post:

ClearAll[diagsF, saF];
diagsF = Module[{ind = {#, #2}}, (Band[ind, Automatic, #] -> 1) & /@Tuples[{1, -1}, 2]] &;
saF = SparseArray[diagsF[#1, #2], {#3, #4}] &;

saF[2, 3, 5, 5] // Normal
(* {{0,1,0,1,0},{0,0,1,0,0},{0,1,0,1,0},{1,0,0,0,1},{0,0,0,0,0}} *)

saF[1, 5, 5, 5] // Normal
(* {{0,0,0,0,1},{0,0,0,1,0},{0,0,1,0,0},{0,1,0,0,0},{1,0,0,0,0}} *)

Row[MatrixForm /@ {saF[2, 3, 5, 5], saF[1, 5, 5, 5], saF[3, 5, 5, 5]}]

enter image description here

share|improve this answer
    
+1 Another nice example: Normal@saF[6, 1, 11] /. (1) :> Style[1, Red] contrasted with saF[6, 11, 11]. –  eldo Jul 11 at 21:31
    
@eldo, thank you... Highlighting the initial entry may be a good variation too. –  kguler Jul 11 at 21:40
n = 10; 
board = ConstantArray[0, {n, n}]; 
diag1[x0_, y0_] := 
  Module[{x = x0, y = y0, satis}, 
         satis = Select[ Plus[{x, y}, #] & /@ Range[-(n - 1), n - 1], 
                         Max[#] <= n \[And] Min[#] >= 1 &];
         MapAt[# + 1 &, board, satis]]
share|improve this answer

May be something like this also will help:

dig[x_, y_, n_] := SparseArray[{Band[{x, y} - (Min[x, y] - 1)] -> 1}, {n, n}] // MatrixForm

dig[3,2,5]

enter image description here

share|improve this answer
    
This is a near-duplicate of the second part of the answer I provided (~9 hours beforehand). –  billisphere Jul 12 at 18:30
    
@billisphere I just focused on your answer now. yes they are almost similar. –  Algohi Jul 12 at 19:05

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.