Re: For Loop and Array related

*To*: mathgroup at smc.vnet.net*Subject*: [mg58031] Re: For Loop and Array related*From*: Maxim <ab_def at prontomail.com>*Date*: Thu, 16 Jun 2005 05:37:59 -0400 (EDT)*References*: <d8oucl$t6q$1@smc.vnet.net>*Sender*: owner-wri-mathgroup at wolfram.com

On Wed, 15 Jun 2005 10:03:01 +0000 (UTC), mchangun at gmail.com <mchangun at gmail.com> wrote: > Hi All, > > I have an array with 100 elements, all set to zero initially. Then I > want to randomly choose one element and increase its value by one, and > repeat this 16000 times. Here is my code: > > Lattice = Table[0, {n, 100}]; > For[i = 1, i = 16000, i++, Lattice[[Random[Integer, {1, 100}]]]++] > > So now if I add all the elements in the list Lattice together, I should > get 16000 (I use Total[Lattice] to get the sum of the list). But this > doesn't happen, and strangely, each time I run this, the sum of the > list is different! What am I doing wrong? > > Also I'm aware that a lot of Mathematica newbies try and write code > like it were C++ and I think i've fallen into this trap as well. So is > there a different (more Mathematica) way which I can implement the > above? > > Thanks in advanced. > Increment[x] internally evaluates x = x + 1 (and returns the old value of x then). Therefore, L[[Random[...]]]++ becomes L[[Random[...]]] = L[[Random[...]]] + 1, where Random is evaluated twice and gives two different indices. Perhaps it would be better if Increment, AddTo and other assignment functions evaluated the arguments of the left-hand side once; that is, in pos=1;L[[pos++]]++ the argument pos++ should be evaluated once and then the expression should be transformed into L[[1]] = L[[1]] + 1. This way we get the desired behaviour: pos now has the value 2 and the first element of L is incremented. Otherwise Increment just confuses the programmer into thinking that it will work like in C. This still wouldn't get rid of side effects, though, as x = x + 1 still evaluates x on the right-hand side of Set. Your example can be rewritten as Lattice[[#]]++& /@ Table[Random[Integer, {1, 100}], {16000}] For further speed-up, this can be compiled: Lattice = Compile[{}, Module[{Lattice}, Lattice = Table[0, {100}]; Lattice[[#]]++& /@ Table[Random[Integer, {1, 100}], {16000}]; Lattice ]][]; Sow and Reap give comparable performance: Lattice = Last@ Reap[ Sow[0, Range@ 100]; Sow[0, Table[Random[Integer, {1, 100}], {16000}]], _, Length@ #2 - 1&]; If the number of tries is much larger than 16000, then the compiled version takes several times less memory than uncompiled, most likely due to the use of packed arrays. Maxim Rytin m.r at inbox.ru