<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>davinci’s notebook &#187; power set</title>
	<atom:link href="http://stargrads.net/blogs/davinci/tag/power-set/feed/" rel="self" type="application/rss+xml" />
	<link>http://stargrads.net/blogs/davinci</link>
	<description>everything is an experiment</description>
	<lastBuildDate>Mon, 21 Mar 2011 18:31:14 +0000</lastBuildDate>
	<language>fa</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>Programming exercise: combinations of a string</title>
		<link>http://stargrads.net/blogs/davinci/2009/10/programming-exercise-combinations-of-a-string/</link>
		<comments>http://stargrads.net/blogs/davinci/2009/10/programming-exercise-combinations-of-a-string/#comments</comments>
		<pubDate>Wed, 07 Oct 2009 18:13:27 +0000</pubDate>
		<dc:creator>davinci</dc:creator>
				<category><![CDATA[programming and technical issues]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[characters]]></category>
		<category><![CDATA[chars]]></category>
		<category><![CDATA[combinations]]></category>
		<category><![CDATA[comparison of programming languages]]></category>
		<category><![CDATA[map]]></category>
		<category><![CDATA[permutations]]></category>
		<category><![CDATA[power set]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[programming exercises]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[recursion]]></category>
		<category><![CDATA[Scheme]]></category>
		<category><![CDATA[strings]]></category>

		<guid isPermaLink="false">http://stargrads.net/blogs/davinci/?p=2290</guid>
		<description><![CDATA[
The problem is to implement a function that outputs all possible combinations of the characters in a string (with length ranging from one to the length of the string). Unlike permutations, two combinations are considered to be the same if they contain the same characters, but in a different order. Another way to define the [...]
]]></description>
			<content:encoded><![CDATA[<p>The problem is to implement a function that outputs all possible <a href="http://en.wikipedia.org/wiki/Combinations">combinations</a> of the characters in a string (with length ranging from one to the length of the string).  Unlike <a href="http://en.wikipedia.org/wiki/Permutations">permutations</a>, two combinations are considered to be the same if they contain the same characters, but in a different order.  Another way to define the problem is to find the <a href="http://en.wikipedia.org/wiki/Power_set">power set</a> of the characters of the string (excluding the empty set).</p>
<p>Like the previous exercise, this one is also from the book <a href="http://www.amazon.ca/gp/product/047012167X?ie=UTF8&amp;tag=davincisnoteb-20&amp;linkCode=as2&amp;camp=15121&amp;creative=330641&amp;creativeASIN=047012167X"><i>Programming Interviews Exposed</i></a><img src="http://www.assoc-amazon.ca/e/ir?t=davincisnoteb-20&amp;l=as2&amp;o=15&amp;a=047012167X" width="1" height="1" border="0" alt="" style="border:none !important;margin:0px !important" /> by John Mongan and Noah Suojanen<sup><a class='footnote' id='note-2290-1' href='#footnote-2290-ms00pie'>[1]</a></sup>\(\)<span id="more-2290"></span>.<!--adsensestart--></p>
<p>To begin with, let&#8217;s consider an example.  What are the combinations of the string &#8220;abcde&#8221;?  Since the ordering of the letters within the combinations don&#8217;t matter, let&#8217;s keep the letters in the same order as in the original string.  Also, for now, let&#8217;s include the empty string as one of the combinations, for simplicity.  Then it&#8217;s clear that there are \(2^{5} = 32\) combinations, since each of the \(5\) letters can be either included or excluded.  (For an input string of length \(n\), there will be \(2^{n}\) combinations, including the empty string.)<!--adsensestop--></p>
<p>The letter &#8220;a&#8221; will be included in half of the combinations, and excluded in the other half.  (Of course, this is also true of each of the other letters.)  In fact, those combinations that exclude &#8220;a&#8221; are just the combinations of the string &#8220;bcde&#8221;, and those that include &#8220;a&#8221; are exactly these same combinations, but prefixed with &#8220;a&#8221;.  This gives an obvious recursive solution to the problem.</p>
<p>Expressed in Scheme, the program looks like this:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="code"><pre class="scheme" style="font-family:monospace;"><span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">define</span> <span style="color: #66cc66;">&#40;</span>power<span style="color: #66cc66;">-</span>set the<span style="color: #66cc66;">-</span>set<span style="color: #66cc66;">&#41;</span>
    <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">null?</span> the<span style="color: #66cc66;">-</span>set<span style="color: #66cc66;">&#41;</span> '<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
        <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#40;</span> <span style="color: #66cc66;">&#40;</span>power<span style="color: #66cc66;">-</span>set<span style="color: #66cc66;">-</span>of<span style="color: #66cc66;">-</span>subset <span style="color: #66cc66;">&#40;</span>power<span style="color: #66cc66;">-</span>set <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">cdr</span> the<span style="color: #66cc66;">-</span>set<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> 
               <span style="color: #66cc66;">&#40;</span>prepend<span style="color: #66cc66;">-</span>excluded <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">lambda</span> <span style="color: #66cc66;">&#40;</span>subset<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">cons</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">car</span> the<span style="color: #66cc66;">-</span>set<span style="color: #66cc66;">&#41;</span> subset<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span>
             <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">append</span>
                power<span style="color: #66cc66;">-</span>set<span style="color: #66cc66;">-</span>of<span style="color: #66cc66;">-</span>subset
                <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">map</span> prepend<span style="color: #66cc66;">-</span>excluded power<span style="color: #66cc66;">-</span>set<span style="color: #66cc66;">-</span>of<span style="color: #66cc66;">-</span>subset<span style="color: #66cc66;">&#41;</span> 
             <span style="color: #66cc66;">&#41;</span> 
        <span style="color: #66cc66;">&#41;</span>
    <span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">define</span> <span style="color: #66cc66;">&#40;</span>combinations the<span style="color: #66cc66;">-</span><span style="color: #b1b100;">string</span><span style="color: #66cc66;">&#41;</span>
    <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">map</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">lambda</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">s</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#40;</span>apply <span style="color: #b1b100;">string</span> <span style="color: #b1b100;">s</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> 
         <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">cdr</span> <span style="color: #66cc66;">&#40;</span>power<span style="color: #66cc66;">-</span>set <span style="color: #66cc66;">&#40;</span>string<span style="color: #66cc66;">-&amp;</span>gt<span style="color: #808080; font-style: italic;">;list the-string))) )</span>
<span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">define</span> test<span style="color: #66cc66;">-</span>input <span style="color: #ff0000;">&quot;abcde&quot;</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">display</span> <span style="color: #66cc66;">&#40;</span>combinations test<span style="color: #66cc66;">-</span>input<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></pre></td></tr></table></div>

<p>The <code>combinations</code> function just converts the input string to a list of letters, applies <code>power-set</code> to the list, and converts the result back into a list of strings.  (The empty set is excluded by applying <code>cdr</code>, since it is the first item in the list returned by <code>power-set</code> by design.)</p>
<p>The <code>power-set</code> function is pretty straightforward.  It computes the power set of the subset that excludes the first letter (with a recursive call), then returns a set consisting of the elements of this power set along with these elements prepended with the excluded letter.  The base case is slightly tricky: the power set of the empty set is not the empty set, but a set containing only the empty set.  </p>
<p>(Aside: I wish that the higher-order functions <a href="http://en.wikipedia.org/wiki/Map_(higher-order_function)">map</a> and <a href="http://en.wikipedia.org/wiki/Fold_(higher-order_function)">fold/reduce</a> had better names &#8212; especially &#8220;map&#8221;, a word that is used for just too many things.)</p>
<p>The same program can be written in Python as follows:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> combinations<span style="color: black;">&#40;</span>input_string<span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> combinations_helper<span style="color: black;">&#40;</span>set_of_chars<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> set_of_chars == <span style="color: #483d8b;">&quot;&quot;</span>:
            <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;&quot;</span><span style="color: black;">&#93;</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            combinations_of_subset = combinations_helper<span style="color: black;">&#40;</span>set_of_chars<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>:<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
            combinations_of_subset.<span style="color: black;">extend</span><span style="color: black;">&#40;</span>
                <span style="color: #008000;">map</span><span style="color: black;">&#40;</span> <span style="color: #ff7700;font-weight:bold;">lambda</span> t: set_of_chars<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> + t, combinations_of_subset<span style="color: black;">&#41;</span>
            <span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> combinations_of_subset
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">return</span> combinations_helper<span style="color: black;">&#40;</span>input_string<span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>:<span style="color: black;">&#93;</span>
&nbsp;
test_input = <span style="color: #483d8b;">&quot;abcde&quot;</span>
<span style="color: #ff7700;font-weight:bold;">print</span> combinations<span style="color: black;">&#40;</span>test_input<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>The Python program uses string manipulation operations (string slicing, concatenation) instead of treating the input as a list as the Scheme program does.  The idea, however, is exactly the same.</p>
<p>There are probably more efficient ways to write these programs in these languages.  In particular, the conversions between strings and lists (in Scheme) and the string manipulation operations (in Python) may be expensive.  </p>
<p>What I like about the <em>idea</em> behind the above programs is that the result of the computation for the combinations excluding a character are re-used when computing the combinations including it.  This saves on a lot of recursive calls.</p>
<p>The &#8220;obvious&#8221; solution to the same problem in C++ is the following:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include&amp;lt;iostream&amp;gt;</span>
<span style="color: #339900;">#include&amp;lt;string.h&amp;gt;</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">void</span> print_combinations_helper<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>input, <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>output, 
    <span style="color: #0000ff;">int</span> len, <span style="color: #0000ff;">int</span> depth, <span style="color: #0000ff;">int</span> start<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #666666;">// The variable depth holds the recursion depth, or, equivalently, </span>
    <span style="color: #666666;">// the index into the output string of the character that's being</span>
    <span style="color: #666666;">// generated.  The variable start is the index of the first of</span>
    <span style="color: #666666;">// the still available letters.</span>
&nbsp;
    <span style="color: #666666;">// At the current depth, cycle through the still available letters.</span>
    <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span> <span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> start<span style="color: #008080;">;</span> i <span style="color: #000040;">&amp;</span>lt<span style="color: #008080;">;</span> len<span style="color: #008080;">;</span> i<span style="color: #000040;">++</span> <span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        output<span style="color: #008000;">&#91;</span>depth<span style="color: #008000;">&#93;</span> <span style="color: #000080;">=</span> input<span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
        print_combinations_helper<span style="color: #008000;">&#40;</span>input, output, len, depth<span style="color: #000040;">+</span><span style="color: #0000dd;">1</span>, i<span style="color: #000040;">+</span><span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    output<span style="color: #008000;">&#91;</span>depth<span style="color: #008000;">&#93;</span> <span style="color: #000080;">=</span> <span style="color: #FF0000;">'\ 0'</span><span style="color: #008080;">;</span>
    <span style="color: #0000dd;">cout</span> <span style="color: #000040;">&amp;</span>lt<span style="color: #008080;">;</span><span style="color: #000040;">&amp;</span>lt<span style="color: #008080;">;</span> output <span style="color: #000040;">&amp;</span>lt<span style="color: #008080;">;</span><span style="color: #000040;">&amp;</span>lt<span style="color: #008080;">;</span> endl<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">void</span> print_combinations<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>input<span style="color: #008000;">&#41;</span> 
<span style="color: #008000;">&#123;</span>
    <span style="color: #666666;">// Allocate a new character buffer to hold the output.  (Assume </span>
    <span style="color: #666666;">// that this always succeeds, or that error handling is being</span>
    <span style="color: #666666;">// taken care of elsewhere.)</span>
    <span style="color: #0000ff;">int</span> len <span style="color: #000080;">=</span> <span style="color: #0000dd;">strlen</span><span style="color: #008000;">&#40;</span>input<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>output <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> <span style="color: #0000ff;">char</span><span style="color: #008000;">&#91;</span>len<span style="color: #000040;">+</span><span style="color: #0000dd;">1</span><span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #666666;">// Recursively print the combinations, starting with the first</span>
    <span style="color: #666666;">// character.</span>
    print_combinations_helper<span style="color: #008000;">&#40;</span>input, output, len, <span style="color: #0000dd;">0</span>, <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #666666;">// Free the memory for the output buffer.</span>
    <span style="color: #0000dd;">delete</span> output<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> 
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">char</span> test_input<span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span> <span style="color: #000080;">=</span> <span style="color: #FF0000;">&quot;abcde&quot;</span><span style="color: #008080;">;</span>
    print_combinations<span style="color: #008000;">&#40;</span>test_input<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>The above program actually also prints out the empty string as one of the combinations, but this can be easily fixed by an <code>if</code> clause, or by relocating the <code>cout</code> statement (lines 18&#8211;19) inside the loop (at line 16, and substituting <code>depth+1</code> for <code>depth</code>).  The reason that I didn&#8217;t write the program that way is because then the combinations would have been output in a very different order compared to the above Scheme/Python programs.  (The way it&#8217;s written now, the output is actually in exactly the reverse order, but that&#8217;s good enough for comparison purposes.)</p>
<p>While the recursive function is called only \(n+1\) times in the Scheme/Python programs (once for each character and once more for the empty set), the C++ program makes a total of \(2^{n}\) calls to the recursive helper function.  On the other hand, while the Scheme/Python programs have to keep \(2^{n}\) items in memory (each of which is \(O(n)\) in size), the C++ program prints each combination as soon as it has been computed and thus uses only \(O(n)\) memory.  </p>
<p>Personally, I prefer the solution used in the Scheme program because I find it conceptually much more elegant.  It would also be preferably if recursive function calls are expensive for some reason.  However, the solution used in the C++ program is better if memory is limited, or if the combinations do not need to be retained in memory after they have been printed.  </p>
<p>Of course, one can write the first program in C++ or the second one in Scheme, but the point is that the two solutions are, in some sense, the more &#8220;natural&#8221; ones for their respective languages.</p>
<p>&#8211; davinci 11803</p>
<img src="http://stargrads.net/blogs/davinci/?ak_action=api_record_view&id=2290&type=feed" alt="" /><p>Related posts:<ol>
<li><a href='http://stargrads.net/blogs/davinci/2009/10/programming-exercise-permutations-of-a-string/' rel='bookmark' title='Programming exercise: permutations of a string'>Programming exercise: permutations of a string</a></li>
<li><a href='http://stargrads.net/blogs/davinci/2009/09/programming-exercise-hello-world/' rel='bookmark' title='Programming exercise: Hello, world!'>Programming exercise: Hello, world!</a></li>
<li><a href='http://stargrads.net/blogs/davinci/2009/09/programming-exercise-maximum-value-in-integer-array-part-1/' rel='bookmark' title='Programming exercise: maximum value in integer array, part 1'>Programming exercise: maximum value in integer array, part 1</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://stargrads.net/blogs/davinci/2009/10/programming-exercise-combinations-of-a-string/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

