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.

I'm trying to do this:

i1 = 1;
i2 = 1;

RandomChoice[{
  (i1 = i1 + 1),
  (i1 = i1 - 1),
  (i2 = i1 + 1),
  (i2 = i2 - 1)}]

In order to chose randomly which variable is going to be incremented or decremented - but it's not working. I've also tried with -- and ++ but I had the same problem. I am clueless about what may be the problem.

share|improve this question

8 Answers 8

May be the most compact approach:

Hold[i1++, i1--, i2++, i2--][[RandomInteger[{1, 4}]]]
share|improve this answer

I'd do :

choices = {{-1, 0}, {0, -1}, {0, 1}, {1, 0}};
{i1, i1} = {i1, i2} + RandomChoice[choices]
share|improve this answer

Putting Increment or Decrement in third argument of Extract:

Extract[expr, list, h]

extracts parts of expr, wrapping each of them with head h before evaluation.

{i1, i2} = {1,1};
vars = Hold[i1, i2];

Extract[
  vars
  , RandomInteger[{1, Length@vars}]
  , RandomChoice[{Increment, Decrement}]];
share|improve this answer
2  
+1, that is particularly clever. –  rcollyer Sep 12 '13 at 17:06

The problem is that the expressions inside RandomChoice[list] are evaluated before one of the elements in the list is picked. You can use the functions Hold and ReleaseHold to force the evaluation of the elements in the list to occur after the random choice like this:

ReleaseHold@RandomChoice[{Hold[i1++], Hold[i1--], Hold[i2++], Hold[i2--]}];
share|improve this answer

There are already many great answers here. Most of then work by holding various things unevaluated. I'd like to propose an alternative of sorts.

If we use indexed Symbols we can avoid unwanted premature evaluation without Hold or similar. Working with lists of "keys" is far easier than working with lists of assigned Symbols.

i[1] = 1;
i[2] = 1;

i[#@{1, 2}] += #@{-1, 1} & @ RandomChoice

That's two calls to RandomChoice, compressed with Function, one for the list of keys and one for the list of addends. Generalized:

roff[s_, keys_, os_, f_: RandomChoice] := s[f@keys] += f@os

Now:

i[_] = 1;

Do[
 roff[i, {"a", "b", "c"}, {-7, -3, 2, 4, 6}],
 {50}
]

i /@ {"a", "b", "c"}
{-7, 9, -3}

Note that you could use any other sampling function besides RandomChoice.

Or taking it in a different direction:

sampleApply[s_, keys_, fns_, R_: RandomChoice] := R[fns] @ s[R@keys]

j[_] = 0;

Do[
 sampleApply[j, Range@5, {Increment, Decrement}],
 {100}
]

Array[j, 5]
{3, -4, 2, 1, -6}

I hope these examples illustrate the flexibility and convenience of this approach.

share|improve this answer
1  
Avoiding Hold induced headache is always good +1 –  ssch Sep 12 '13 at 18:53

Switch[RandomInteger[3], 0,++i1, 1,--i1, 2,++i2, _,--i2]

share|improve this answer

This is a more general approach, already made to a function: holdRandomChoice chooses randomly one of the listed commands without any of the others being evaluated:

SetAttributes[holdRandomChoice, HoldAll];
holdRandomChoice[list__] := Module[{x = Unevaluated@list},
   Part[x, RandomInteger@{1, Length@x}]];

Clear[i];
holdRandomChoice[Print[i = 1], Print[i = 2], Print[i = 3]]
i
During evaluation of In[1]:= 2

Out[4]= 2

Note that none of the other commands got printed.

share|improve this answer
    
FYI: you don't need Unevaluated or Module here; it would be a bit cleaner to use: Part[#, RandomInteger@{1, Length@#}] & @ Hold[list] –  Mr.Wizard Sep 12 '13 at 19:44
2  
Actually, I would just write: holdRandomChoice[list__] := ReleaseHold @ RandomChoice @ Thread @ Hold @ {list} –  Mr.Wizard Sep 12 '13 at 19:46

a variation on tom's answer:

ReleaseHold@RandomChoice[{
     Hold[i1 += RandomChoice[{-1,1}]],
     Hold[i2 += RandomChoice[{-1,1}]] }]

which may be useful since it can be generalised, eg.:

ReleaseHold@RandomChoice[{
     Hold[i1 += RandomVariate[NormalDistribution[0, 3]]],
     Hold[i2 += RandomVariate[NormalDistribution[0, 3]]]}]
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.