Re: exchanging 2 elements in a list (problem with Block)
- To: mathgroup at smc.vnet.net
- Subject: [mg27631] Re: exchanging 2 elements in a list (problem with Block)
- From: "Allan Hayes" <hay at haystack.demon.co.uk>
- Date: Fri, 9 Mar 2001 02:35:45 -0500 (EST)
- References: <98505m$5h0@smc.vnet.net> <98722r$8rs@smc.vnet.net>
- Sender: owner-wri-mathgroup at wolfram.com
Richard Fateman has pointed a bug out to me in my previous posting -- Block in Swap1[m_,i_,j_]:= Block[{s=m}, s[[{i,j}]]= s[[{j,i}]];s ] causes Swap1[{a,s},1,2]; $RecursionLimit::reclim: Recursion depth of 256 exceeded. Replacing Block with Module corrects this. *** However this example does point up a general problem with Block *** -- Allan --------------------- Allan Hayes Mathematica Training and Consulting Leicester UK www.haystack.demon.co.uk hay at haystack.demon.co.uk Voice: +44 (0)116 271 4198 Fax: +44 (0)870 164 0565 "Allan Hayes" <hay at haystack.demon.co.uk> wrote in message news:98722r$8rs at smc.vnet.net... > > Richard Fateman > > Richard, > Two ways: > > Swap1[m_,i_,j_]:= > Block[{s=m}, > s[[{i,j}]]= s[[{j,i}]];s > ] > > Swap1[{a,b,c,d,e,f},2,4] > > {a,d,c,b,e,f} > > Swap2[m_,i_,j_]:= > ReplacePart[m,m,{{i},{j}},{{j},{i}}] > > Swap2[{a,b,c,d,e,f},2,4] > > {a,d,c,b,e,f} > > For swapping columns we have (besides double Transpose versions of the > above): > > m= {{a,b,c,d},{e,f,g,h}}; > > m[[All,{2,4}]]= m[[All,{4,2}]];m > > {{a,d,c,b},{e,h,g,f}} > > Next, I look at the first three of your examples. > > 1 --------------------------------------------------------------------- > > Clear["`*"] > > Exchangeitems1[m_, r_Integer, s_Integer] := > Block[{temp = m[[r]]}, > m[[r]] = m[[s]]; > m[[s]] = temp; > m > > ]; > > Exchangeitems1[{a,b,c,d,e,f},2,4] > > Set::setps:{a,b,c,d,e,f} in assignment of part is not a symbol. > > Set::setps:{a,b,c,d,e,f} in assignment of part is not a symbol. > > {a, b, c, d, e, f} > > > Analysis > > Crucial here is that {a,b,c,d,e,f} is passed directly to m, so we get, for > example > {a,b,c,d,e,f} [[r]]={a,b,c,d,e,f} [[s]] > > However settings like > > mm[[3]] = p > > works only when mm is a *symbol* that has been assigned a value by Set, not > SetDelayed. For example > > mm= Evaluate[{1,2,3,4}]; > > and, of course this value must have a position with index 3. > > Further, when these conditions hold, it is the stored value of mm that is > changed: a new mm is not constructed -- this more efficient. > > 2 -------------------------------------------------------- > > Clear["`*"] > > Exchangeitems2[m_,r_Integer,s_Integer]:= > Block[{temp}, > temp=m[[r]]; > m=ReplacePart[m,m[[s]],{r}]; > m=ReplacePart[m,temp,{s}]; > m > ]; > > Exchangeitems2[{a,b,c,d,e,f},2,4] > > {a,d,c,d,e,f} > > > Analysis: > > The replacement of m by {a,b,c,d,e,f} is a crucial here also: > First we get > > temp = {a,b,c,d,e,f}[[2]] > > that becomes > > temp = b, which is stored (actually as a replacement rule) > > > Then we get > > {a,b,c,d,e,f}= ReplacePart[{a,b,c,d,e,f},{a,b,c,d,e,f}[[4]],{2}] > > that becomes > > {a,b,c,d,e,f}= {a,d,c,d,e,f} > > This results in the following being stored > a=a, b=d, c=c, d=d, e=e, f =f . > Here > b=d > is the important one if course. > So, when the next line is evaluted we begin with > > {a,b,c,d,e,f}= ReplacePart[{a,b,c,d,e,f},temp,{2}] > > Which becomes successively (temp has already been defined as b, *and > a,b....on the left side are not evaluated*) > > {a,b,c,d,e,f}= ReplacePart[{a,d,c,d,e,f},temp,{2}] > {a,b,c,d,e,f}= ReplacePart[{a,d,c,d,e,f},b,{2}] > {a,b,c,d,e,f}= ReplacePart[{a,d,c,d,e,f},d,{2}] > {a,b,c,d,e,f}= {a,d,c,d,e,f} > > This does not change the rules stored. > > Finally we evaluated {a,b,c,d,e,f} with b =d in store. > This gives > {a,d,c,d,e,f} > > ** And b = d is still around > > b > > d > > **Actually, worse could happen > > Exchangeitems2[{1,2,3,4,5,6},2,4] > > Set::setraw: Cannot assign to raw object 1. > > Set::setraw: Cannot assign to raw object 2. > > Set::setraw: Cannot assign to raw object 3. > > General::stop: Further output of Set::setraw will be suppressed > during this \ > calculation. > > {1,2,3,4,5,6} > > 3 ------------------------------------------------------------- > > I have interchanged k and m in the following to conform to the previous two > definitions > > Clear["`*"] > Exchangeitems[m_,r_Integer,s_Integer]:=Block[{k,temp},k=m; > temp=k[[r]]; > k=ReplacePart[k,k[[s]],{r}]; > k=ReplacePart[k,temp,{s}]; > k]; > > Exchangeitems[{a,b,c,d,e,f},2,4] > > {a,d,c,b,e,f} > > Analysis > > The variable k is not useless, it is what makes this work. > We get > k = {a,b,c,d,e,f} , which is stored > temp = b is stored > Then, the symbol k is redefined by > k = ReplacePart[{a,b,c,d,e,f} ,{a,b,c,d,e,f} [[4]],{2}] > which becomes > k = {a,d,c,d,e,f}, which is stored > Then > k=ReplacePart[{a,d,c,d,e,f},b,{4}] > which becomes > k={a,d,c,b,e,f}, which is stored > Finally k evauates to {a,d,c,b,e,f} > > -- > Allan > --------------------- > Allan Hayes > Mathematica Training and Consulting > Leicester UK > www.haystack.demon.co.uk > hay at haystack.demon.co.uk > Voice: +44 (0)116 271 4198 > Fax: +44 (0)870 164 0565 > > "Richard Fateman" <fateman at cs.berkeley.edu> wrote in message > news:98505m$5h0 at smc.vnet.net... > > > > Actually, I wanted to exchange 2 rows in a matrix, > > but writing this program I found I could not even > > exchange 2 elements in a simple list by the first > > two (most obvious) programs I wrote. The third > > works. So does the fourth. > > > > Anyone care to explain why the first 2 fail? > > (Typing them in to a system does not really explain > > that much.) > > > > try Exchangitems[{a,b,c,d,e,f},2,4] which should > > result in {a,d,c,b,e,f}. > > Naturally it should not SET any of the variables > > a,b,c,... . version 2 sets b to the value d. > > > > > > Exchangeitems1[m_,r_Integer,s_Integer]:= > > Block[{temp=m[[r]]}, > > m[[r]]=m[[s]]; > > m[[s]]=temp; > > m]; > > > > > > Exchangeitems2[m_,r_Integer,s_Integer]:= > > Block[{temp}, > > temp=m[[r]]; > > m=ReplacePart[m,m[[s]],{r}]; > > m=ReplacePart[m,temp,{s}]; > > m]; > > > > > > (* this works by adding a useless variable *) > > Exchangeitems[k_,r_Integer,s_Integer]:= > > Block[{m,temp}, > > m=k; > > temp=m[[r]]; > > m=ReplacePart[m,m[[s]],{r}]; > > m=ReplacePart[m,temp,{s}]; > > m]; > > > > (*Here is a more "functional" version *) > > > > ei[k_, low_, hi_]:= ei[k,hi,low] /; low>hi; > > ei[k_, low_, hi_]:= k /; low==hi; > > ei[k_, low_, hi_] := > > Flatten[{Take[k, {1, low - 1}], {k[[hi]]}, > > Take[k, {low + 1, hi - 1}], {k[[low]]}, Drop[k, hi]}, 1]; > > > > (*and here is an APL-style version*) > > > > > > ei2[k_,r_,s_]:=Table[Switch[j,r,k[[s]], > > s,k[[r]], > > _,k[[j]]], > > {j,1,Length[k]}]; > > > > > > > > Is there a nice, efficient, (and correct) program to do this? > > > > > > Perhaps there is a better way to do this > > > > >