1
$\begingroup$

I want to know if there's a way to impose desired condition on Tuple command output. I have generated a list of 3-tuple of elements from {1,2,3,4,5,6,7,8,9,10} using

Tuples[{1,2,3,4,5,6,7,8,9,10}, 3]

Now, I want to select only those tuples of the list which satisfy this condition:- a+b+c=15, where a,b and c belongs to {1,2,3,4,5,6,7,8,9,10}

I have just begun using Mathematica 10.1.0.0

$\endgroup$
0
3
$\begingroup$

This is answer to your original question, sorting only those tuples that are have total sum of 15. You can have a delayed replacement rule with a condition for the required sum:

Tuples[{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 3] /. x_List /; Total[x] == 15 :> Sort[x]

If you actually meant selecting only those tuples, you can simply use Select:

Select[Tuples[{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 3], Total[#] == 15 &]

... or use Cases, if you prefer pattern-matching instead of a function:

Cases[Tuples[{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 3], x_List /; Total[x] == 15]

One has to note that these are really not scalable methods, since combinatorial explosion will use away all the memory for storage of tuples very easily on larger values. They're straight-forward for very small toy problems, though.

$\endgroup$
3
  • $\begingroup$ It solved my problem. Thank you. $\endgroup$ – Abhijit Gupta Apr 5 '15 at 7:28
  • $\begingroup$ May I know what modification should be made if I change the condition to say - a^2+b^2+c^2=15 ? $\endgroup$ – Abhijit Gupta Apr 5 '15 at 7:35
  • $\begingroup$ @AbhijitGupta You can easily modify the condition to something like {a_, b_, c_} /; a^2 + b^2 + c^2 == 15 (although 15 doesn't return tuples). You should also consider constructs like {a, b, c} /. Solve[a^2 + b^2 + c^2 == 38 && 1 <= a <= b <= c <= 10, {a, b, c}, Integers], where you avoid generating tuples to filter altogether. $\endgroup$ – kirma Apr 5 '15 at 8:07
5
$\begingroup$

Horribly inefficient way to do such things. Use IntegerPartitions:

set = Range@100;
total = 400

s = Select[Tuples[set, 3], Total[#] == t &]; // Timing // First
j = Sort[Join @@ Permutations /@ IntegerPartitions[total, {3}, set]]; // Timing // First

s == j

(* 
   12.948083
   0.
   True
*)

The latter is below timing resolution...

For your case, this w/b

Sort[Join@@Permutations/@IntegerPartitions[15,{3},{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}]]
$\endgroup$
7
  • $\begingroup$ What modification do I have to make if I change the constraint to a^2+b^2+c^2=40 ? $\endgroup$ – Abhijit Gupta Apr 5 '15 at 7:49
  • $\begingroup$ @AbhijitGupta: Modify your thinking? Why would one want to create a slew of tuples, most of which won't meet the criteria, only to waste time filtering them? There are tools (like Solve) that will get you answers to that kind of problem much more efficiently... $\endgroup$ – ciao Apr 5 '15 at 7:55
  • $\begingroup$ Inefficiency... well, it depends. Unless running out of memory, one may also consider difference between clarity and efficiency. Clarity is often a good starting point for small problems. In this case, I decided not to rewrite the starting point of using Tuples... $\endgroup$ – kirma Apr 5 '15 at 7:57
  • $\begingroup$ @kirma: In any case, Sort[Join @@ Permutations /@ Sqrt[IntegerPartitions[40, {3}, (Range@10)^2]]] will answer the a^2+b^2+c^2=40 kinds of question , again vastly more efficiently than building and filtering tuples. $\endgroup$ – ciao Apr 5 '15 at 8:04
  • 1
    $\begingroup$ @AbhijitGupta: Well, when you get to domains beyond sizes a kid can do on an abacus (oh, say only 1-1000), let us know how that Tuples[Range@1000,{3}] works out for you ;-} In any case, specification of domain/etc. is copiously covered in the documentation. $\endgroup$ – ciao Apr 5 '15 at 8:11
3
$\begingroup$

If order does not matter you could use IntegerPartition. This yields 15 partitions.

ip = IntegerPartitions[15, {3}];
v = Pick[ip, Max@# < 11 & /@ ip]

yields:

{{10, 4, 1}, {10, 3, 2}, {9, 5, 1}, {9, 4, 2}, {9, 3, 3}, {8, 6, 
  1}, {8, 5, 2}, {8, 4, 3}, {7, 7, 1}, {7, 6, 2}, {7, 5, 3}, {7, 4, 
  4}, {6, 6, 3}, {6, 5, 4}, {5, 5, 5}}

To count the permutations:

mn[x_] := Multinomial @@ Tally[x][[All, 2]]
Total[mn /@ v]

yields: 73 (as per Tuples answer).

To generate list:

Join @@ (Permutations /@ v)
$\endgroup$
2
  • $\begingroup$ Ah, lol - typing at same time - I'll happily delete mine if desired, +1 o/c! (and don't forget - there's another argument to IP to avoid the extra filtering step) $\endgroup$ – ciao Apr 5 '15 at 7:43
  • $\begingroup$ @rasher no your answer adds insight, so keep. :) $\endgroup$ – ubpdqn Apr 5 '15 at 7:45

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.