C++: List Comprehensions

 


A list comprehension is a special syntax in some programming languages to describe lists. It is similar to the way mathematicians describe sets, with a set comprehension, hence the name.

Some attributes of a list comprehension are that:

  1. They should be distinct from (nested) for loops within the syntax of the language.
  2. They should return either a list or an iterator (something that returns successive members of a collection, in order).
  3. The syntax has parts corresponding to that of set-builder notation.

Write a list comprehension that builds the list of all Pythagorean triples with elements between 1 and n. If the language has multiple ways for expressing such a construct (for example, direct list comprehensions and generators), write one example for each.

There is no equivalent construct in C++. The code below uses two nested loops and an if statement:

#include <vector>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <iterator>
 
void list_comprehension( std::vector<int> & , int ) ;
 
int main( ) {
   std::vector<int> triangles ;
   list_comprehension( triangles , 20 ) ;
   std::copy( triangles.begin( ) , triangles.end( ) ,
	 std::ostream_iterator<int>( std::cout , " " ) ) ;
   std::cout << std::endl ;
   return 0 ;
}
 
void list_comprehension( std::vector<int> & numbers , int upper_border ) {
   for ( int a = 1 ; a < upper_border ; a++ ) {
      for ( int b = a + 1 ; b < upper_border ; b++ ) {
	 double c = pow( a * a + b * b , 0.5 ) ; //remembering Mr. Pythagoras
	 if ( ( c * c ) < pow( upper_border , 2 ) + 1 ) {
	    if ( c == floor( c ) ) {
	       numbers.push_back( a ) ;
	       numbers.push_back( b ) ;	      
	       numbers.push_back( static_cast<int>( c ) ) ;
	    }
	 }
      }
   }
}

This produces the following output:

3 4 5 5 12 13 6 8 10 8 15 17 9 12 15 12 16 20
Works with: C++11

#include <functional>
#include <iostream>
 
void PythagoreanTriples(int limit, std::function<void(int,int,int)> yield)
{
    for (int a = 1; a < limit; ++a) {
        for (int b = a+1; b < limit; ++b) {
            for (int c = b+1; c <= limit; ++c) {
                if (a*a + b*b == c*c) {
                    yield(a, b, c);
                }
            }
        }
    }
}
 
int main()
{
    PythagoreanTriples(20, [](int x, int y, int z)
    {
        std::cout << x << "," << y << "," << z << "\n";
    });
    return 0;
}

Output:

3,4,5
5,12,13
6,8,10
8,15,17
9,12,15
12,16,20

SOURCE

Content is available under GNU Free Documentation License 1.2.