2
$\begingroup$

Let

a = {{2, 2}, {2, 2}};

Why does

(--(a[[#]])) & @@@ {{1, 2}, {2, 1}}

give

{{1, 1}, {1, 1}}

I expected

{{2, 1}, {1, 2}}

Let

p = {2, 1};

Is there any easier way to decrease matrix elements; for example, the second in the first row and the first in the second row?

That is, I would like a function

F[a, p]

which gives

{{2, 1}, {1, 2}}

Is there an easier and faster way to do this than the below:

(--(a[[#]])) & @@@ Transpose[{Range[2], p]
$\endgroup$

closed as off-topic by ciao, m_goldberg, MarcoB, Young, Hector Aug 21 '16 at 19:28

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "This question arises due to a simple mistake such as a trivial syntax error, incorrect capitalization, spelling mistake, or other typographical error and is unlikely to help any future visitors, or else it is easily found in the documentation." – ciao, m_goldberg, MarcoB, Young, Hector
If this question can be reworded to fit the rules in the help center, please edit the question.

  • $\begingroup$ Use ##, not #... also, avoid using uppercase initials for your symbols, else you risk clashing with built-ins... $\endgroup$ – ciao Aug 20 '16 at 23:38
4
$\begingroup$

Here is one way to do it:

With[
 {
  a = {{2, 2}, {2, 2}},
  f = Subtract[#, 1] &,
  p = {{1, 2}, {2, 1}}
 },
 MapAt[f, a, p]
 ]

MapAt responds to your specific request of, "for example the second in the first row and the first in the second row? That is a function"

$\endgroup$
2
$\begingroup$

As I understand, you would like to modify a matrix in-place.

SetAttributes[decrease, HoldFirst];

decrease[m_?MatrixQ, pos__List] :=
 Do[m[[Sequence @@ p]]--, {p, {pos}}]

Example:

SeedRandom[1];
test = RandomInteger[{1, 5}, {5, 3}]

{{5, 3, 5}, {1, 2, 1}, {1, 3, 1}, {1, 4, 3}, {1, 4, 5}}

Let's decrease second row all together, first element in third row, second and third in fourth and last in last:

decrease[test, {2}, {3, 1}, {4, {2, 3}}, {-1, -1}];

test

{{5, 3, 5}, {0, 1, 0}, {0, 3, 1}, {1, 3, 2}, {1, 4, 4}}


Edit: Incorporating a feature of a general modifying function.

SetAttributes[modifier, HoldFirst];

modifier[m_?MatrixQ, pos__List, f_Function: (# - 1 &)] :=
 Do[Set[
   m[[Sequence @@ p]], f@m[[Sequence @@ p]]], {p, {pos}}]

Leave out the optional function and the specified elements will be decreased by one, or specify the modifying operation, for example:

modifier[test, {2}, {3, 1}, 10 # - 2 &]
$\endgroup$
1
$\begingroup$

To see what is wrong with your code, you can use Trace which shows that the '--' decrement happens before the [[ ]] look up. I couldn't find a simple way of adapting your code, but I would aim to use something simpler.

I like to work in terms of matrices, and SparseArray gives you an convenient way to construct the required matrix. If you need to update your matrix a this is one way to do it.

a = {{2, 2}, {2, 2}};
p = {{1, 2}, {2, 1}};
a -= SparseArray[p -> 1]
$\endgroup$

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