つまり、
A =\{a_0,..,a_n\}\\
B \subseteq A\\
\forall B(B \in f(A))
となる関数$f(A)$を作ります。
但し、$A=\phi$ のとき $f(A)=\{\phi\}$ としています。
def getSubsets = {l->
if(!l) return [[]]
def ss = []
def x = Integer.parseInt(('1' * l.size()),2)
for(int y=x;y>0;y=--y&x){
def s = []
Integer.toBinaryString(y).padLeft(8, '0').reverse().eachWithIndex{flg,idx->
if(flg=='1') s << l[idx]
}
ss << s
}
ss
}
ビット演算y=--y&x
がこの計算の要旨で、これはビットの部分集合を得ます。
よくわからない場合は真偽表でも書いて確かめてみてください。
リストのサイズのBit表現の部分集合の逆順リストのフラグ位置を求めることで、任意のリストの部分集合を得られます。
groovy> def list = [1,2,3]
groovy> getSubset(list)
Result: [[1, 2, 3], [2, 3], [1, 3], [3], [1, 2], [2], [1]]
なお、わかると思いますが、この関数に長いリストを叩き込むと出力がどエライことになります。
部分集合を引数としてとるクロージャを引数として取る関数にして、それぞれの部分集合に対する(返却すべき)演算結果のリストを返すくらいにしておいたほうが無難だと思います。