| Bytes | Lang | Time | Link |
|---|---|---|---|
| 013 | Japt v2.0a0 | 250129T161000Z | Shaggy |
| 099 | Python 2 | 191030T011936Z | Chas Bro |
| 012 | Brachylog | 191029T055747Z | Unrelate |
| 073 | Mathematica | 131016T200206Z | DavidC |
| 071 | Sage | 131017T183226Z | boothby |
| 080 | Ruby | 131016T130808Z | Doorknob |
| 053 | GolfScript | 131016T220338Z | Howard |
| 076 | APLIBM | 131017T101748Z | TwiN |
| 073 | Mathematica | 131017T101210Z | alephalp |
| 313 | javascript | 131016T142304Z | Math chi |
Japt v2.0a0, 13 bytes
¸à3 fÈÕeÈâ ÊÍ
¸à3 fÈÕeÈâ ÊÍ :Implicit input of string
¸ :Split on spaces
à3 :Combinations of length 3
f :Filter by
È :Passing each through the following function
Õ : Transpose
e : All truthy when
È : Passed through the following function
â : Deduplicate
Ê : Length
Í : Subtract from 2
Python 2, 99 bytes
lambda A:[a for a in combinations(A,3)if all(len(set(t))-2for t in zip(*a))]
from itertools import*
Brachylog, 12 bytes
ṇ₁⊇Ṫz{=|≠}ᵐz
Takes input through the input variable and generates the output through the output variable.
Second test case taken from a recently closed duplicate in its encoding, since this solution doesn't really care what anything actually means.
The output variable is
⊇ a subsequence
Ṫ of length 3
ṇ₁ of the input split on spaces,
z z the columns of which
{ }ᵐ are all
| either
= the same element repeated,
≠ or entirely free of duplicates.
Mathematica 93 92 93 82 76 73
f={}⋃Select[StringSplit@#~Subsets~{3}, FreeQ[Tally/@(Characters@#^T),2]&]&
The Logic
StringSplit@#~Subsets~{3} produces a list of 3-card subsets. Each triple such as:
{{"D", "G", "3", "N"}, {"W", "G", "3", "S"}, {"O", "G", "3", "O"}}
or

is then transposed,

and Tally/@(Characters@#^T) tallies the number of distinct items in each row.
{3,1,1,3}
3 corresponds to "all different"; 1 corresponds to "all same".
FreeQ[...,2] determines whether 2 cards of the same type or in the triple.
If 2 is not among the tallies, then the three cards are a "set", according to Game of Set rules.
Usage
f["OR1N WP2N DG3N DR1D WG3S WG1N WR2D WP3N DR2O DR1D OG3O OR2D"]
{{"DG3N", "WG3S", "OG3O"}, {"OR1N", "WP2N", "DG3N"}, {"WP2N", "DR1D", "OG3O"}}
Sage, 71
If C is a string, say "OR1N WP2N DG3N DR1D WG3S WG1N WR2D WP3N DR2O DR1D OG3O OR2D", execute
[c for c in Subsets(C.split(),3)if{1,3}>={len(set(x))for x in zip(*c)}]
to get [{'DR1D', 'OG3O', 'WP2N'}, {'DR2D', 'WR2D', 'OR2D'}, {'WG3S', 'OG3O',
'DG3N'}, {'DG3N', 'WP2N', 'OR1N'}]
And here's a very different approach using the interpretation that a Set is a projective line in GF(3)^4:
[c for c in Subsets(C.split(),3)if sum(matrix(3,map('WODRPG123N'.find,''.join(c))))%3==0]
I was a little annoyed that D was used twice... until I figured how to abuse that. But even better, I abuse the find method, too. str.find returns -1 if a letter isn't found. Since -1 = 2 mod 3, the letter S is handled appropriately because it doesn't occur in 'WODRPG123N'.
Ruby, 104 98 81 80 characters
$*.combination(3).map{|c|puts c*?,if(0..3).all?{|i|c.map{|x|x[i]}.uniq.size!=2}}
Sample run (using your example data):
c:\a\ruby>set.rb OR1N WP2N DG3N DR1D WG3S WG1N WR2D WP3N DR2O DR1D OG3O OR2D
OR1N,WP2N,DG3N
WP2N,DR1D,OG3O
WP2N,DR1D,OG3O
DG3N,WG3S,OG3O
It outputs WP2N,DR1D,OG3O twice because you have two DR1Ds in your sample data.
Explanation:
$*.combination(3).map{|c| - each combination of 3 cards
puts c*?,if - output the set, if...
(0..3).all?{|i| - if all of the numbers from 0 to 3 (the indeces of the properties in the string) evaluate to true when passed into this block
c.map{|x|x[i]} - take the ith index of each string
.uniq.size!=2} - if the amount of unique properties (form, color, etc.) is not 2 (so, 1 or 3)
GolfScript, 53 characters
" "/:w,,{:a,{:^,{a^]{w=}%.0\zip{.&,2=|}/!{.p}*;}/}/}/
Input must be provided on STDIN, example online:
> OR1N WP2N DG3N DR1D WG3S WG1N WR2D WP3N DR2O DR2D OG3O OR2D
["OR1N" "DG3N" "WP2N"]
["WP2N" "OG3O" "DR1D"]
["DG3N" "OG3O" "WG3S"]
["WR2D" "OR2D" "DR2D"]
Commented code:
" "/:w # split the input at spaces and assign it to variable w
,, # create the array [0..n-1] (n being the length of w)
{:a,{:^,{ # three nested loops: a=0..n-1, ^=0..a-1, _=0..b-1
# (third loop has no variable assigned but just pushes on stack)
a^] # make an array [a,^,_] of the three loop variables
{w=}% # take the corresponding list items, i.e. [w[a],w[^],w[_]]
.0\ # push zero, add duplicate of the the array
zip # zip transposes the array, thus [OR1N WP2N DG3N] -> [OWD RPG 123 NNN]
{ # loop over those entries
.& # unique
,2= # length equals 2?
| # "or" with top of stack (two zero pushed before)
}/ # end of loop, on stack remains the results of the "or"s
!{.p}* # if no length of 2 is there, make a copy of the set and print it
; # discard stack item
}/}/}/ # closing the three nested loops
APL(IBM), 76
⍉¨x/⍨{{⍵≡1⌽⍵}⍵=1⌽⍵}¨x←⊃¨(∘.,/3⍴⊂⍪¨(' '≠y)⊂y←⍞)⌷⍨¨z/⍨∧/¨2</¨z←,⍳3⍴12
I don't have IBM APL, but I believe this will work.
Sample run (Emulating IBM APL in Dyalog APL)
OR1N WP2N DG3N DR1D WG3S WG1N WR2D WP3N DR2O DR1D OG3O OR2D
OR1N WP2N WP2N DG3N
WP2N DR1D DR1D WG3S
DG3N OG3O OG3O OG3O
Mathematica 73
f = Select[StringSplit@#~Subsets~{3}, FreeQ[Tally /@ Thread@Characters@#, 2] &] &
Usage
f["OR1N WP2N DG3N DR1D WG3S WG1N WR2D WP3N DR2O DR1D OG3O OR2D"]
{{"OR1N", "WP2N", "DG3N"}, {"WP2N", "DR1D", "OG3O"}, {"WP2N", "DR1D", "OG3O"}, {"DG3N", "WG3S", "OG3O"}}
javascript 323 313
function a(b){d=h=[];c=e=f=0;for(i in b){for(j in b){for(k in b[i]){if(b[i][k]==b[j][k]){if(c+f<4)c++;else if(c==4){h+=b[j];if(h.length=3)return h}}else{for(l in d){for(m in d[l]){g=f;if(d[l][2]==i){if(d[l][3]==k)if(b[j][k]!=d[l][0]&&b[j][k]!=d[l][1])f++;}else{continue}}if(g==f)d[e++]=[b[i][k],b[j][k],j,k]}}}}}}
its a function that takes a array of objects, and returns a array of objects.
DEMO fiddle (with tidy-up).