1
$\begingroup$
Do[Print[{x + y + z == 3, x + y > z}], {x, 1, 2, 1}, {y, 1, 2, 1}, {z, 1, 2, 1}]

If I run this syntax I get a series of Outputs, I am trying to Count only the number of outputs which is {True,True}

$\endgroup$
1
  • 1
    $\begingroup$ list = Table[{x + y + z == 3, x + y > z}, {x, 1, 2, 1}, {y, 1, 2, 1}, {z, 1, 2, 1}]; Count[list, {True, True}, Infinity]. How about using Count when you want to count? $\endgroup$
    – Öskå
    Commented May 2, 2014 at 10:48

5 Answers 5

6
$\begingroup$

Just use Table instead of Do and Print, then Count with an appropriate levelspec:

Count[
 Table[{x + y + z == 3, x + y > z}, {x, 2}, {y, 2}, {z, 2}],
 {True, True},
 {-2}
]
1
$\endgroup$
3
$\begingroup$

Here is an approach:

test = Tuples[{1, 2}, 3];
Cases[{{##1}, #1 + #2 + #3 == 3, #1 + #2 > #3} & @@@ test, {_, True, 
  True}]

yielding (as one would expect):{{{1, 1, 1}, True, True}}

or you could use:

Pick[test, And[#1 + #2 + #3 == 3, #1 + #2 > #3] & @@@ test]

To count just use Length (obviously unnecessary in this case)

$\endgroup$
5
  • 2
    $\begingroup$ FYI a nice shorthand for #1 + #2 + #3 is +## $\endgroup$ Commented May 2, 2014 at 11:00
  • $\begingroup$ @SimonWoods thank you Simon Woods: always learning $\endgroup$
    – ubpdqn
    Commented May 2, 2014 at 11:03
  • $\begingroup$ @Simon out of curiosity did you learn that from me or come up with it yourself? Do you also use 1##? $\endgroup$
    – Mr.Wizard
    Commented May 2, 2014 at 11:05
  • $\begingroup$ @Mr.Wizard, I think I must have learnt it from you, sorry I should have acknowledged that. I've used 1## but only for fun. $\endgroup$ Commented May 2, 2014 at 11:32
  • $\begingroup$ @Simon I don't expect acknowledgement; I was just curious. I'm the only one I can recall seeing use that around here but I know we have a similar style. (I love it when you show me how to make my code more terse!) $\endgroup$
    – Mr.Wizard
    Commented May 2, 2014 at 11:50
2
$\begingroup$

Sometimes, storing the whole list before counting may be inappropriate (perhaps the list is huge). In this case, this solution may be useful:

count = 0;
Do[If[And @@ {x + y + z == 3, x + y > z}, count++],
   {x, 1, 2, 1}, {y, 1, 2, 1}, {z, 1, 2, 1}
];
count

1

$\endgroup$
1
  • 1
    $\begingroup$ If the list is huge, then speed might be a consideration. And[x + y + z == 3, x + y > z] should be faster; also compiling should save time. $\endgroup$
    – Michael E2
    Commented May 2, 2014 at 23:38
1
$\begingroup$

(Before Mr.W updates his post:)

Boole[(+##1 == 3) ~And~ (+##2 > #1)] & ~Array~ {2, 2, 2} ~Total~ -1
(* 1 *)

or

cnt = 0; (+##1 == 3)&&(+##2 > #1) & ~Array~ {2, 2, 2}//.{True :> cnt++}; cnt

or

cnt = 0; (cnt += Boole[+##1 == 3 && +##2 > #1]) & ~Array~ {2, 2, 2}; cnt
$\endgroup$
1
  • $\begingroup$ I edited your post to make the infix more readable, as I always recommend. Also I don't believe Rule was correct so I replaced it. +1 for syntax fun. p.s. ##1 and #1 can be written ## and #, for those who like to save characters. p.p.s. && and :> are already infix so there's not much point in writing out ~And~ or ~RuleDelayed~, other than being silly. ;-) $\endgroup$
    – Mr.Wizard
    Commented May 3, 2014 at 2:01
0
$\begingroup$

If you have a list of True and False values, you can count them by changing True values to 1 (using Boole) and summing the new list, then for the number of falses invert the list and sum:

list = {True, True, False};
trues = Total@Boole@list;
falses = Total@Boole[Not /@ list];

[Alternatively] You can also use Length with Cases with the Pattern 'if value equals' the desired boolean:

trues = Length@Cases[list, x_ /; x == True] 
falses = Length@Cases[list, x_ /; x == False] 
$\endgroup$

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.