```"Harry Ohlsen" <harryo / qiqsolutions.com> schrieb im Newsbeitrag
news:40A41302.9090307 / qiqsolutions.com...
> Robert Klemme wrote:
>
> > Ah, similar idea but nicer coding.
>
> Coming from you, that's a much appreciated compliment!

You're welcome! :-)

> > I like especially your calculation of
> > the counting range and int[idx] as bit test.  I didn't know that one.
>
> I discovered during a re-browse of pickaxe a couple of months ago, but
this is the first time I've actually had a chance to use it.
>
> > Btw, you don't need the test for length 0 if you do
> >
> > for n in 1 ... (2<<length) do
>
> Good point.
>
> Something I was thinking about was that the power set (set of subsets)
becomes large very quickly (obvious from the "2 << length", I guess).  It
might be nice to have an iterator, too.  The method that returns the
collection of subsets could then just use it.

Another good point!

> Something like this (I've removed the empty set test, since I think this
is cleaner in a mathematical sense) ...

That might be handled by an additional flag with a default value (which
one, the mathematical or the practical?).  Practically you often don't
need / want the empty set.

Funny to see how this evolves.  My current vesion looks like this:

module Enumerable
def each_subset(skip_empty = false)
for n in (skip_empty ? 1 : 0) ... (1 << size) do
subset = []

each_with_index do |elem, i|
subset << elem if n[i]
end

yield subset
end

self
end

def powerset(skip_empty = false)
subsets = []

each_subset(skip_empty) { |s| subsets << s }

return subsets
end
end

Changes / Improvements:

- self[index] is not used since it is not available with all Enumerables
- self returned from iterator
- renamed #subsets to #powerset (this is the mathematical correct term,
isn't it)
- changed (2 << length - 1) to (1 << length)

Here's another experimental version that works even if #size is not
supported.  This really needs only #each.  Alternatively one could do an
initial iteration to calculate the size - that saves the intermediate
array.

module Enumerable
def each_subset(skip_empty = false)
enum = respond_to?( :size ) ? self : to_a

for n in (skip_empty ? 1 : 0) ... (1 << enum.size) do
subset = []

enum.each_with_index do |elem, i|
subset << elem if n[i] == 1
end

yield subset
end

self
end

def powerset(skip_empty = false)
subsets = []

each_subset(skip_empty) { |s| subsets << s }

return subsets
end
end

# test class
class Test
include Enumerable

def initialize(n); @n=n; end
def each; @n.times {|c| yield c}; self; end
end

p Test.new(3).powerset

Kind regards

robert

```