Skip to main content

output formatting - How to keep Collect[] result in order?


For example,


Collect[(1 + x + Cos[s] x^2)^3, x]


gives the result


1 + 3 x + 3 x^5 Cos[s]^2 + x^6 Cos[s]^3 + x^2 (3 + 3 Cos[s]) + x^3 (1 + 6 Cos[s]) 
+ x^4 (3 Cos[s] + 3 Cos[s]^2)

Terms of the form $x^n$ are in random order. I would like the result is to be as follows:


 1 + 3 x + x^2 (3 + 3 Cos[s]) + x^3 (1 + 6 Cos[s]) +  
x^4 (3 Cos[s] + 3 Cos[s]^2) + 3 x^5 Cos[s]^2 + x^6 Cos[s]^3




Well, First Thank you very much, Jens! Second, I found there is something wrong with your statement "the HoldForm could be left out". I have tried on my mathematica 8, it turns out that the "HoldForm" is necessary . if "HoldForm" is not there, the order is still random in the output . And I tried to understand this as well as "rule" and "ruledelayed" stuff but can't figure it out. I have tried several input, each confused me. summarized as follows




  1. Replace[cx, List[x__] -> Plus[x]]


    will give


    Sequence[1, 3 x, x^2 (3 + 3 Cos[s]), x^3 (1 + 6 Cos[s]), x^4 (3 Cos[s] + 3 Cos[s]^2), 3 x^5 Cos[s]^2, x^6 Cos[s]^3] 

    But I suppose it should give the Plus result because


    Replace[cx, List[x__] -> jjj[x]]


    gives


    jjj[1, 3 x, x^2 (3 + 3 Cos[s]), x^3 (1 + 6 Cos[s]),  x^4 (3 Cos[s] + 3 Cos[s]^2), 3 x^5 Cos[s]^2, x^6 Cos[s]^3]


  2. Replace[cx, List[x__] -> HoldForm@Plus[x]] gives the right result


    1 + 3 x + x^2 (3 + 3 Cos[s]) + x^3 (1 + 6 Cos[s]) +  x^4 (3 Cos[s] + 3 Cos[s]^2) + 3 x^5 Cos[s]^2 + x^6 Cos[s]^3


  3. Replace[cx, List[x__] :> Plus[x]] gives


    1 + 3 x + 3 x^5 Cos[s]^2 + x^6 Cos[s]^3 + x^2 (3 + 3 Cos[s]) + x^3 (1 + 6 Cos[s]) + x^4 (3 Cos[s] + 3 Cos[s]^2)


    Although it gives the right plus result, the order is wrong.





Answer



Here is an approach that doesn't rely on undocumented features or on low-level box manipulations. We're dealing with a polynomial, so we can simply collect its coefficients and arrange them any way we like as follows:


c0 = Collect[(1 + x + Cos[s] x^2)^3, x];

cx = CoefficientList[c0, x] x^Range[0, Exponent[c0, x]]


(*
==> {1, 3 x, x^2 (3 + 3 Cos[s]), x^3 (1 + 6 Cos[s]),
x^4 (3 Cos[s] + 3 Cos[s]^2), 3 x^5 Cos[s]^2, x^6 Cos[s]^3}
*)

Replace[cx, List[x__] :> HoldForm[Plus[x]]]


$1+3 x+x^2 (3+3 \cos (s))+x^3 (1+6 \cos (s))+x^4 \left(3 \cos (s)+3 \cos ^2(s)\right)+3 x^5 \cos ^2(s)+x^6 \cos ^3(s)$




I've just assembled the desired form of the polynomial by creating a list cx of all terms up to the maximum power Exponent[c0, x], and then turning that list into a sum by means of Replace. Here, the HoldForm was put in so that the output now can be arranged in any alternative order by permuting (or, in particular, reversing) the list cx before doing the Replace:


Replace[Reverse@cx, List[x__] :> HoldForm[Plus[x]]]


$x^6 \cos ^3(s)+3 x^5 \cos ^2(s)+x^4 \left(3 \cos (s)+3 \cos ^2(s)\right)+x^3 (1+6 \cos (s))+x^2 (3+3 \cos (s))+3 x+1$



The output is in held form, so if you apply ReleaseHold to it the order will revert back to the first version. The HoldForm could also be exploited to do further cosmetic changes on the expression, such as putting coefficients before the power of x - but you didn't ask for that.


Edit In response to a follow-up question: the Replace command has RuleDelayed (:>) instead of -> in it because the pattern indicated by x__ has to be fed into the Plus only at the time when there is actually a list of terms present. E.g., if you use List[x__] -> Plus[x] then the right-hand side is immediately evaluated to give you x as the result of Plus[x] (assuming that x hasn't been defined globally). And when you then later encounter the Replace statement it will say to feed the pattern inside List into the right-hand side that now has the form x instead of Plus[x]. That will yield something with the head Sequence corresponding to the sequence of arguments inside the given List.


Comments

Popular posts from this blog

plotting - How to draw lines between specified dots on ListPlot?

I would like to create a plot where I have unconnected dots and some connected. So far, I have figured out how to draw the dots. My code is the following: ListPlot[{{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4,13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full] I have thought using ListLinePlot command, but I don't know how to specify to the command to draw only selected lines between the dots. Do have any suggestions/hints on how to do that? Thank you. Answer One possibility would be to use Epilog with Line : ListPlot[ {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4, 13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full, Epilog -> { Line[ ...

equation solving - Invert and fit implicitly defined curve

I need to fit an implicitly defined curve. I thought I could get some data out of Solve , and then using FindFit . Therefore, I would like to find the relation the parametric curve defined by $F(x,y)=0$: Solve[-(1/2) + 1/2 (0.41202 BesselK[0, 0.1 Sqrt[x^2 + y^2]] + (0.101483 x BesselK[1, 0.1 Sqrt[x^2 + y^2]])/Sqrt[x^2 + y^2]) == 0, y] But I can't get an output: Solve was unable to solve the system with inexact coefficients or the system obtained by direct rationalization of inexact numbers present in the system. Since many of the methods used by Solve require exact input, providing Solve with an exact version of the system may help. >> Edit: In particular, I would like to fit the data coming from the curve with the expression of another curve, and not with a function $f(x)$. In particular, since this clearly looks like a cardioid , I would like it to fit to something like it. What other strategies could I try?

dynamic - How can I make a clickable ArrayPlot that returns input?

I would like to create a dynamic ArrayPlot so that the rectangles, when clicked, provide the input. Can I use ArrayPlot for this? Or is there something else I should have to use? Answer ArrayPlot is much more than just a simple array like Grid : it represents a ranged 2D dataset, and its visualization can be finetuned by options like DataReversed and DataRange . These features make it quite complicated to reproduce the same layout and order with Grid . Here I offer AnnotatedArrayPlot which comes in handy when your dataset is more than just a flat 2D array. The dynamic interface allows highlighting individual cells and possibly interacting with them. AnnotatedArrayPlot works the same way as ArrayPlot and accepts the same options plus Enabled , HighlightCoordinates , HighlightStyle and HighlightElementFunction . data = {{Missing["HasSomeMoreData"], GrayLevel[ 1], {RGBColor[0, 1, 1], RGBColor[0, 0, 1], GrayLevel[1]}, RGBColor[0, 1, 0]}, {GrayLevel[0], GrayLevel...