1
$\begingroup$

I have a list expr of symbols.

Clear["Global`*"]; $Version (* 14.1.0 for Mac OS X ARM (64-bit) (July 16, 2024) *) expr = {a,d,c,b,f,c,a,X,X,a,b,b,X,b,f,c,b,d,a,f,X,d,d,c,X,X,f,f,c,f}; 

I want to move all X's to the right. This goal can be achieved by

wanted = Join[DeleteCases[expr, X], Cases[expr, X]] (* {a,d,c,b,f,c,a,a,b,b,b,f,c,b,d,a,f,d,d,c,f,f,c,f,X,X,X,X,X,X} *) 

But I want a rule-based solution using ReplaceRepeated[] because this is suitable for my ultimate goal. I tried

rule = {{p___, X, q_, r___} :> {p, q, X, r}}; expr2 = expr //. rule (* {a,d,c,b,f,c,a,X,X,a,b,b,X,b,f,c,b,d,a,f,X,d,d,c,X,X,f,f,c,f} *) 

My question is: Why ReplaceRepeated[] stopped there? Am I doing something wrong?

$\endgroup$
9
  • $\begingroup$ I'm on the road, but my first guess is that when q matches X, the replacement results in the same expression. Would that cause it to stop? $\endgroup$ Commented Oct 14, 2024 at 1:57
  • $\begingroup$ @MichaelE2 I see now. Got it thanks! Should I post a solution myself? $\endgroup$ Commented Oct 14, 2024 at 2:04
  • 1
    $\begingroup$ @MichaelE2 I found a workaround, but cannot find no satisfactory answer to my question itself... $\endgroup$ Commented Oct 14, 2024 at 2:36
  • 1
    $\begingroup$ Does this help with finding an explanation: {a, X, c, d, X, b, X} //. {{p___, X, q_, r___} :> (Print[{"q" -> q, #}]; #) &@{p, q, X, r}}? It prints the replacement for each match. lericr has already explained the point in my comment. $\endgroup$ Commented Oct 14, 2024 at 12:52
  • 1
    $\begingroup$ If you make your rule {{p___, X, q : Except[X], r___} :> {p, q, X, r}} or {{p___, X, r__} :> {p, r, X}}, it will work. $\endgroup$ Commented Oct 14, 2024 at 15:13

1 Answer 1

1
$\begingroup$

ReplaceRepeated stops evaluating when the expression no longer changes. When it encounters two X adjacent to each other, the rule moves the first X to just after the subsequent X, but at that point, the expression is indistinguishable from what it was previously. So, ReplaceRepeated stops.

$\endgroup$
5
  • $\begingroup$ ReplaceList[expr2, rule] returns several different results. Does ReplaceRepeated give up applying rules after just one invariant case although there are non-invariant cases? $\endgroup$ Commented Oct 14, 2024 at 5:14
  • 1
    $\begingroup$ @A.Kato Yes, I pretty sure it stops at the first match. ReplaceRepeated doesn't care if the replacement results in no effective change. $\endgroup$ Commented Oct 14, 2024 at 12:31
  • $\begingroup$ Thank you for clear explanation. FullSimplify[] tries wider range of transformation than Simplify[]. In the same way, I had assumed ReplaceRepeated[] tries all possible matching pattern which is avalable by ReplaceList[]. I learned from your answer and from others's comments that ReplaceRepeated[] try to round things up as quickly as possible instead of aiming for perfection :-) Probably this is a tip to avoid the danger of getting stuck in an infinite loop. $\endgroup$ Commented Oct 15, 2024 at 5:41
  • 1
    $\begingroup$ @A.Kato For fun, one way to do what you imagined ReplaceRepeated worked: {a, d, c, b, f, c, a, X, X, a, b, b, X, b, f, c, b, d, a, f, X, d, d, c, X, X, f, f, c, f} //. whole_ :> Last@DeleteDuplicates[Prepend[ReplaceList[whole, {{p___, X, q_, r___} :> ({p, q, X, r})}], whole]] $\endgroup$ Commented Oct 15, 2024 at 14:08
  • $\begingroup$ @MichaelE2 Thank you so much. This is indeed "Full" or "Try Hard" version of "ReplaceRepeated". $\endgroup$ Commented Oct 16, 2024 at 0:10

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.