3
$\begingroup$

Next task to complete:

  • Count *-symbol in such expression as a + s^2*b - c/y + o^3 + n*m*u (in this case count of * should be 6)

  • Powers such $o^3$ should be expand to $o*o*o$

I try, but my code is pretty ugly.

enter image description here

$\endgroup$
2
  • $\begingroup$ Please do not post code in a image. We need code posted as properly formatted text. Please edit your question by replacing the image with properly formatted code. Use the {?) that appears at the top right of the editor panel to learn how to format. $\endgroup$
    – m_goldberg
    Commented Jul 5, 2015 at 21:14
  • $\begingroup$ It may be inappropriate to count $k-1$ multiplications for $x^k$; binary exponentiation can certainly do that with less multiplications in some cases. $\endgroup$ Commented Jul 6, 2015 at 2:33

3 Answers 3

1
$\begingroup$

This doesn't give the result you are looking for exactly because it uses the full form of the expression you give it.

SetAttributes[countTimes, HoldAll];
countTimes[expr_] := Block[{Times, Power, power, times},
  power[a_, b_ /; b > 0] := Nest[times[a, #] &, a, b - 1];
  power[a_, b_ /; b < 0] := 1/power[a, -b];
  power[a_, 0] := 1;
  times[a___, b_times] := times[Sequence @@ b, a];
  Total[(Length /@ 
        Extract[#, Position[#, times[___]]] &[(expr /. 
         Power -> power) /. Times -> times]) - 1]
  ]

expr = a + s^2*b - c/y + o^3 + n*m*u

countTimes[expr]

(*8*)

The reason this gives 8 instead of 6 is because of the term -c/y which in full form is Times[-1,c,Power[y,-1]]. If you want to treat this specially you will need to add definitions to account for such patterns.

$\endgroup$
2
  • $\begingroup$ This does not work. Take a look at countTimes[a*b*c]. $\endgroup$
    – m_goldberg
    Commented Jul 5, 2015 at 21:10
  • $\begingroup$ @m_goldberg given the edit I believe this works now though I disagree with the accept. $\endgroup$
    – Andy Ross
    Commented Jul 5, 2015 at 23:18
3
$\begingroup$

Accepting that in Mathematica -c/y is automatically converted to -1*c*y^-1 and permitting the result shown in Andy's answer I believe we can use a simpler approach, at least for the kind of expression given in example.

Define rules that determine how a Times or Power expression should be counted, then use Cases to find all instances in you expression and total them with Tr:

rules = {
   _*x__ :> Length@{x},
   _^n_?Positive :> n - 1
 };

expr = a + s^2*b - c/y + o^3 + n*m*u;

Tr @ Cases[expr, #, -2] & /@ rules

Tr @ %
{5, 3}

8

As a single function:

fn[expr_] :=
 Tr @ Cases[expr, #, -2] & /@ {_*x__ :> Length@{x}, _^n_?Positive :> n - 1} // Tr

String conversion

If you prefer a string processing result, now accepting that the form Mathematica uses may seem rather arbitrary, I propose:

stringfn[expr_] := 
  StringCases[
    ToString[expr, InputForm],
    {"*" :> 1, "^" ~~ d__?DigitQ :> FromDigits[d] - 1}
  ] // Tr

a + s^2*b - c/y + o^3 + n*m*u // stringfn
6
$\endgroup$
2
  • $\begingroup$ Very much cleaner than mine +1 $\endgroup$
    – Andy Ross
    Commented Jul 5, 2015 at 22:56
  • $\begingroup$ @Andy Thank you. $\endgroup$
    – Mr.Wizard
    Commented Jul 5, 2015 at 22:57
3
$\begingroup$

I think this is easier to do by working with strings.

First write a function that will expand strings of the form "Power(x,k)" where k is an integer in "xx...x" with k - 1 ""s.

f[x_, k_] :=
  Module[{i = Abs[ToExpression[k]] - 1},
    Nest[StringJoin[#, "*" <> x] &, x, i]]

A couple of tests for f.

f["s", 2] 
"s*s"
f["ab", "-3"]
"ab*ab*ab"

Next write a function that will use f to transform powers and will count the stars in the expression after f has done its transformation.

starCount[expr_] :=
  StringCount[
    StringReplace[
      expr // CForm // ToString, 
      "Power(" ~~ v : WordCharacter .. ~~ "," ~~ k : NumberString ~~ ")" :> f[v, k]],
    "*"]

starCount[a + s^2*b - c/y + o^3 + n*m*u]
6
starCount[1/(b s^3) + 1/t^4]
6

Note: I use CForm to recover the /s that represent division, which the OP apparently wants to preserve as a distinct operator.

$\endgroup$
4
  • $\begingroup$ I like the idea of string conversion however this seems baroque. I added what seems like a cleaner alternative to my answer. Does mine fail where yours does not? $\endgroup$
    – Mr.Wizard
    Commented Jul 5, 2015 at 22:55
  • $\begingroup$ @Mr.Wizard. Well, your string munger gets 3 from 1/(b s^3) + 1/t^4 and mine gets 6. Which do you think would be the value the OP would expect? $\endgroup$
    – m_goldberg
    Commented Jul 5, 2015 at 23:56
  • $\begingroup$ Frankly I don't know. +1 for your interpretation. $\endgroup$
    – Mr.Wizard
    Commented Jul 6, 2015 at 1:51
  • 1
    $\begingroup$ @Mr.Wizard. Perhaps we can agree that this is a rather difficult question to deal with -- especially since there are not any asterisks at all in a Mathematica numerical expression as the kernel sees them. Are we not counting virtual stars in a symbolic sky with no star to guide us, but only a rather poor example to serve in its place. No wonder there is no agreement on the answer. And, please, don't take this guff I'm spouting seriously. $\endgroup$
    – m_goldberg
    Commented Jul 6, 2015 at 2:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.