<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[BitSubsetIterator - Feedback?]]></title><description><![CDATA[<p>Hi,</p>
<p>ich brauchte einen Iterator, der bei einer gegebenen Zahl alle Untermengen durchläuft. Level-Order ist wichtig (also bei einer Zahl immer erst alle Zahlen anzeigen, bei denen nur ein Bit wegfällt), aber auf einem Level ist die Reihenfolge egal.</p>
<p>Wenn ich also eine Bitfolge 11100 habe, soll er mir 11100 ausgeben, danach 11000, 10100, 01100 ausgeben und daraufhin 10000, 01000, 00100. Wobei &quot;Ausgabe&quot; wieder eine Zahl ist, also kein String mit '0' und '1' oder so.</p>
<p>Nun habe ich vorher nie Iteratoren geschrieben und meine Frage ist einfach:</p>
<p>&quot;<em>Habt ihr generelle Kommentare/Vorschläge?</em>&quot;</p>
<p>Insbesodnere frage ich mich, ob man sich von einem Iterator noch mehr wünscht und ob die Abfrage aufs Ende mit <code>atEnd()</code> schön gelöst ist. Da der zu Grunde liegende Typ nativ ist, kann er kein begin() und end() anbieten oder würdet ihr dafür freie Funktionen gestalten?</p>
<p>Falls nichts kommt, weil keiner Lust hat den Code durchzuschauen, kann ich das verstehen. Dennoch wollte ich Mal gefragt haben. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f60b.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_savoring_food"
      title=":yum:"
      alt="😋"
    /></p>
<p>Ich muss wohl dazu sagen, dass topBits eine Lookup-Table ist, die ich zufällig zur Hand habe. Die muss natürlich zu T passen, weswegen man eine entsprechende Abfrage vorher bräuchte.</p>
<pre><code class="language-cpp">#ifndef BIT_SUBSET_ITERATOR
#define BIT_SUBSET_ITERATOR

#include &lt;iterator&gt;
#include &lt;vector&gt;
#include &lt;set&gt;
#include &lt;boost/foreach.hpp&gt;
#include &quot;topBits.hpp&quot;

namespace Utils
{
	template&lt;typename T&gt;
	class BitSubsetIterator :
		public std::iterator&lt;std::input_iterator_tag, typename T&gt;
	{
	public:
		typedef std::set&lt;typename T&gt; TreeLevel;
		typedef std::vector&lt;TreeLevel&gt; TreeLevels;
		typedef typename TreeLevels::const_iterator TreeLevelsIterator;
		typedef typename TreeLevel::const_iterator TreeLevelIterator;

		BitSubsetIterator(T bits);
		BitSubsetIterator&amp; operator++();
		BitSubsetIterator operator++(int);
		typename const T&amp; operator*() const;
		bool atEnd() const;

	private:
		void createTreeLevels(T bits);
		TreeLevel&amp; getTreeLevel(unsigned int level);
		void insertFirstSubsetsIntoLevel(T bits, unsigned int levelNumber);

		TreeLevelsIterator currentLevel;
		TreeLevelIterator currentIndex;

		TreeLevels treeLevels;
	};

	// ===================================================

	template&lt;typename T&gt;
	typename const T&amp; BitSubsetIterator&lt;T&gt;::operator*() const
	{
		return *currentIndex;
	}

	// ===================================================

	template&lt;typename T&gt;
	bool BitSubsetIterator&lt;T&gt;::atEnd() const
	{
		return currentLevel == treeLevels.end();
	}

	// ===================================================

	template&lt;typename T&gt;
	BitSubsetIterator&lt;T&gt; BitSubsetIterator&lt;T&gt;::operator++( int )
	{
		BitSubsetIterator&lt;T&gt; cpy(*this);
		++(*this); // korrigiert dank volkard
		return cpy;
	}

	// ===================================================

	template&lt;typename T&gt;
	BitSubsetIterator&lt;T&gt;&amp; BitSubsetIterator&lt;T&gt;::operator++()
	{
		if(currentLevel != treeLevels.end()) // if not at end
		{
			if(++currentIndex == currentLevel-&gt;end()) // increase index and
			{
				++currentLevel;
				if(currentLevel != treeLevels.end())
					currentIndex = currentLevel-&gt;begin(); // increase level and reset index
			}
		}

		return *this;
	}

	// ===================================================

	template&lt;typename T&gt;
	BitSubsetIterator&lt;T&gt;::BitSubsetIterator( T bits )
	{
		createTreeLevels(bits);

		currentLevel = treeLevels.begin();
		currentIndex = currentLevel-&gt;begin();
	}

	// ===================================================

	template&lt;typename T&gt;
	typename BitSubsetIterator&lt;T&gt;::TreeLevel&amp; BitSubsetIterator&lt;T&gt;::getTreeLevel(unsigned int level)
	{
		if(treeLevels.size() &lt; level + 1)
			treeLevels.resize(level + 1);

		return treeLevels[level];
	}

	// ===================================================

	template&lt;typename T&gt;
	void BitSubsetIterator&lt;T&gt;::insertFirstSubsetsIntoLevel(T bits, unsigned int levelNumber)
	{
		TreeLevel&amp; level = getTreeLevel(levelNumber);
		TreeLevel newLevelElements;

		T workNumber = bits;

		while(workNumber)
		{
			// erase current bit
			bits ^= topBits[workNumber];

			if(bits != 0)
			{
				// insert subset
				newLevelElements.insert(bits);
			}

			// reproduce bit
			bits ^= topBits[workNumber];
			// erase bit from workNumber
			workNumber ^= topBits[workNumber];
		}

		level.insert(newLevelElements.begin(), newLevelElements.end());

		// now, insert children's subsets
		BOOST_FOREACH(T subset, newLevelElements)
			insertFirstSubsetsIntoLevel(subset, levelNumber + 1);
	}

	// ===================================================

	template&lt;typename T&gt;
	void BitSubsetIterator&lt;T&gt;::createTreeLevels(T bits)
	{
		TreeLevel level0;
		level0.insert(bits);
		treeLevels.push_back(level0);

		insertFirstSubsetsIntoLevel(bits, 1);

		// last level will be empty
		treeLevels.pop_back();
	}
};

#endif
</code></pre>
<p>Herzlichen Dank und beste Grüße!</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/317088/bitsubsetiterator-feedback</link><generator>RSS for Node</generator><lastBuildDate>Wed, 29 Jul 2026 11:26:21 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/317088.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 27 May 2013 10:08:25 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to BitSubsetIterator - Feedback? on Mon, 27 May 2013 12:54:59 GMT]]></title><description><![CDATA[<p>Hi,</p>
<p>ich brauchte einen Iterator, der bei einer gegebenen Zahl alle Untermengen durchläuft. Level-Order ist wichtig (also bei einer Zahl immer erst alle Zahlen anzeigen, bei denen nur ein Bit wegfällt), aber auf einem Level ist die Reihenfolge egal.</p>
<p>Wenn ich also eine Bitfolge 11100 habe, soll er mir 11100 ausgeben, danach 11000, 10100, 01100 ausgeben und daraufhin 10000, 01000, 00100. Wobei &quot;Ausgabe&quot; wieder eine Zahl ist, also kein String mit '0' und '1' oder so.</p>
<p>Nun habe ich vorher nie Iteratoren geschrieben und meine Frage ist einfach:</p>
<p>&quot;<em>Habt ihr generelle Kommentare/Vorschläge?</em>&quot;</p>
<p>Insbesodnere frage ich mich, ob man sich von einem Iterator noch mehr wünscht und ob die Abfrage aufs Ende mit <code>atEnd()</code> schön gelöst ist. Da der zu Grunde liegende Typ nativ ist, kann er kein begin() und end() anbieten oder würdet ihr dafür freie Funktionen gestalten?</p>
<p>Falls nichts kommt, weil keiner Lust hat den Code durchzuschauen, kann ich das verstehen. Dennoch wollte ich Mal gefragt haben. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f60b.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_savoring_food"
      title=":yum:"
      alt="😋"
    /></p>
<p>Ich muss wohl dazu sagen, dass topBits eine Lookup-Table ist, die ich zufällig zur Hand habe. Die muss natürlich zu T passen, weswegen man eine entsprechende Abfrage vorher bräuchte.</p>
<pre><code class="language-cpp">#ifndef BIT_SUBSET_ITERATOR
#define BIT_SUBSET_ITERATOR

#include &lt;iterator&gt;
#include &lt;vector&gt;
#include &lt;set&gt;
#include &lt;boost/foreach.hpp&gt;
#include &quot;topBits.hpp&quot;

namespace Utils
{
	template&lt;typename T&gt;
	class BitSubsetIterator :
		public std::iterator&lt;std::input_iterator_tag, typename T&gt;
	{
	public:
		typedef std::set&lt;typename T&gt; TreeLevel;
		typedef std::vector&lt;TreeLevel&gt; TreeLevels;
		typedef typename TreeLevels::const_iterator TreeLevelsIterator;
		typedef typename TreeLevel::const_iterator TreeLevelIterator;

		BitSubsetIterator(T bits);
		BitSubsetIterator&amp; operator++();
		BitSubsetIterator operator++(int);
		typename const T&amp; operator*() const;
		bool atEnd() const;

	private:
		void createTreeLevels(T bits);
		TreeLevel&amp; getTreeLevel(unsigned int level);
		void insertFirstSubsetsIntoLevel(T bits, unsigned int levelNumber);

		TreeLevelsIterator currentLevel;
		TreeLevelIterator currentIndex;

		TreeLevels treeLevels;
	};

	// ===================================================

	template&lt;typename T&gt;
	typename const T&amp; BitSubsetIterator&lt;T&gt;::operator*() const
	{
		return *currentIndex;
	}

	// ===================================================

	template&lt;typename T&gt;
	bool BitSubsetIterator&lt;T&gt;::atEnd() const
	{
		return currentLevel == treeLevels.end();
	}

	// ===================================================

	template&lt;typename T&gt;
	BitSubsetIterator&lt;T&gt; BitSubsetIterator&lt;T&gt;::operator++( int )
	{
		BitSubsetIterator&lt;T&gt; cpy(*this);
		++(*this); // korrigiert dank volkard
		return cpy;
	}

	// ===================================================

	template&lt;typename T&gt;
	BitSubsetIterator&lt;T&gt;&amp; BitSubsetIterator&lt;T&gt;::operator++()
	{
		if(currentLevel != treeLevels.end()) // if not at end
		{
			if(++currentIndex == currentLevel-&gt;end()) // increase index and
			{
				++currentLevel;
				if(currentLevel != treeLevels.end())
					currentIndex = currentLevel-&gt;begin(); // increase level and reset index
			}
		}

		return *this;
	}

	// ===================================================

	template&lt;typename T&gt;
	BitSubsetIterator&lt;T&gt;::BitSubsetIterator( T bits )
	{
		createTreeLevels(bits);

		currentLevel = treeLevels.begin();
		currentIndex = currentLevel-&gt;begin();
	}

	// ===================================================

	template&lt;typename T&gt;
	typename BitSubsetIterator&lt;T&gt;::TreeLevel&amp; BitSubsetIterator&lt;T&gt;::getTreeLevel(unsigned int level)
	{
		if(treeLevels.size() &lt; level + 1)
			treeLevels.resize(level + 1);

		return treeLevels[level];
	}

	// ===================================================

	template&lt;typename T&gt;
	void BitSubsetIterator&lt;T&gt;::insertFirstSubsetsIntoLevel(T bits, unsigned int levelNumber)
	{
		TreeLevel&amp; level = getTreeLevel(levelNumber);
		TreeLevel newLevelElements;

		T workNumber = bits;

		while(workNumber)
		{
			// erase current bit
			bits ^= topBits[workNumber];

			if(bits != 0)
			{
				// insert subset
				newLevelElements.insert(bits);
			}

			// reproduce bit
			bits ^= topBits[workNumber];
			// erase bit from workNumber
			workNumber ^= topBits[workNumber];
		}

		level.insert(newLevelElements.begin(), newLevelElements.end());

		// now, insert children's subsets
		BOOST_FOREACH(T subset, newLevelElements)
			insertFirstSubsetsIntoLevel(subset, levelNumber + 1);
	}

	// ===================================================

	template&lt;typename T&gt;
	void BitSubsetIterator&lt;T&gt;::createTreeLevels(T bits)
	{
		TreeLevel level0;
		level0.insert(bits);
		treeLevels.push_back(level0);

		insertFirstSubsetsIntoLevel(bits, 1);

		// last level will be empty
		treeLevels.pop_back();
	}
};

#endif
</code></pre>
<p>Herzlichen Dank und beste Grüße!</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2326413</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2326413</guid><dc:creator><![CDATA[Eisflamme]]></dc:creator><pubDate>Mon, 27 May 2013 12:54:59 GMT</pubDate></item><item><title><![CDATA[Reply to BitSubsetIterator - Feedback? on Mon, 27 May 2013 12:28:00 GMT]]></title><description><![CDATA[<p>Eisflamme schrieb:</p>
<blockquote>
<p>&quot;<em>Habt ihr generelle Kommentare/Vorschläge?</em>&quot;</p>
</blockquote>
<p>Ist das so lahm, wie es aussieht?</p>
<p>Eisflamme schrieb:</p>
<blockquote>
<pre><code class="language-cpp">template&lt;typename T&gt;
	BitSubsetIterator&lt;T&gt; BitSubsetIterator&lt;T&gt;::operator++( int )
	{
		BitSubsetIterator&lt;T&gt; cpy(*this);
		++cpy;
		return cpy;
	}
</code></pre>
</blockquote>
<p>strange</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2326441</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2326441</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Mon, 27 May 2013 12:28:00 GMT</pubDate></item><item><title><![CDATA[Reply to BitSubsetIterator - Feedback? on Mon, 27 May 2013 12:33:52 GMT]]></title><description><![CDATA[<p>Keine Ahnung, ich dachte, so implementiert man operator++(int) generell. Erscheint mir auch lahm, aber der ist ja so definiert, dass er ne Kopie erstellt. Man könnte ihn höchstens verbieten, weil es wohl kaum Anwendungsfälle gibt, wo man ihn wirklich will.</p>
<p>Würdest Du den Iterator ansonsten gern für den Anwendungsfall, dass du das Resultat brauchst, nutzen? Oder ist der Dir zu unkomfortabel aus irgendeinem Grund?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2326443</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2326443</guid><dc:creator><![CDATA[Eisflamme]]></dc:creator><pubDate>Mon, 27 May 2013 12:33:52 GMT</pubDate></item><item><title><![CDATA[Reply to BitSubsetIterator - Feedback? on Mon, 27 May 2013 12:36:53 GMT]]></title><description><![CDATA[<p>Eisflamme schrieb:</p>
<blockquote>
<p>Keine Ahnung, ich dachte, so implementiert man operator++(int) generell. Erscheint mir auch lahm, aber der ist ja so definiert, dass er ne Kopie erstellt. Man könnte ihn höchstens verbieten, weil es wohl kaum Anwendungsfälle gibt, wo man ihn wirklich will.</p>
</blockquote>
<p>Das waren zwei verschiedene Themen bei mir.<br />
Der ganze Iterator sieht mir sehr lahm aus. Kaann mir nicht vorstellen, daß das so sein sollte.</p>
<p>Der op++(int), ja ich verbiete ihn gerne, andererseits, kein ernstzunehmender Programmierer benutzt den op++(int) statt des normalen, wenn er nicht echt unvermeidlich eine Kopie braucht. Nee, da meinte ich, warum erhöhst Du die Kopie statt *this? So klappt der doch gar nicht.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2326444</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2326444</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Mon, 27 May 2013 12:36:53 GMT</pubDate></item><item><title><![CDATA[Reply to BitSubsetIterator - Feedback? on Mon, 27 May 2013 12:40:06 GMT]]></title><description><![CDATA[<p>Ach ups, ja, der ist einfach falsch.</p>
<p>Wie würdest Du den Iterator schneller gestalten? Der hat halt Initialisierungsaufwand, danach ist er doch recht rasch.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2326445</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2326445</guid><dc:creator><![CDATA[Eisflamme]]></dc:creator><pubDate>Mon, 27 May 2013 12:40:06 GMT</pubDate></item><item><title><![CDATA[Reply to BitSubsetIterator - Feedback? on Mon, 27 May 2013 12:46:00 GMT]]></title><description><![CDATA[<p>Eisflamme schrieb:</p>
<blockquote>
<p>Wenn ich also eine Bitfolge 11100 habe, soll er mir 111 ausgeben, danach 110, 101, 011 ausgeben und daraufhin 100, 010, 001. Wobei &quot;Ausgabe&quot; wieder eine Zahl ist, also kein String mit '0' und '1' oder so.</p>
</blockquote>
<p>Verstehe ich nicht.<br />
Durch was fliegen die beiden Nullen am Ende gleich mal weg?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2326448</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2326448</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Mon, 27 May 2013 12:46:00 GMT</pubDate></item><item><title><![CDATA[Reply to BitSubsetIterator - Feedback? on Mon, 27 May 2013 12:48:31 GMT]]></title><description><![CDATA[<p>Auch das war ein Flüchtigkeitsfehler. Ich sollte meine Beiträge genauer probelesen. Also die Nullen bleiben, sonst wären das ja auch keine Untermengen der Ursprungszahl.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2326449</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2326449</guid><dc:creator><![CDATA[Eisflamme]]></dc:creator><pubDate>Mon, 27 May 2013 12:48:31 GMT</pubDate></item><item><title><![CDATA[Reply to BitSubsetIterator - Feedback? on Mon, 27 May 2013 13:05:40 GMT]]></title><description><![CDATA[<blockquote>
<p>bei einer gegebenen Zahl alle Untermengen durchläuft.</p>
</blockquote>
<p>Was sind die Untermengen einer Zahl?</p>
<blockquote>
<p>Bitfolge 11100 habe, soll er mir 11100 ausgeben, danach 11000, 10100, 01100 ausgeben und daraufhin 10000, 01000, 00100.</p>
</blockquote>
<p>Sind das alle oder warum darf keine 1 in die letzten beiden Bit.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2326452</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2326452</guid><dc:creator><![CDATA[knivil]]></dc:creator><pubDate>Mon, 27 May 2013 13:05:40 GMT</pubDate></item><item><title><![CDATA[Reply to BitSubsetIterator - Feedback? on Mon, 27 May 2013 16:41:07 GMT]]></title><description><![CDATA[<p>Na ja, war mir klar, dass das so formuliert falsch ist, aber ich dachte, das reicht zum Verständnis sinngemäß aus.</p>
<p>Betrachtet man eine Zahl als eine Kombination von Bits, könnte man sie als Menge schreiben der Form:<br />
{BIT1, BIT2, BIT5} für 10011</p>
<p>Hier von möchte ich alle Untermengen, die also entsprechend wären:<br />
{BIT1, BIT2} für 00011, {BIT1, BIT5} für 10001, {BIT2, BIT5} für 10010. Das nenne ich hier Level1, während Level2 ein zweites Bit abzieht, was sich somit darin äußert, dass nur ein Bit auf Level2 gesetzt ist.</p>
<p>Tatsächliche Ausgabe ist eine Zahl, die der entsprechenden Verknüpfung genannter Bits entspricht.</p>
<blockquote>
<p>Sind das alle oder warum darf keine 1 in die letzten beiden Bit.</p>
</blockquote>
<p>Ja, das sind alle. Die 1 darf nicht in das letzte Bit, weil diese Bits in der Ausgangszahl nicht besetzt sind und die Zahl somit nach obiger Repräsentation/Interpretation keine Obermenge einer Zahl wie 00010 darstellt. Nochmal: mir ist bewusst, dass eine Zahl keine (nicht-triviale? ich bin kein Mathematiker) Menge ist, das wollte ich einfach nur zur Veranschaulichung nutzen.</p>
<p>Man könnte auch sagen, ich suche alle x bei gegebenem y, sodass gilt: x BIT_AND y = x</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2326550</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2326550</guid><dc:creator><![CDATA[Eisflamme]]></dc:creator><pubDate>Mon, 27 May 2013 16:41:07 GMT</pubDate></item><item><title><![CDATA[Reply to BitSubsetIterator - Feedback? on Mon, 27 May 2013 19:27:59 GMT]]></title><description><![CDATA[<p>Du willst durch die Potenzmenge iterieren. D.h. 110010 -&gt; {1,2,5}. Weglassen bei Level 0: {}, Level 1: {1}, {2}, {5}, Level 2: {1,2}, {1,5}, {2, 5}, Level 3: {1,2,3}. Algorithmen zum erzeugen der Potenzmenge sollten beim iterieren helfen. Auch sind die Stellen mit 0 irrelevant, D.h. man kann von 111 ausgehen und beim generieren der Zahlen auf die Position mappen.</p>
<p>Suche dir eine Version heraus, die deine Ordnung (Levels) erzeugt: <a href="http://rosettacode.org/wiki/Power_set" rel="nofollow">http://rosettacode.org/wiki/Power_set</a> , beispielsweise kann man vielleicht in Clojure's subset Funktion nachsehen. Oder hier: <a href="http://www.martinbroadhurst.com/combinatorial-algorithms.html#power-set" rel="nofollow">http://www.martinbroadhurst.com/combinatorial-algorithms.html#power-set</a> , wo ein Ansatz ohne Container angerissen wird.</p>
<p>Gegenfrage: Wofuer brauchst du das?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2326603</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2326603</guid><dc:creator><![CDATA[knivil]]></dc:creator><pubDate>Mon, 27 May 2013 19:27:59 GMT</pubDate></item><item><title><![CDATA[Reply to BitSubsetIterator - Feedback? on Mon, 27 May 2013 21:45:19 GMT]]></title><description><![CDATA[<p>Super, vielen Dank. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
<p>Brauchen tue ich das mittlerweile nicht mehr. Es handelt sich um viele Flags, die mit Strings versehen werden. Kombiniert man Flags, erhält man jedoch u.U. andere Strings als String1 + String2. Es ist jedoch viel zweckdienlicher einfach die Strings mit ihren Bitkombinationen nach Anzahl der Bits zu sortieren und darüber zu iterieren. Die Potenzmenge ist einfach viel zu groß.</p>
<p>Aber ich wollte eben üben Mal einen Iterator zu schreiben.</p>
<p>Danke und beste Grüße, die Algorithmen für Potenzmengen schaue ich mir dennoch an!</p>
<p>Beste Grüße,<br />
Eisflamme</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2326675</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2326675</guid><dc:creator><![CDATA[Eisflamme]]></dc:creator><pubDate>Mon, 27 May 2013 21:45:19 GMT</pubDate></item><item><title><![CDATA[Reply to BitSubsetIterator - Feedback? on Mon, 27 May 2013 22:38:45 GMT]]></title><description><![CDATA[<p>Wenn Deine Reihenfolge nicht so komisch sein müßte, hätte ich was recht leckeres.</p>
<pre><code>Maske:
111010

Ausgabe:
111010
111000
110010
110000
101010
101000
100010
100000
11010
11000
10010
10000
1010
1000
10
</code></pre>
<pre><code>#include &lt;iostream&gt;

class BitSubsetGenerator{
    uint32_t bits;
    uint32_t mask;
public:
    BitSubsetGenerator(uint32_t bits)
    :bits(0)
    ,mask(bits){
    }
    uint32_t peek(){
        return bits^mask;
    }
    void pop(){
        bits=((bits|~mask)+1)&amp;mask;
    }
    bool isEmpty(){
        return bits==mask;
    }
};

struct bin{
    uint32_t n;
    explicit bin(uint32_t n)
    :n(n){
    }
    friend std::ostream&amp; operator&lt;&lt;(std::ostream&amp; out,bin b){
        if(b.n&gt;=2)
            out&lt;&lt;bin(b.n/2);
        return out&lt;&lt;char('0'+b.n%2);
    }
};

int main(){
   BitSubsetGenerator bsg(58);
   std::cout&lt;&lt;bin(58)&lt;&lt;'\n'&lt;&lt;'\n';
   while(!bsg.isEmpty()){
        std::cout&lt;&lt;bin(bsg.peek())&lt;&lt;'\n';
        bsg.pop();
   }
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2326683</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2326683</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Mon, 27 May 2013 22:38:45 GMT</pubDate></item><item><title><![CDATA[Reply to BitSubsetIterator - Feedback? on Mon, 27 May 2013 23:32:15 GMT]]></title><description><![CDATA[<p>Ja, muss halt Level-Order sein, weil 111 ja einen anderen Namen haben kann als string(110) + string(001).</p>
<p>Sonst aber echt super. Wie kommt man auf so was? Bin das schrittweise durchgegangen und sehe, dass es klappt, aber verstehen tue ich's nicht.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2326694</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2326694</guid><dc:creator><![CDATA[Eisflamme]]></dc:creator><pubDate>Mon, 27 May 2013 23:32:15 GMT</pubDate></item><item><title><![CDATA[Reply to BitSubsetIterator - Feedback? on Tue, 28 May 2013 04:14:02 GMT]]></title><description><![CDATA[<p>Eisflamme schrieb:</p>
<blockquote>
<p>Ja, muss halt Level-Order sein, weil 111 ja einen anderen Namen haben kann als string(110) + string(001).</p>
<p>Sonst aber echt super. Wie kommt man auf so was? Bin das schrittweise durchgegangen und sehe, dass es klappt, aber verstehen tue ich's nicht.</p>
</blockquote>
<p>Der Trick ist ganz einfach.</p>
<p>Grundmenge sei mal:<br />
111000110010001100</p>
<p>bits sei irgendwann<br />
???000??00?000??00</p>
<p>Jetzt will ich dafür sorgen, daß ich wenn ich das rechte Fragezeichen umklappe, daß dann wenn es von 0 nach 1 umklappt, war alles gut, aber wenn es von 1 nach 0 umklappt, soll es seinen linken Nachbarn umklappen. Also ganz normales binäres addieren. Klappt der linke Nachbar um von 1 nach 0, soll er wiederum seinen linken Nachbarn mitnehmen, nur daß der jetzt drei Stellen weiter links ist.<br />
Und das geht ganz einfach, ich baue eine Hühnerleiter aus zwangsgesetzten Bits!!!<br />
???000??00?000??00<br />
Dann setze ich die inverse Grundmenge rein<br />
???111??11?111??11<br />
Jetzt kann ich einfach das ganz rechte Bit mit +1 klappen und falls ein Überlauf von einem ? in eine Hühnerleiter reinfällt, trägt die Hühnerleiter ihn sicher auch wieder hinaus ins nächste ?.</p>
<p>Damit ist<br />
bits=((bits|~mask)+1)&amp;mask<br />
erklärt.</p>
<p>Jo, und die bits lasse ich bei 0 beginnen und bei Vollsein enden. Wegen +1 war das praktisch. Es hat nur mit +1 funktioniert, mit -1 nicht. Voll doof! Darum laufe ich aufwärts, und deswegen geschieht mit<br />
return bits^mask<br />
die Anzeige rückwärts.</p>
<p><img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/27a1.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--right_arrow"
      title=":arrow_right:"
      alt="➡"
    /> <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f4a1.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--light_bulb"
      title=":bulb:"
      alt="💡"
    /><br />
Haha, wie doof war das denn? Natürlich geht -1 auch. Dazu muss nur die Hühnerleiter aus 0-en bestehen. Das führt zu deutlich verbessertem Code.</p>
<pre><code>class BitSubsetGenerator{
    uint32_t bits;
    uint32_t mask;
public:
    BitSubsetGenerator(uint32_t bits)
    :bits(bits)
    ,mask(bits){
    }
    uint32_t peek(){
        return bits;
    }
    void pop(){
        bits=(bits-1)&amp;mask;
    }
    bool isEmpty(){
        return bits==0;
    }
};
</code></pre>
<p>Jo, da sehe ich jetzt nicht mehr viel Spielraum für Verbesserungen. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f921.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--clown_face"
      title=":clown:"
      alt="🤡"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2326713</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2326713</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Tue, 28 May 2013 04:14:02 GMT</pubDate></item><item><title><![CDATA[Reply to BitSubsetIterator - Feedback? on Tue, 28 May 2013 05:39:31 GMT]]></title><description><![CDATA[<p>Volkard unser Bitfriemler <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/2764.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--red_heart"
      title="&lt;3"
      alt="❤"
    /></p>
<p>Danke für dies Lehrstunde.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2326715</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2326715</guid><dc:creator><![CDATA[otze]]></dc:creator><pubDate>Tue, 28 May 2013 05:39:31 GMT</pubDate></item><item><title><![CDATA[Reply to BitSubsetIterator - Feedback? on Tue, 28 May 2013 09:23:33 GMT]]></title><description><![CDATA[<p>Okay, super, vielen Dank <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
<p>Ich hätte jetzt noch iterator-bezogene Fragen:<br />
- Findet ihr einen Iterator hier sinnvoll? (die anderen Fragen sind dennoch weiter interessant :))<br />
- Braucht ein Iterator unbedingt mehr Operatoren? Würdet ihr euch welche wünschen?<br />
- Habe ich etwas misdesigned, sodass der Iterator gar nicht als Input-Iterator überall brav funktioniert?<br />
- Wie würdet ihr die &quot;atEnd&quot;-Problematik lösen? Meine Kristallkugel sagt mir, anders.</p>
<p>Wenn ihr dazu auch noch Infos hätte, wäre auch dieser Tag gerettet. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2326748</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2326748</guid><dc:creator><![CDATA[Eisflamme]]></dc:creator><pubDate>Tue, 28 May 2013 09:23:33 GMT</pubDate></item><item><title><![CDATA[Reply to BitSubsetIterator - Feedback? on Tue, 28 May 2013 11:25:08 GMT]]></title><description><![CDATA[<p>Eisflamme schrieb:</p>
<blockquote>
<p>- Wie würdet ihr die &quot;atEnd&quot;-Problematik lösen? Meine Kristallkugel sagt mir, anders.</p>
</blockquote>
<p>Ich weiß nicht, was Dein atEnd() macht, ex wäre nett gewesen, ein ganzes Programm zu posten incl main(). Falls Du wolltest, daß man aus der main() das atEnd aufruft, dann ist es unhübsch.<br />
Eigentlich ist es eine range oder ein Generator.<br />
Was als InputIterator rein muss, steht eigentlich da: <a href="http://en.cppreference.com/w/cpp/concept/InputIterator" rel="nofollow">http://en.cppreference.com/w/cpp/concept/InputIterator</a></p>
<p>Mal ein paar ganz wirre Gedanken dazu, streich die 95%, die Mist sind und nimm, falls ein guter Gedanke drin ist, den auf.</p>
<p>Eine steinharte Lösung, wenn man sich nur auf atEnd() stützen kann, wäre</p>
<pre><code>#include &lt;iostream&gt;
#include &lt;cassert&gt;

class BitSubsetIterator{
    uint32_t bits;
    uint32_t mask;
    bool ended;
public:
    BitSubsetIterator(){
        ended=true;
    }
    explicit BitSubsetIterator(uint32_t bits)
    :bits(bits)
    ,mask(bits){
        ended=false;
    }
    uint32_t operator*(){
        return bits;
    }
    BitSubsetIterator operator++(){
        bits=(bits-1)&amp;mask;
        if(atEnd())
            ended=true;
        return *this;
    }
    bool atEnd(){
        return bits==0;
    }
    friend bool operator==(BitSubsetIterator a,BitSubsetIterator b){
        if(a.ended==b.ended)
            return true;
        if(a.ended!=b.ended)
            return false;
        return a.bits==b.bits;
    }
    friend bool operator!=(BitSubsetIterator a,BitSubsetIterator b){
        return !(a==b);
    }
};

struct bin{
    uint32_t n;
    explicit bin(uint32_t n)
    :n(n){
    }
    friend std::ostream&amp; operator&lt;&lt;(std::ostream&amp; out,bin b){
        if(b.n&gt;=2)
            out&lt;&lt;bin(b.n/2);
        return out&lt;&lt;char('0'+b.n%2);
    }
};

int main(){
   for(BitSubsetIterator i=BitSubsetIterator(58),end;i!=end;++i)
        std::cout&lt;&lt;bin(*i)&lt;&lt;'\n';
}
</code></pre>
<p>Manchmal hebe ich ein globales end-Objekt aus.</p>
<pre><code>#include &lt;iostream&gt;
#include &lt;cassert&gt;

class BitSubset{
    public:
    uint32_t bits;
    BitSubset(uint32_t bits)
    :bits(bits){
    }
    class iterator{
        uint32_t bits;
        uint32_t mask;
        iterator(){//only fpr the End
        }
        friend class BitSubset;
    public:
        explicit iterator(uint32_t bits)
        :bits(bits)
        ,mask(bits){
        }
        uint32_t operator*(){
            return bits;
        }
        iterator operator++(){
            bits=(bits-1)&amp;mask;
            return *this;
        }
        bool atEnd(){
            return bits==0;
        }
        static iterator theEnd;
        friend bool operator==(iterator a,iterator b){
            if(&amp;b==&amp;theEnd)
                return a.atEnd();
            if(&amp;a==&amp;theEnd)
                return b.atEnd();
            return a.bits==b.bits;
        }
        friend bool operator!=(iterator a,iterator b){
            return !(a==b);
        }
    };
    iterator begin(){
        return iterator(bits);
    }
    iterator end(){
        return iterator::theEnd;
    }
};
BitSubset::iterator BitSubset::iterator::theEnd;

struct bin{
    uint32_t n;
    explicit bin(uint32_t n)
    :n(n){
    }
    friend std::ostream&amp; operator&lt;&lt;(std::ostream&amp; out,bin b){
        if(b.n&gt;=2)
            out&lt;&lt;bin(b.n/2);
        return out&lt;&lt;char('0'+b.n%2);
    }
};

int main(){
    BitSubset bs(58);
   for(BitSubset::iterator i=bs.begin();i!=bs.end();++i)
        std::cout&lt;&lt;bin(*i)&lt;&lt;'\n';
}
</code></pre>
<p>Aber wenn irgend möglich. nicht so prüfen, sondern das end-Objekt so gestalten, daß mit einem evtl leicht modifizierten op== der Vergleich klappt. Hier gehts gerade mal leicht, Glück gehabt.</p>
<pre><code>#include &lt;iostream&gt;
#include &lt;cassert&gt;

class BitSubset{
    public:
    uint32_t bits;
    BitSubset(uint32_t bits)
    :bits(bits){
    }
    class iterator{
        uint32_t bits;
        uint32_t mask;
        iterator()
        :bits(0){//only fpr the End
        }
        friend class BitSubset;
    public:
        explicit iterator(uint32_t bits)
        :bits(bits)
        ,mask(bits){
        }
        uint32_t operator*(){
            return bits;
        }
        iterator operator++(){
            bits=(bits-1)&amp;mask;
            return *this;
        }
        static iterator theEnd;
        friend bool operator==(iterator a,iterator b){
            return a.bits==b.bits;
        }
        friend bool operator!=(iterator a,iterator b){
            return !(a==b);
        }
    };
    iterator begin(){
        return iterator(bits);
    }
    iterator end(){
        return iterator::theEnd;
    }
};
BitSubset::iterator BitSubset::iterator::theEnd;

struct bin{
    uint32_t n;
    explicit bin(uint32_t n)
    :n(n){
    }
    friend std::ostream&amp; operator&lt;&lt;(std::ostream&amp; out,bin b){
        if(b.n&gt;=2)
            out&lt;&lt;bin(b.n/2);
        return out&lt;&lt;char('0'+b.n%2);
    }
};

int main(){
    BitSubset bs(58);
   for(BitSubset::iterator i=bs.begin();i!=bs.end();++i)
        std::cout&lt;&lt;bin(*i)&lt;&lt;'\n';
}
</code></pre>
<p>Und bettelt darum, wieder rückgebaut zu werden.</p>
<pre><code>#include &lt;iostream&gt;
#include &lt;cassert&gt;

class BitSubset{
    public:
    uint32_t bits;
    BitSubset(uint32_t bits)
    :bits(bits){
    }
    class iterator{
        uint32_t bits;
        uint32_t mask;
    public:
        iterator()
        :bits(0){//only fpr the End
        }
        explicit iterator(uint32_t bits)
        :bits(bits)
        ,mask(bits){
        }
        uint32_t operator*(){
            return bits;
        }
        iterator operator++(){
            bits=(bits-1)&amp;mask;
            return *this;
        }
        friend bool operator==(iterator a,iterator b){
            return a.bits==b.bits;
        }
        friend bool operator!=(iterator a,iterator b){
            return !(a==b);
        }
    };
    iterator begin(){
        return iterator(bits);
    }
    static iterator end(){
        return iterator();
    }
};

struct bin{
    uint32_t n;
    explicit bin(uint32_t n)
    :n(n){
    }
    friend std::ostream&amp; operator&lt;&lt;(std::ostream&amp; out,bin b){
        if(b.n&gt;=2)
            out&lt;&lt;bin(b.n/2);
        return out&lt;&lt;char('0'+b.n%2);
    }
};

int main(){
    BitSubset bs(58);
    for(BitSubset::iterator i=bs.begin();i!=bs.end();++i)
        std::cout&lt;&lt;bin(*i)&lt;&lt;'\n';
}
</code></pre>
<p>Oft halten meine Iteratoren eine Referenz auf den Container.</p>
<pre><code>#include &lt;iostream&gt;
#include &lt;cassert&gt;

class BitSubset{
    public:
    uint32_t bits;
    BitSubset(uint32_t bits)
    :bits(bits){
    }
    class iterator{
        uint32_t bits;
        BitSubset&amp; subset;
    public:
        explicit iterator(uint32_t bits,BitSubset&amp; subset)
        :bits(bits)
        ,subset(subset){
        }
        uint32_t operator*(){
            return bits;
        }
        iterator&amp; operator++(){//uups, die ganze Zeit das &amp; vergessen
            bits=(bits-1)&amp;subset.bits;
            return *this;
        }
        friend bool operator==(iterator a,iterator b){
            assert(&amp;a.subset==&amp;b.subset);//Hier frue ich mich immer, zugegeben, paranoid. :)
            return a.bits==b.bits;
        }
        friend bool operator!=(iterator a,iterator b){
            return !(a==b);
        }
    };
    iterator begin(){
        return iterator(bits,*this);//Ja, hier wandert regelmäßig auch 
    }
    iterator end(){
        return iterator(0,*this);//ein wenig Iteratorlogik hon. 
    }
};

struct bin{
    uint32_t n;
    explicit bin(uint32_t n)
    :n(n){
    }
    friend std::ostream&amp; operator&lt;&lt;(std::ostream&amp; out,bin b){
        if(b.n&gt;=2)
            out&lt;&lt;bin(b.n/2);
        return out&lt;&lt;char('0'+b.n%2);
    }
};

int main(){
    for(auto i:BitSubset(58))
        std::cout&lt;&lt;bin(i)&lt;&lt;'\n';
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2326780</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2326780</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Tue, 28 May 2013 11:25:08 GMT</pubDate></item><item><title><![CDATA[Reply to BitSubsetIterator - Feedback? on Tue, 28 May 2013 12:22:32 GMT]]></title><description><![CDATA[<p>Ja, ist bei mir dann unhübsch. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
<p>Und danke für die Codes! Also ergibt es Sinn eine Klasse drum herum zu basteln und den Iterator nicht einfach für sich stehen zu lassen. Gefällt mir. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /> Den Zeiger auf den Container hältst Du nur wegen dem assert (nicht, dass ich das nicht auch sinnvoll fände)?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2326795</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2326795</guid><dc:creator><![CDATA[Eisflamme]]></dc:creator><pubDate>Tue, 28 May 2013 12:22:32 GMT</pubDate></item><item><title><![CDATA[Reply to BitSubsetIterator - Feedback? on Tue, 28 May 2013 12:32:56 GMT]]></title><description><![CDATA[<p>Eisflamme schrieb:</p>
<blockquote>
<p>Ja, ist bei mir dann unhübsch. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
<p>Und danke für die Codes! Also ergibt es Sinn eine Klasse drum herum zu basteln und den Iterator nicht einfach für sich stehen zu lassen.</p>
</blockquote>
<p>Also die main() finde ich so hübscher.</p>
<p>Eisflamme schrieb:</p>
<blockquote>
<p>Den Zeiger auf den Container hältst Du nur wegen dem assert (nicht, dass ich das nicht auch sinnvoll fände)?</p>
</blockquote>
<p>Nee, das ist nur ein kostenloses Bonbon, wenn ich mich wegen anderer Gründe entscheide, eine Referenz auf den Container zu halten, nämlich wenn der Iterator zu viele Informationen kennen müßte, die der Container eh auch kennt, wenn der Iterator zu schwer werden würde, zu viele Status-Variablen, langsames Kopieren. Oder gar die vollkommene Unmöglichkeit von einem Kind zum nächsten zu springen, ohne den Container zu sehen, ein Iterator über eine Hashtable wäre so ein Fall, keine Zelle weiß, wo die nächste ist, sondern nur den Container selbst könnte es verraten. Wollte das Container-Kennen nur der Vollständigkeit halber nennen, manchmal brauche ist es.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2326800</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2326800</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Tue, 28 May 2013 12:32:56 GMT</pubDate></item></channel></rss>