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$

2 Answers 2

4
$\begingroup$

Also

ClearAll[cKp]
cKp[e_,n_]:= _List?(CountDistinct[#] == n && SubsetQ[e, #]&)
$\endgroup$
2
  • $\begingroup$ Very elegant thank you $\endgroup$
    – Jojo
    May 9, 2018 at 8:50
  • $\begingroup$ @Joe, thank you for the accept. $\endgroup$
    – kglr
    May 9, 2018 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$
2
  • 1
    $\begingroup$ this works too...Hold[list_List, Length@Intersection[elems, list] == n] (I don't have ContainsAll ..) $\endgroup$
    – george2079
    May 8, 2018 at 16:42
  • $\begingroup$ Thank you this is nice and it works $\endgroup$
    – Jojo
    May 9, 2018 at 8:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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