5
$\begingroup$

I would like a pattern which takes as an argument a set with $n$ elements, and an integer $k$ which is less than $n$ and greater than 1, and which matches against any $k$ distinct elements of the set, in a nice elegant way.

So I'd like ChoosePattern[set,k] which satisfies, for example,

MatchQ[{a,b}, ChoosePattern[{a,b,c},2]]
MatchQ[{c,b}, ChoosePattern[{a,b,c},2]]
MatchQ[{1,2,4,3}, ChoosePattern[Range[8],4]]
MatchQ[{1,8,5,6}, ChoosePattern[Range[8],4]]

And doesn't match

MatchQ[{a,d}, ChoosePattern[{a,b,c},2]]
MatchQ[{c,b,a}, ChoosePattern[{a,b,c},2]]
MatchQ[{1,2,2,3}, ChoosePattern[Range[8],4]]
MatchQ[{1,8,5,6,7}, ChoosePattern[Range[8],4]]

Thank you

EDIT: Just a small addition to kglr's very nice solution, here are my pattern and matching functions for choosing either any number, or a fixed number, or a range of possible numbers, of distinct elements from a given set;

ChoosePattern[set_List, 
  k_Integer] := _List?(CountDistinct[#] === k && SubsetQ[set, #] &)
ChoosePattern[
  set_List, {k1_Integer, 
   k2_Integer}] := _List?(CountDistinct[#] === Length[#] && 
     k1 <= Length[#] <= k2 && SubsetQ[set, #] &)
ChoosePattern[
  set_List] := _List?(CountDistinct[#] === Length[#] && 
     SubsetQ[set, #] &)
ChooseQ[set_List, subset_List, k_Integer] := 
 MatchQ[subset, ChoosePattern[set, k]]
ChooseQ[set_List, subset_List, {k1_Integer, k2_Integer}] := 
 MatchQ[subset, ChoosePattern[set, {k1, k2}]]
ChooseQ[set_List, subset_List] := MatchQ[subset, ChoosePattern[set]]
$\endgroup$
4
$\begingroup$

Also

ClearAll[cKp]
cKp[e_,n_]:= _List?(CountDistinct[#] == n && SubsetQ[e, #]&)
$\endgroup$
  • $\begingroup$ Very elegant thank you $\endgroup$ – Joe May 9 '18 at 8:50
  • $\begingroup$ @Joe, thank you for the accept. $\endgroup$ – kglr May 9 '18 at 17:35
7
$\begingroup$

This seems to pass all those tests:

ChooseKPattern[elems_List, n_Integer] := Block[{list}
, Condition @@ Hold[
    list_List
  , Length[DeleteDuplicates @ list] == n && ContainsAll[elems, list]
  ]
]
$\endgroup$
  • 1
    $\begingroup$ this works too...Hold[list_List, Length@Intersection[elems, list] == n] (I don't have ContainsAll ..) $\endgroup$ – george2079 May 8 '18 at 16:42
  • $\begingroup$ Thank you this is nice and it works $\endgroup$ – Joe May 9 '18 at 8:49

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.