# Decreasing specific elements in a matrix [closed]

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, p]

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

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"

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;
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 &]


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]