3
$\begingroup$

I have a list of the form:

{1,1, (1 if x>y, -1 if y>=x), -1}

I want to count the number of 1's in the list. The output I'm looking for is something of the form:

3 if x>y

2 if y>= x

How can I achieve this?

$\endgroup$
  • $\begingroup$ I take it that you execute a function to check if x>y and then if the list is already in that form, Count[list, 1] should work. Clarity is needed as to how the list looks like. $\endgroup$ – Abhay Hegde Apr 1 at 17:50
  • $\begingroup$ Thanks for your comment! The problem is that I don't want to evaluate the condition. I want it to give me a list of counts and symbolic conditions. $\endgroup$ – naomig Apr 1 at 17:55
  • $\begingroup$ But that list as it is cannot be evaluated, right? How do you encode the information that if and else part in the list. I mean I want to just know how have you really stored that list. $\endgroup$ – Abhay Hegde Apr 1 at 17:59
  • $\begingroup$ Oh I see. The list is literally of the form in the question, such that some of the entries are piecewise functions. This is why just using Count[list,1] doesn't work---it ignores every entry that is a piecewise expression. $\endgroup$ – naomig Apr 1 at 18:03
1
$\begingroup$
countPW[ls_, pat_] :=  Module[{
   cf = MapAt[Count[Flatten@#, pat] &, #, {{1, ;;, 1}, {2}}] &, 
   pwe = PiecewiseExpand[Append[Cases[_If]@ls, Cases[Except[_If]]@ls]}, 
   PiecewiseExpand[#, Method -> {"ConditionSimplifier" -> FullSimplify}] & @ cf @ pwe]

Examples:

list1 = {1, 1, If[x > y, 1, -1], -1};

countPW[list1, -1 | 1]
5
countPW[list1, 1] // TeXForm

$\begin{cases} 2 & x\leq y \\ 3 & \text{True} \end{cases}$

countPW[list1, -1] // TeXForm

$\begin{cases} 2 & x\leq y \\ 1 & \text{True} \end{cases}$

list2 = {1, 1, If[x > y, 1, -1], If[z > w, 1, -1], -1};

countPW[list2, -1 | 1]
7
countPW[list2, 1] // TeXForm

$\begin{cases} 2 & x\leq y\land w\geq z \\ 3 & \neg (w<z\veebar x\leq y) \\ 4 & \text{True} \end{cases}$

countPW[list2, -1] // TeXForm

$\begin{cases} 3 & x\leq y\land w\geq z \\ 2 & \neg (w<z\veebar x\leq y) \\ 1 & \text{True} \end{cases}$

list3 = {1, 1, 2, If[x > y, {1, 2, 3, -1}, -1], If[z > w, {1, 3, 4}, {2, 2, -1}], -1};

countPW[list3, 2 | -1] // TeXForm

$\begin{cases} 3 & x\leq y\land w<z \\ 6 & x\leq y\land w\geq z \\ 4 & x>y\land w<z \\ 7 & \text{True} \end{cases}$

| improve this answer | |
$\endgroup$
  • $\begingroup$ this is AWESOME, thank you!!! $\endgroup$ – naomig Apr 2 at 13:35
1
$\begingroup$

If the conditional expression is written in the Mathematica form

expr = {1, 1, If[x > y, 1, -1], -1, If[x > y, 1, -1], -1};

then we could define a function

Clear[count]
count[expr_, patt_] := Block[{cond, alt1, alt2},
  {cond, alt1, alt2} = 
      FirstCase[expr, item_If :> List @@ item];
      If[cond, 
         Evaluate[Count[expr /. cond :> True, patt]],
             Evaluate[Count[expr /. cond :> False, patt]]]    
]

which counts the patterns in the conditional expression

count[expr, 1]
(*  If[x > y, 4, 2]  *)

count[expr, -1]
(*  If[x > y, 2, 4]  *)

Note that count assumes, but does not check for, identical first arguments of each If.

| improve this answer | |
$\endgroup$
0
$\begingroup$

In no way is this the best solution, but this does the job.

l = Piecewise[{{1, x > y}, {-1, x <= y}}]

list = RandomChoice[{1, -1, l}, 5]
(*{Piecewise[{{1, x > y}, {-1, x <= y}}], -1, 1, Piecewise[{{1, x > y}, {-1, x <= y}}], -1}*)

Count[Assuming[#, Refine /@ list], 1] & /@ {x > y, x <= y}
(*3,1*)
| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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