```On 2006-12-19 22:10:13 -0500, James Cunningham
<jameshcunningham / gmail.com> said:

> As part of my first-ever submission to the ruby quiz, I wrote
> (translated from Python, really) a recursive routine to return all
> n-combinations of an array. So that:
>
> combinations([1, 2, 3], 2)
>
> would return
>
> [[1, 2], [1, 3], [2, 3]]
>
> and combinations([1, 2, 3], 2, false)
>
> would return
>
> [[1, 2], [1, 3], [2, 3], [2, 1], [3, 1], [3, 2]]
>
> My original code was as follows (with some stupid corrections):
>
> def combinations sequence, n, unique=true
>   return [] if n == 0
>   return sequence if n == 1
>   result = []
>
>   0.upto(sequence.length - 1) do |i|
>     sub_sequence = sequence[(i + 1)..-1]
>     sub_sequence += sequence[0..i] if not unique
>
>     combinations(sequence[(i + 1)..-1], n - 1).each do |smaller|
>       result << [sequence[i]] + smaller
>     end
>   end
>
>   result
> end
>
> But this gives a "TypeError: can't convert Fixnum into Array", from the
> line "result << [sequence[i]] + smaller". After a few minutes of
> scratching my head, it became clear that sometimes the result of
> combinations(...) was an Array (which is expected) and sometimes it was
> of type whatever the array elements were (which is unexpected),
> whenever the array would be a singleton.
>
> I ended up changing it to "result << ([sequence[i]] +
> [smaller]).flatten", but after I turned it in I realized that won't do
> - I'd want the code to handle cases where elements of the array are
> themselves arrays. I added the check "smaller = [smaller] if
> smaller.class != Array", but it doesn't *seem* like I should have to do
> that.
>
> Where am I going wrong here?
>
> Best,
> James Cunningham

Okay. It occurs to me that I was wrong in two respects.

Even with the change of adding "smaller = [smaller] if smaller.class !=
Array", I still get weird flattening.

combinations([1, 2, [3, 4]], 2)

should return

[[1, 2], [1, [3, 4]], [2, [3, 4]]]

[[1, 2], [1, 3, 4], [2, 3, 4]]

Also, combinations([1, 2, 3], 2, false) doesn't do what I'd expect: as
far as I can tell it should collect all 2-permutations, but it has the
same effect as combinations([1, 2, 3], 2).

For reference, here's the Python code that seems to work in the way I describe:

def combinations(sequence, n, unique=True):
if not n: yield []

for i in range(len(sequence)):
sub_sequence = sequence[i + 1:]
if not unique: sub_sequence += sequence[:i]

for smaller in combinations(sub_sequence, n - 1, unique):
yield [sequence[i]] + smaller

Best,
James

```