Generating combinations without recursion

3

Given a list of strings and a length, give all combinations of that list with the given length. The problem is: your code must not be recursive. Yes, it can be done. I have done it myself, when I had no clue what this "recursion" was.

Input: A list of strings of an undefined length, and an integer defining the length of the combination. The strings will be at least one character long, and will only contain letters or numbers. The way of input will be specified by you, the programmer.

Output: A list of possible combinations as strings, not necessarily distinct (although you can make it that way, if you like). You do not have to sort the list.

Test Cases: As said before, the method of input will be specified by you.
[a,b] 3 -> Nothing
[1,0,0] 2 -> 10 10 00, or 00 10 if distinct.
[abc,bcd,cde] 2 -> abcbcd abccde bcdcde

If you even manage to do this, I will commend you. As always, shortest code wins. Good luck.

beary605

Posted 2012-06-16T07:23:22.587

Reputation: 3 904

Question was closed 2019-01-05T15:01:12.010

5what does "without recursion" mean in this context? can you use a while loop? for loop? context would be helpful here... – Jeff – 2012-06-16T07:45:29.930

If I look at your third test case, it seems that you care about the order. Is cdeabc a valid combination? – Howard – 2012-06-16T08:45:39.160

Yes it is. Why not? – beary605 – 2012-06-16T09:27:25.050

2@beary605 Because your test case says it is not. – Howard – 2012-06-16T09:55:21.620

1Are we permitted to assume that none of the input strings are empty or contain newlines? – Peter Taylor – 2012-06-16T10:01:12.423

Yep. Hehe, how would you input newlines? – beary605 – 2012-06-16T14:08:29.970

@rhymingorange Ehehe, recursion is when you call a function in itself. – beary605 – 2012-06-17T01:34:06.563

@beary605 I understand what recursion is. it's just that you can do the equivalent of recursion using a while loop with very little difficulty. Just trying to tease out the "spirit" of the problem. – Jeff – 2012-06-17T05:13:14.603

@rhymingorange It depends on the recursive algorithm, but yeah, that's true. – beary605 – 2012-06-17T05:41:43.123

To howards question: Shall we ignore the order of elements? So for example 3: abc-bcd = bcd-abc? – user unknown – 2012-06-18T04:24:45.653

Yep, whatever goes. As long as you have them all in there. – beary605 – 2012-06-18T04:27:05.990

Not all languages have to offer looping constructs other than explicit recursion. – dfeuer – 2019-03-06T04:51:14.440

Answers

5

GolfScript (44 42 32 chars)

n%){\,=}+[[]]@1/{`{1$+}+%}%;\,n*

This takes input on stdin as a list of newline-separated strings followed by a line containing the desired subset size. It assumes that none of the input strings is empty. It takes some inspiration from Howard's solution, and can be shortened by two chars if using his input format:

~{\,=}+[[]]@1/{`{1$+}+%}%;\,n*

Output is a newline separated list of concatenations.

E.g.

$ golfscript.rb subcombo.gs <<END
> a
> b
> c
> 2
> END
ab
ac
bc

Note: this uses a horribly inefficient algorithm. A much nicer implementation in terms of performance is (62 61 chars)

n%)~\:S;2\?({2S,?<}{:s.~)&.s+.s^@4*/|}/{:x;S{;x.2/:x;1&},}%n*

which uses Gosper's hack.

Peter Taylor

Posted 2012-06-16T07:23:22.587

Reputation: 41 901

How do you even stumble across such obscure programming nuggets? – Gareth – 2012-06-16T11:16:26.850

@Gareth, I was taught this one by Arthur Norman. It's part of a collection of interesting titbits called HAKMEM.

– Peter Taylor – 2012-06-16T19:11:19.887

Answer to you! You are pretty much the only answerer, other than the other GolfScript, that didn't use a built-in combo generator. – beary605 – 2012-06-19T02:03:55.803

4

GolfScript, 33 35 34 characters

~[[]]@{\{.[2$]+.,4$={puts}*}%\}%];

Assumes that the input is list of strings and number in GolfScript compatible format (on STDIN). Example:

> ["abc" "bcd" "cde"] 2
abcbcd
bcdcde
abccde

You can also test this version online.

Edit: The first version was broken.

Howard

Posted 2012-06-16T07:23:22.587

Reputation: 23 109

puts? Seriously? – Peter Taylor – 2012-06-17T21:35:55.633

@PeterTaylor Maybe I don't understand you correctly, but why not? Btw I just noticed that we can save a char and get rid of the dot. – Howard – 2012-06-18T05:09:29.717

It's so long that I think its only purpose is debugging. You can save two more chars by ditching puts and just filtering the list to ones of the right length: ~[[]]@{\{.[2$]+}%\}%;{,1$=},\;n* – Peter Taylor – 2012-06-18T06:28:09.277

4

Mathematica, 21

""<>##&@@@Subsets@##&

Usage:

""<>##&@@@Subsets@##&[{"a", "b", "c", "d"}, {3}]

{"abc", "abd", "acd", "bcd"}

Mr.Wizard

Posted 2012-06-16T07:23:22.587

Reputation: 2 481

My goodness, that's really compact. – DavidC – 2012-07-26T17:00:15.677

3

Mathematica, 34 30 24 characters

StringJoin@@@Subsets@@#&

where i is input consisting of a list of the strings and the length of combinations. For example,

k = {{"abc", "bcd", "cde"},{2}};
StringJoin@@@Subsets@@#&[k]

(* out *)
{"abcbcd", "abccde", "bcdcde"}

Additional examples:

d = {"a", "b", "cd", "e", "fgh"}
m = {d, {2}}
n = {d, {3}}
p = {d, {4}}

StringJoin@@@Subsets@@#&[m]
StringJoin@@@Subsets@@#&[n]
StringJoin@@@Subsets@@#&[p]
(* out *)
{"ab", "acd", "ae", "afgh", "bcd", "be", "bfgh", "cde", "cdfgh", "efgh"}
{"abcd", "abe", "abfgh", "acde", "acdfgh", "aefgh", "bcde", "bcdfgh", "befgh", "cdefgh"}
{"abcde", "abcdfgh", "abefgh", "acdefgh", "bcdefgh"}

DavidC

Posted 2012-06-16T07:23:22.587

Reputation: 24 524

1Ha! Mma beating golfscript and J ... :D – Dr. belisarius – 2012-06-19T00:44:01.317

1

J, 50 48 46 44 43 41 35 characters

;"1(>@{:{."1(i.@!@#A.])@}:)".1!:1[1

Takes input from the keyboard. I've changed the input format from previous answers. Strings should come first, single-quoted, and separated by semi-colons, followed by the integer.

   ;"1(>@{:{."1(i.@!@#A.])@}:)".1!:1[1
'hello';'mr';'wibble';2
hellomr
hellowibble
mrhello
mrwibble
wibblehello
wibblemr

Entering a number larger than the largest possible combination just gives the largest possible combination:

   ;"1(>@{:{."1(i.@!@#A.])@}:)".1!:1[1
hello mr wibble 8
hellomrwibble
hellowibblemr
mrhellowibble
mrwibblehello
wibblehellomr
wibblemrhello

Gareth

Posted 2012-06-16T07:23:22.587

Reputation: 11 678

1

Scala 52

Not a challenge - know your API:

def c(l:Seq[_],n:Int)=l combinations n mkString "\n"

invocation sample:

scala> c(Seq("foo", "bar", "foobar"), 2)
res199: String = 
List(foo, bar)
List(foo, foobar)
List(bar, foobar)

Now beary605 observes that he didn't thought about library methods combinations, so I come up with this one, which doesn't use combinations, but maybe he now will come up with a permutation prohibition.

Scala 63 (without literal combinations method):

def c(l:Seq[_],n:Int)=l.permutations.map(_.take(2).toSet).toSet

user unknown

Posted 2012-06-16T07:23:22.587

Reputation: 4 210

Hehe, I should have added "no using built-in combo functions", but oh well. – beary605 – 2012-06-18T05:13:04.887

@beary605: Posted an alternative solution. Now you prohibit permutation, :) then map, then println? – user unknown – 2012-06-19T01:48:03.777

Hahaha. Very clever. ;) – beary605 – 2012-06-19T02:03:00.127

1

Java, 208 characters

No imports, two method calls, so it should be pretty guaranteed that there are no implisit recursive calls neither.

class S{public static void main(String[]a){int n=a.length-1,k=Integer.parseInt(a[0]),i=0,j;while(++i<1<<n)if(Integer.bitCount(i)==k){String s="";for(j=0;j<n;)if((i&1<<j++)!=0)s+=a[j];System.out.println(s);}}}

Slightly more readable:

class S{
    public static void main(String[]a){
        int n=a.length-1,k=Integer.parseInt(a[0]),i=0,j;
        while(++i<1<<n)
            if(Integer.bitCount(i)==k){
                String s="";
                for(j=0;j<n;)
                    if((i&1<<j++)!=0)
                        s+=a[j];
                System.out.println(s);
            }
    }
}

Takes input from command line arguments. First arg is the length and the rest is the strings. Outputs each combination on a separate line:

$ java S 3 A B C D
ABC
ABD
ACD
BCD

daniero

Posted 2012-06-16T07:23:22.587

Reputation: 17 193