Re: working with lists
- To: mathgroup at smc.vnet.net
- Subject: [mg113214] Re: working with lists
- From: Leonid Shifrin <lshifr at gmail.com>
- Date: Tue, 19 Oct 2010 05:54:48 -0400 (EDT)
- References: <201010180947.FAA00936@smc.vnet.net>
Sam, The following seems to solve your problem. You did not specify whether subtractions must accumulate - I assumed this is so. In[1]:= Clear[f]; f[x_List] := Module[{subtr = 0}, Map[If[Mod[# - subtr, 3] == 0, 2 (# - subtr++), # - subtr] &, x]] In[3]:= tst = {1, 2, 3, 5, 7} Out[3]= {1, 2, 3, 5, 7} In[4]:= f[tst] Out[4]= {1, 2, 6, 4, 12} Generally, this sort of problems are hard to immediately translate into purely functional Mathematica code, since the next elements depend on the previous ones, but non-locally - the entire list after certain element gets modified. Here is another (procedural) implementation: In[5]:= Clear[ff]; ff[x_List] := Module[{i = 1, xl = x}, For[i = 1, i <= Length[xl], i++, If[Mod[xl[[i]], 3] == 0, xl[[i]] *= 2; xl[[i + 1 ;;]] -= 1]]; xl] In[7]:= ff[tst] Out[7]= {1, 2, 6, 4, 12} It can be compiled for speed: fff = Compile[{{x, _Integer, 1}}, Module[{i = 1, xl = x}, For[i = 1, i <= Length[xl], i++, If[Mod[xl[[i]], 3] == 0, xl[[i]] *= 2; xl[[i + 1 ;; Length[xl]]] -= 1]]; xl]]; In[9]:= fff[tst] Out[9]= {1, 2, 6, 4, 12} The first version can be compiled as well: ffff = Compile[{{x, _Integer, 1}}, Module[{subtr = 0}, Map[If[Mod[# - subtr, 3] == 0, 2 (# - subtr++), # - subtr] &, x]]] In[11]:= ffff[tst] Out[11]= {1, 2, 6, 4, 12} It is interesting to compare speed on larger lists: In[14]:= ltst = RandomInteger[{1, 10000}, 10000]; In[23]:= (res1 = f[ltst]); // Timing Out[23]= {0.521, Null} In[25]:= (res2 = ff[ltst]); // Timing Out[25]= {1.752, Null} In[26]:= (res3 = fff[ltst]); // Timing Out[26]= {0.762, Null} In[27]:= (res4 = ffff[ltst]); // Timing Out[27]= {0.02, Null} In[28]:= res1 == res2 == res3 == res4 Out[28]= True This shows that in this particular case, Map with procedural code embedding is both superior in uncompiled form and helped much more by using Compile. You could change Map to For loop with the same effect - what matters here is that by using an accumulator variable we dramatically reduce the number of operations, as compared to the version where entire list gets modified each time. This shows once again, that for problems like this, procedural paradigm serves you better (a rare case in Mathematica). Hope this helps. Regards, Leonid On Mon, Oct 18, 2010 at 2:47 AM, Sam Takoy <sam.takoy at yahoo.com> wrote: > Hi, > > I'm not very good at working with lists. May I ask for someone to work > out an example which has several elements of what I need to do. > > What's the best way to write a function f[list] that goes through each > element of the lest, doubles each element divisible by three and reduces > each of the following elements by 1. That is > > > f[{ 1 2 3 5 7}] is { 1 2 6 4 12 } > > Many thanks in advance, > > Sam > >
- References:
- working with lists
- From: Sam Takoy <sam.takoy@yahoo.com>
- working with lists