g | x | w | all
Bytes Lang Time Link
016Japt v1.4.5250127T101035ZShaggy
093JavaScript V8250127T112526ZArnauld
097Python 3250128T003039ZLucenapo
012Jelly250127T180623ZJonathan
030Haskell + hgl250127T161738ZWheat Wi
121Maple250127T162225Zdharr
014Vyxal250127T114805Zlyxal
038Charcoal250127T123111ZNeil
082Retina250127T105636ZNeil

Japt v1.4.5, 18 17 16 bytes

Takes input as a 2D array of ["element","colour"] pairs, outputs a 3D array. Any set of values can be substituted for the elements & colours.

à3 f@#søXyâ mʬ

Try it

à3 f@#\u0085søXyâ mʬ     :Implicit input of 2D array
à3                        :Combinations of length 3
   f                      :Filter by
    @                     :Passing each X through the following function
     #\u0085              :  Compressed integer 133
            s             :  To string
             ø            :  Contains
              Xy          :    Transpose X
                â         :    Deduplicate each sub-array
                  m       :    Map
                   Ê      :      Length
                    ¬     :    Join

JavaScript (V8), 93 bytes

Expects a list of 9-bit integers, using a combination of the following bit-masks:

Prints triplets of integers in the same format.

f=([c,...a],m,o=[])=>c?f(a,m|c,[...o,c])|f(a,m,o):150>>m%8&!o[3]&&(m/=8,m&=m-1)&m-1&&print(o)

Try it online! (prettified I/O)
Try it online! (raw I/O)

Commented

f = (          // f is a recursive function taking:
  [c,          //   c = next card
      ...a],   //   a[] = remaining cards
  m,           //   m = bit-mask, initially undefined
  o = []       //   o[] = output
) =>           //
c ?            // if c is defined:
  f(           //   first recursive call where the card is selected:
    a,         //     pass a[]
    m | c,     //     update m with a bitwise OR with c
    [...o, c]  //     append c to o[]
  ) |          //   end of recursive call
  f(a, m, o)   //   second recursive call with everything unchanged
               //   (i.e. the card is ignored)
:              // else, make sure that:
  150 >> m % 8 //   1) m % 8 is in [1, 2, 4, 7]
               //      (either a single element bit or the 3 of them)
               //      by testing the bit-mask 0b10010110 = 150
  & !o[3]      //   2) o[3] is not defined (no more than 3 cards)
  && (         //   3) three color bits are set in m:
    m /= 8,    //     - discard the element bits
    m &= m - 1 //     - remove the least significant 1
  ) & m - 1    //     - remove the least significant 1 again
  && print(o)  //   print o if all conditions are met

Python 3, 97 bytes

lambda t:[(x,y,z)for x in t for y in t for z in t if-128|x^y^z==-128|x+y+z<2>(x*y*z>>33)%7<x<y<z]

Try it online!

Uses the following bit masks:
1,2,4,8,16,32 for colours
2048,4096,8192 for elements

Jelly, 12 bytes

œc3=ⱮḄ§BȦʋ$Ƈ

A monadic Link that accepts a list of cards as pairs of [Element, Colour] where Element and Colour are integers or characters and yields the valid sets as a list of triples of cards.

Try it online! Or see the test-suite.

How?

œc3=ⱮḄ§BȦʋ$Ƈ - Link: list of pairs of ints/chars, Cards
œc3          - combinations of three {Cards} -> Triples
           Ƈ - keep those Triples for which:
          $  -   last two links as a monad - f(Triple):
    Ɱ        -     map across {RightCard in Triple) with:
   =         -       {Triple} equals {RightCard} (vectorises)
         ʋ   -     last four links as a dyad - f(Comparisons=that, Triple):
     Ḅ       -       convert {Comparisons} from binary
      §      -       sum each {of those}
       B     -       convert {that} to binary (vectorises)
        Ȧ    -       any & all of {that}? (here, contains no zeros when flattened?)

Note: the right argument of ʋ is not used, this was only made dyadic (i.e. is not Ʋ) because it allows the first link in the filter's chain - the dyadic =Ɱ - to not need to specify that it should use its left argument on both sides (i.e. otherwise we need to use `).

In general, a triple is being assessed as follows

Triple to check:
((Element=A, Colour=a), (Element=B, Colour=b), (Element=C, Colour=c))

=Ɱ -> Comparisons:
[[[A==A, a==a], [A==B, a==b], [A==C, a==c]],
 [[B==A, b==a], [B==B, b==b], [B==C, b==c]],
 [[C==A, c==a], [C==B, c==b], [C==C, c==c]],
]

Ḅ -> convert that from binary:
[[2*(A==A)+(a==a), 2*(A==B)+(a==b), 2*(A==C)+(a==c)],
 [2*(B==A)+(b==a), 2*(B==B)+(b==b), 2*(B==C)+(b==c)],
 [2*(C==A)+(c==a), 2*(C==B)+(c==b), 2*(C==C)+(c==c)],
]

§ -> sum each of those:
[2*(A==A)+(a==a)+2*(A==B)+(a==b)+2*(A==C)+(a==c),
 2*(B==A)+(b==a)+2*(B==B)+(b==b)+2*(B==C)+(b==c),
 2*(C==A)+(c==a)+2*(C==B)+(c==b)+2*(C==C)+(c==c),
]

...which is equal to:
[3 + 2 * ((A==B) + (A==C)) + (a==b) + (a==c),
 3 + 2 * ((B==A) + (B==C)) + (b==a) + (b==c),
 3 + 2 * ((C==A) + (C==B)) + (c==a) + (c==b),
]

Then it checks whether all three of these numbers are either three or seven by checking they are all one less than a power of two (all ones in binary).

This works because the Colours (abc) need to all be different in order not to change any number's two least significant bits (from the 3 + ), meanwhile, the Elements (ABC) need to either (a) all be different (to keep every number down to three) OR (b) all be the same (making all numbers equal seven). Note that the maximum a number can ever be is nine (when the three cards are all the same). Furthermore, no mix of threes and sevens is possible (if one expression evaluates to seven, each of the others have one of its Element equality terms so they both increase from three).

Haskell + hgl, 30 bytes

fl(mp<%(uq=:(uq*|*lq))<uz)<ss3

Attempt This Online!

Takes input as a list of tuples. The interiors of the tuples can be any types with an Eq instance, I use numbers in the test case.

Explanation

Pretty straightforward. ss3 gets us all the triplets, then we use a filter (fl) to get the ones matching. The internals of the check is the most interesting part.

Reflection

I'm not happy with how long this is.

Maple, 121 bytes

c->select(x->nops({map2(op,2,x)[]})=3and((e:=nops({map2(op,1,x)[]}))=3or e=1),[seq(c[i],i=combinat:-choose(nops(c),3))]);

Ungolfed:

f:=proc(c)                                # input e.g. [[W,Y],[F,B],[S,R],[S,R]]
[seq(c[i],i=combinat:-choose(nops(c),3))];# all combinations of 3 cards
select(x->nops({map2(op,2,x)[]})=3        # filter for 3 different colors
  and ((e:=nops({map2(op,1,x)[]}))=3 or e=1),%); # and either 1 or 3 elements 
end proc;

Vyxal, 14 bytes

3ḋ'∩÷:U⁼$UL2≠*

Try it Online!

Ah 2011-2017, much simpler times in life. That time being when I played Club Penguin (ending in 2017 because that's well when Disney decided it'd be a good idea to shut the website down smh). Fun fact you mightn't've known about me: I was an avid IRL Card Jitsu collector (because they made real life Card Jitsu booster packs that were sold in actual brick and mortar stores). I was also black belt on Club Penguin, so this challenge brings back good memories of being young :)

In terms of the code golf (the reason we're here), takes input as a list of [Element, Colour], and outputs as a list of lists of [Element, Colour]. The linked program converts the IO from the challenge body to this format (the header and footer).

Explained

3ḋ'∩÷:U⁼$UL2≠*­⁡​‎‎⁡⁠⁡‏⁠‎⁡⁠⁢‏‏​⁡⁠⁡‌⁢​‎‎⁡⁠⁣‏‏​⁡⁠⁡‌⁣​‎‎⁡⁠⁤‏⁠‎⁡⁠⁢⁡‏‏​⁡⁠⁡‌⁤​‎‎⁡⁠⁢⁢‏⁠‎⁡⁠⁢⁣‏⁠‎⁡⁠⁢⁤‏‏​⁡⁠⁡‌⁢⁡​‎‎⁡⁠⁣⁡‏⁠‎⁡⁠⁤⁢‏‏​⁡⁠⁡‌⁢⁢​‎⁠‎⁡⁠⁣⁢‏⁠‎⁡⁠⁣⁣‏⁠‎⁡⁠⁣⁤‏⁠‎⁡⁠⁤⁡‏‏​⁡⁠⁡‌­
3ḋ              # ‎⁡Combinations without replacement of length 3
  '             # ‎⁢Keep combinations where:
   ∩÷           # ‎⁣  (After transposing the combination to have [elements, colours] on the stack)
     :U⁼        # ‎⁤  The colours are unique
        $    *  # ‎⁢⁡   AND
         UL2≠   # ‎⁢⁢  There are either 3 unique colours, or 1 unique colour
💎

Created with the help of Luminespire.

Charcoal, 38 bytes

WS⊞υιFLυFιΦE…υκ⁺λ⁺§υκ§υι⬤λ№E⊕№αν⊕⊗π№λν

Try it online! Link is to verbose version of code. Takes input as a list of newline terminated pairs of uppercase letters and other printable ASCII and outputs a list of sets of three cards. Explanation:

WS⊞υι

Read in the cards.

FLυFι

Start enumerating the third and second card of each possible set.

E…υκ⁺λ⁺§υκ§υι

Enumerate all sets of three cards as a single string.

Φ...⬤λ№E⊕№αν⊕⊗π№λν

Filter on those whose characters are unique, unless they are uppercase letters, in which case they may appear exactly 3 times.

Retina, 82 bytes

Lv`[A-C].+
L$wm`(?<=^(..)+)(..)(..)+
$1$2$3
Am`(\d).+\1|([A-C]).+\2.+$(?<!^(\2.)+)

Try it online! Takes input as a string of six characters using A-C to represent elements and any six digits of your choice to represent colours. (I have not been consistent between different test cases.) Explanation:

Lv`[A-C].+

Get all of the even-length suffixes of the input.

L$wm`(?<=^(..)+)(..)(..)+
$1$2$3

Get all of the sets of three cards.

Am`(\d).(..)?\1|([A-C]).+\3.+$(?<!^(\3.)+)

Remove those with repeated digits or those with duplicated but not triplicated letters.