2
$\begingroup$

I am curious about how LeafCount works because when I count the number of leaves in my solution to a Wolfram Challenge, I get a much smaller result than those listed on the leaderboard for Multiples of 3 and 5: enter image description here Solution warning: I will show the solution to Multiples of 3 and 5, although it is a very simple application of two basic arithmetic operators from number theory

LeafCount[ThreeFive[n_Integer] /; n > 0 := Floor[n/15]]
LeafCount[Floor[n/15]]

I made sure to look at the Possible Issues section of the documentation center on Leaf Count. Two factors that might be the reason for this discrepancy

  • LeafCount is based on the FullForm of expressions:
  • Unlike TreeForm, LeafCount takes into consideration the structure of expression heads
$\endgroup$
2
  • 2
    $\begingroup$ Take a look at ExpressionTree[ThreeFive ...] and ExpressionTree[Floor[n/15]]. You can see that your definition of function gets evaluated (!) and returns "nothing" (or something like this, I am not sure), therefore only one leaf. Try with Hold: LeafCount[Hold[ThreeFive[...] := ...]], which will give you 17 leafs (one of them being Hold itself). $\endgroup$
    – Domen
    Commented Nov 22, 2021 at 22:17
  • $\begingroup$ Thank you it worked! $\endgroup$ Commented Nov 22, 2021 at 22:19

1 Answer 1

3
$\begingroup$

You are getting a smaller leaf count than expected because the expression is evaluating before the leaves are counted. To get the leaf count of the unevaluated expression, used Unevaluated:

In[1]:= LeafCount[Unevaluated[ThreeFive[n_Integer] /; n > 0 := Floor[n/15]]]
                                         
Out[1]= 16

LeafCount does not hold its arguments, so LeafCount[ThreeFive[...] := ...] is equivalent to LeafCount[Null]:

In[2]:= FullForm[ThreeFive[n_Integer] /; n > 0 := Floor[n/15]]

Out[2]//FullForm= Null

In[3]:= LeafCount[ThreeFive[n_Integer] /; n > 0 := Floor[n/15]]

Out[3]= 1

In[4]:= LeafCount[Null]

Out[4]= 1

The first Possible Issue example is a red herring, LeafCount[Sqrt[x]] gives LeafCount[Power[x, Rational[1, 2]]] not because of FullForm, but because Sqrt evaluated. LeafCount[Unevaluated[Sqrt[x]]] gives 2 as expected.

For some atomic expressions (i.e. rational and complex numbers), LeafCount treats the atom as a compound expression according to its FullForm:

In[5]:= AtomQ[1/2]                                                                                                     
Out[5]= True

In[6]:= FullForm[1/2]                                                                                                  
Out[6]//FullForm= Rational[1, 2]

In[7]:= LeafCount[1/2]                                                                                                 
Out[7]= 3

That explains why LeafCount[n/15] gives 5 (Times[Rational[1, 15], n]) rather than 3 (Times[1/15, n]).

Setting the issue of FullForm aside, LeafCount gives the number of leaves in the tree of all subexpressions (including heads), not in the tree of heads (as used by TreeForm). These are the "Subexpressions" and "Heads" structures in ExpressionTree, respectively:

ExpressionTree[f[a[b]][c, d], "Subexpressions"]

"Subexpressions" ExpressionTree

ExpressionTree[f[a[b]][c, d], "Heads"]

"Heads" ExpressionTree

Currently, neither ExpressionTree or TreeForm directly give trees corresponding to the FullForm of rationals and complexes, but it can be done:

In[1]:= tree = ExpressionTree[n/15 + 2/3 I, "Atoms"]

tree

In[2]:= positions = TreePosition[tree, _Rational | _Complex, {-1}]

Out[2]= {{2}, {3, 2}}

In[3]:= SetAttributes[atomTree, HoldFirst];
atomTree[fullForm_] := ExpressionTree[Unevaluated[fullForm], "Atoms"]

In[5]:= rules = Map[
  pos |-> pos -> 
    TreeExtract[tree, pos, 
     leaf |-> 
      ToExpression[ToString[FullForm[TreeData[leaf]]], StandardForm, 
       atomTree]], positions]

rules

In[6]:= TreeReplacePart[tree, rules]

TreeReplacePart

In[7]:= Length[TreeLeaves[%]]

Out[7]= 11

In[8]:= LeafCount[n/15 + 2/3 I]

Out[8]= 11
$\endgroup$

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