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

array 1

is then transposed,

array 2

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 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)


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"}}

Tags:

Code Golf