Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set::setps: in the part assignment is not a symbol. >>

I'm defining a function in Mathematica where if the i-th value in a list in 1, and the i+1-th value is 0, the function switches those two values.

I've defined it as:

f[i_, x_] := (If[x[[i]] == 1 && x[[i + 1]] == 0, x[[i]] = 1; x[[i + 1]] = 0]);

However when I test it with i = 2 and x = {1,1,0,0} I get the following error:

Set::setps: {1,1,0,0} in the part assignment is not a symbol. >>

I don't quite know what I'm doing wrong, as I thought I was calling everything correctly.

like image 863
Mary Avatar asked Oct 13 '12 18:10

Mary


1 Answers

You seem to have found a solution but let's break this down anyway.

First you have a simple transcription error where your Sets apply the original values rather than swapping them. With this change the basic code works:

i = 2;
x = {1, 1, 0, 0};

If[
 x[[i]] == 1 && x[[i + 1]] == 0,
 x[[i]] = 0; x[[i + 1]] = 1;
]

x
{1, 0, 1, 0}

So we have successfully changed x. To make this into a function we must pass the name of x to this code rather than the value of x. This is the source of your error:

{1, 1, 0, 0}[[2]] = 0;

Set::setps: {1,1,0,0} in the part assignment is not a symbol. >>

What you need is a Hold attribute on your function:

SetAttributes[f, HoldAll]

f[i_, x_] := If[x[[i]] == 1 && x[[i + 1]] == 0, x[[i]] = 0; x[[i + 1]] = 1;]

i = 2 ;
x = {1, 1, 0, 0};

f[2, x]

x
{1, 0, 1, 0}

Perhaps you did not intend to change the value of x itself but this technique will surely come in handy in other applications. To modify the function above to manipulate a copy of the data we may use Module, and we don't need the Hold attribute:

f2[i_, xImmutable_] :=
  Module[{x = xImmutable},
    If[x[[i]] == 1 && x[[i + 1]] == 0, x[[i]] = 0; x[[i + 1]] = 1];
    x
  ]

i = 2 ;
x = {1, 1, 0, 0};

f2[2, x]
{1, 0, 1, 0}

Notice that x within Module is a local variable and not your global list x, which remains unchanged.

For fun let's implement this in a different way.

f3[i_, x_] := 
 If[
   x[[i + {0, 1}]] == {1, 0},
   ReplacePart[x, {i -> 0, i + 1 -> 1}],
   x
 ]

f3[2, x]
{1, 0, 1, 0}
like image 123
Mr.Wizard Avatar answered Oct 20 '22 15:10

Mr.Wizard