Skip to content

Commit

Permalink
Added list comprehension project
Browse files Browse the repository at this point in the history
  • Loading branch information
seanbaxter committed Jan 20, 2020
1 parent 25c1782 commit 2773bde
Show file tree
Hide file tree
Showing 35 changed files with 2,875 additions and 284 deletions.
12 changes: 12 additions & 0 deletions comprehension/accumulate.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Sums the first ten squares and prints them, using views::ints to generate
// and infinite range of integers, views::transform to square them, views::take
// to drop all but the first 10, and accumulate to sum them.

#include <vector>
#include <iostream>

int main() {
auto sq = [](int x) { return x * x; };
int sum = (... + sq(@range(1:11)));
std::cout<< sum<< '\n'; // Prints 385
}
13 changes: 13 additions & 0 deletions comprehension/any_of.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include <vector>
#include <iostream>

int main() {
using std::cout;

std::vector<int> v { 6, 2, 3, 4, 5, 6 };

cout<< std::boolalpha;
cout<< "vector any_of is 6: "<< (... || (6 == v[:]))<< '\n';
cout<< "vector all_of is 6: "<< (... && (6 == v[:]))<< '\n';
cout<< "vector none_of is 6: "<< (... && (6 != v[:]))<< '\n';
}
26 changes: 26 additions & 0 deletions comprehension/build_all.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
set -x
circle iterate.cxx && ./iterate
circle pack1.cxx && ./pack1
circle pack2.cxx && ./pack2
circle slice.cxx && ./slice
circle range.cxx && ./range
circle for.cxx && ./for
circle locus.cxx && ./locus
circle expansion.cxx && ./expansion
circle list_comp.cxx && ./list_comp
circle locus2.cxx && ./locus2
circle fold.cxx && ./fold
circle range_for.cxx && ./range_for
circle sequences.cxx && ./sequences
circle slice2.cxx && ./slice2
circle pack_decl.cxx && ./pack_decl
circle hello.cxx && ./hello
circle any_of.cxx && ./any_of
circle count.cxx && ./count
circle count_if.cxx && ./count_if
circle for_each.cxx && ./for_each
circle for_each2.cxx && ./for_each2
circle is_sorted.cxx && ./is_sorted
circle filter.cxx && ./filter
circle accumulate.cxx && ./accumulate
circle comprehension.cxx && ./comprehension
9 changes: 9 additions & 0 deletions comprehension/comprehension.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include <vector>
#include <cstdio>

int main() {
std::vector v = [ for i : @range(1:6)... => for i2 : i => i ... ... ];

// Prints '1 2 2 3 3 3 4 4 4 4 5 5 5 5 5 '.
printf("%d ", v[:])...; printf("\n");
}
1,722 changes: 1,722 additions & 0 deletions comprehension/comprehension.md

Large diffs are not rendered by default.

19 changes: 19 additions & 0 deletions comprehension/count.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include <vector>
#include <array>
#include <iostream>

int main() {
using std::cout;

// Count the number of 6s.
// Promote each comparison to int, because adding bools in a dynamic
// fold expression will return a bool type.
std::vector<int> v { 6, 2, 3, 4, 5, 6 };
int count1 = (... + (int)(6 == v[:]));
cout<< "vector: "<< count1<< '\n';

// Do it with an array.
std::array<int, 6> a { 6, 2, 3, 4, 5, 6 };
int count2 = (...+ (int)(6 == a[:]));
cout<< "array: "<< count2<< '\n';
}
18 changes: 18 additions & 0 deletions comprehension/count_if.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include <vector>
#include <array>
#include <iostream>

int main() {
using std::cout;

// This is the identical implementation as count.cxx.
// ranges::count and ranges::count_if are implemented with the same
// fold expression in Circle.
std::vector<int> v { 6, 2, 3, 4, 5, 6 };
int count1 = (... + (int)(6 == v[:]));
cout<< "vector: "<< count1<< '\n';

std::array<int, 6> a { 6, 2, 3, 4, 5, 6 };
int count2 = (...+ (int)(6 == a[:]));
cout<< "array: "<< count2<< '\n';
}
60 changes: 60 additions & 0 deletions comprehension/expansion.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include <vector>
#include <set>
#include <algorithm>
#include <cstdio>

int main() {
std::vector<int> v { 4, 2, 2, 2, 5, 1, 1, 9, 8, 7 };

// Print the vector values.
printf("%3d ", v[:])...; printf("\n");

// Fill the vector with powers of 2.
v[:] = 1<< @range()...;
printf("%3d ", v[:])...; printf("\n");

// Populate a set with the same values. Print their values.
// Slice is like an enhanced ranged-for, so it supports the usual
// STL containers, or anything else with begin, end and size member
// functions.
std::set<int> set;
set.insert(v[:])...;
printf("%3d ", set[:])...; printf("\n");

// Add up all values into an accumulator. This is better done with a
// fold expression.
int sum = 0;
sum += v[:]...;
printf("sum = %d\n", sum); // sum = 41

// Add each right element into its left element. Because the loop is
// executed left-to-right, we don't risk overwriting any elements before
// we source them.
v[:] += v[1:]...;
printf("%3d ", v[:])...; printf("\n"); // 6 4 4 7 6 2 10 17 15 7

// Reset the array to 1s.
v[:] = 1...;

// Perform a prefix scan. Add into each element the sum of all elements
// before it. This is like the fourth example, but with the operands
// flipped.
v[1:] += v[:]...;
printf("%3d ", v[:])...; printf("\n"); // 1 2 3 4 5 6 7 8 9 10

// Reverse the array in place. Exchange each element with its mirror
// up through the midpoint.
int mid = v.size() / 2;
std::swap(v[:mid], v[::-1])...;
printf("%3d ", v[:])...; printf("\n"); // 10 9 8 7 6 5 4 3 2 1

// Add into each element its index from the range of integers.
v[:] += @range()...;
printf("%3d ", v[:])...; printf("\n"); // 10 10 10 10 10 10 10 10 10 10

// Reset the array to ascending integers. Now swap the even and odd
// positions. The 2-element step skips every other item.
v[:] = @range()...;
std::swap(v[::2], v[1::2])...;
printf("%3d ", v[:])...; printf("\n"); // 1 0 3 2 5 4 7 6 9 8
}
14 changes: 14 additions & 0 deletions comprehension/filter.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include <vector>
#include <string>
#include <cstdio>

int main() {
std::vector<int> vi { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

// Create a vector of strings. Filter for the even elements and convert
// to strings.
std::vector v2 = [for i : vi if 0==i%2 => std::to_string(i) ...];

// Print the strings out.
printf("%s ", v2[:].c_str())...; printf("\n"); // Prints '2 4 6 8 10 '.
}
Empty file added comprehension/find.cxx
Empty file.
114 changes: 114 additions & 0 deletions comprehension/fold.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#include <vector>
#include <algorithm>
#include <cstdio>

inline int fact(int x) {
// Use a fold expression to compute factorials. This evaluates the product
// of integers from 1 to x, inclusive.
return (... * @range(1:x+1));
}

inline void func() {
std::vector<int> v { 4, 2, 2, 2, 5, 1, 1, 9, 8, 7, 1, 7, 4, 1 };

// (... || pack) is a short-circuit fold on operator||.
bool has_five = (... || (5 == v[:]));
printf("has_five = %s\n", has_five ? "true" : "false");

bool has_three = (... || (3 == v[:]));
printf("has_three = %s\n", has_three ? "true" : "false");

// Reduce the number of 1s.
int num_ones = (... + (int)(1 == v[:]));
printf("has %d ones\n", num_ones);

// Find the max element using qualified lookup for std::max.
int max_element = (... std::max v[:]);
printf("max element = %d\n", max_element);

// Find the min element using the ADL trick. This uses unqualified lookup
// for min.
using std::min;
int min_element = (... min v[:]);
printf("min element = %d\n", min_element);

// Find the biggest difference between consecutive elements.
int max_diff = (... std::max (abs(v[:] - v[1:])));
printf("max difference = %d\n", max_diff);

// Compute the Taylor series for sign. s is the current index, so
// pow(-1, s) alternates between +1 and -1.
// The if clause in the for-expression filters out the even elements,
// where are zero for sine, and leaves the odd powers. This compacts the
// vector to 5 elements out of 10 terms.
int terms = 10;
std::vector series = [for i : terms if 1 & i => pow(-1, i/2) / fact(i)...];
printf("series:\n");
printf(" %f\n", series[:])...;

// Compute x raised to each odd power. Use @range to generate all odd
// integers from 1 to terms, and raise x by that.
double x = .3;
std::vector powers = [pow(x, @range(1:terms:2))...];
printf("powers:\n");
printf(" %f\n", powers[:])...;

// Evaluate the series to approximate sine. This is a simple dot
// product between the coefficient and the powers vectors.
double sinx = (... + (series[:] * powers[:]));
printf("sin(%f) == %f\n", x, sinx);
}

@meta func();

int main() {
std::vector<int> v { 4, 2, 2, 2, 5, 1, 1, 9, 8, 7, 1, 7, 4, 1 };

// (... || pack) is a short-circuit fold on operator||.
bool has_five = (... || (5 == v[:]));
printf("has_five = %s\n", has_five ? "true" : "false");

bool has_three = (... || (3 == v[:]));
printf("has_three = %s\n", has_three ? "true" : "false");

// Reduce the number of 1s.
int num_ones = (... + (int)(1 == v[:]));
printf("has %d ones\n", num_ones);

// Find the max element using qualified lookup for std::max.
int max_element = (... std::max v[:]);
printf("max element = %d\n", max_element);

// Find the min element using the ADL trick. This uses unqualified lookup
// for min.
using std::min;
int min_element = (... min v[:]);
printf("min element = %d\n", min_element);

// Find the biggest difference between consecutive elements.
int max_diff = (... std::max (abs(v[:] - v[1:])));
printf("max difference = %d\n", max_diff);

// Compute the Taylor series for sign. s is the current index, so
// pow(-1, s) alternates between +1 and -1.
// The if clause in the for-expression filters out the even elements,
// where are zero for sine, and leaves the odd powers. This compacts the
// vector to 5 elements out of 10 terms.
int terms = 10;
std::vector series = [for i : terms if 1 & i => pow(-1, i/2) / fact(i)...];
printf("series:\n");
printf(" %f\n", series[:])...;

// Compute x raised to each odd power. Use @range to generate all odd
// integers from 1 to terms, and raise x by that.
double x = .3;
std::vector powers = [pow(x, @range(1:terms:2))...];
printf("powers:\n");
printf(" %f\n", powers[:])...;

// Evaluate the series to approximate sine. This is a simple dot
// product between the coefficient and the powers vectors.
double sinx = (... + (series[:] * powers[:]));
printf("sin(%f) == %f\n", x, sinx);
}

30 changes: 30 additions & 0 deletions comprehension/for.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include <string>
#include <vector>
#include <cstdio>

int main() {
std::string s = "Hello world";

// Use a for-expression to print only the lowercase characters.
std::string s2 = ['*', for c : s if islower(c) => c..., '*'];
puts(s2.c_str()); // Prints '*elloworld*'

// Use a for-expression to double each character.
std::string s3 = [for c : s => { c, c }...];
puts(s3.c_str()); // Prints 'HHeelllloo wwoorrlldd'

// Use a for-expression to emit upper/lower-case pairs.
std::string s4 = [for c : s => {(char)toupper(c), (char)tolower(c)}...];
puts(s4.c_str()); // Prints 'HhEeLlLlOo WwOoRrLlDd'

// Use the index to create alternating upper and lowercase characters.
std::string s5 = [for i, c : s => (char)((1&i) ? tolower(c) : toupper(c))...];
puts(s5.c_str()); // Prints 'HeLlO WoRlD'

// Create a vector of vectors.
printf("Creating a vector of vectors:\n");
std::vector vecs = [for i : 5 => [for i2 : i => i...] ...];
for(auto& v : vecs) {
printf("[ "); printf("%d ", v[:])...; printf("]\n");
}
}
19 changes: 19 additions & 0 deletions comprehension/for2.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include <vector>
#include <map>
#include <string>
#include <cstdio>

int main() {
std::map<std::string, int> map {
{ "Washington", 1 },
{ "Madison", 5 },
{ "Lincoln", 16 },
{ "Grant", 18 },
{ "Coolidge", 30 },
};

std::string s = [for &x : map => x.first[:]... ...];
puts(s.c_str());
}


31 changes: 31 additions & 0 deletions comprehension/for_each.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include <vector>
#include <array>
#include <list>
#include <forward_list>
#include <queue>
#include <iostream>

int main() {
using std::cout;

cout<< "vector: ";
std::vector<int> v { 1, 2, 3, 4, 5, 6 };
cout<< v[:]<< ' ' ...;

cout<< "\narray: ";
std::array<int, 6> a { 1, 2, 3, 4, 5, 6 };
cout<< a[:]<< ' ' ...;

cout<< "\nlist: ";
std::list<int> ll { 1, 2, 3, 4, 5, 6 };
cout<< ll[:]<< ' ' ...;

cout<< "\nfwd_list: ";
std::forward_list<int> fl { 1, 2, 3, 4, 5, 6 };
cout<< fl[:]<< ' ' ...;

cout<< "\ndeque: ";
std::deque<int> d { 1, 2, 3, 4, 5, 6 };
cout<< d[:]<< ' ' ...;
cout<< '\n';
}
Loading

0 comments on commit 2773bde

Please sign in to comment.