/*
 * Lazy generation of Pythagorean Triples
 * Inspired by http://b...content-available-to-author-only...i.com/2014/04/21/getting-lazy-with-c/
 * John Zwinck, 2014-04-22
 * 
 * This demonstrates a different, perhaps more C++ish solution to lazily
 * generate a sequence.  This approach does no dynamic memory allocation.
 * The main idea is to implement a custom forward iterator (STL compatible).
 *
 * Separation of concerns are handled thusly:
 * 1. Generating Pythagorean Triples is done by our triple_iterator.
 * 2. Printing is handled by std::ostream_iterator<>.
 * 3. Limiting the number of triples generated is via std::copy_n().
 *
 * As in the original version, the algorithm is naive.
 */

#include <algorithm>
#include <iostream>
#include <iterator>

using namespace std;

struct triple
{
    int x = 0;
    int y = 0;
    int z = 0;
};

ostream& operator<<(ostream& out, const triple& value)
{
    return out << value.x << ", " << value.y << ", " << value.z;
}

// unbounded forward iterator producing Pythagorean Triples on demand
class triple_iterator : public iterator<forward_iterator_tag, triple>, triple
{
public:
    triple_iterator() { ++*this; } // initialize to the first valid triple
    const triple& operator*() { return *this; }

    // set ourselves to the next Pythagorean Triple
    triple_iterator& operator++()
    {
    	// we must skip certain actions the first time through,
    	// to give the appearance of resuming where we returned the last time
        bool resume = true;

        for (; ; ++z) {
            if (!resume) {
                x = 1;
            }
            for (; x <= z; ++x) {
                if (!resume) {
                    y = x;
                }
                for (; y <= z; ++y) {
                    if (resume) {
                        ++y;
                    }
                    if (x*x + y*y == z*z) {
                        return *this;
                    }
                    resume = false;
                }
            }
        }
    }
};

int main()
{
    // write the first few Pythagorean Triples to stdout
    copy_n(triple_iterator(), 10, ostream_iterator<triple>(cout, "\n"));
}
