Game of Set Puzzle
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"}}
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 DR1D
s 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 i
th index of each string
.uniq.size!=2}
- if the amount of unique properties (form, color, etc.) is not 2 (so, 1 or 3)
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"}}