Last active
August 29, 2015 14:07
-
-
Save scientific-coder/4d6c6c058d06c1251a3b to your computer and use it in GitHub Desktop.
FizzBuzz
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <functional> | |
// TODO : monoid | |
template<typename... Fn> struct composer; | |
template<> struct composer<> { | |
template<typename Data> Data operator()(Data d){ return d; } | |
}; | |
template<typename F0, typename... Fn> | |
struct composer<F0, Fn...> : private composer<Fn...> { | |
F0 f; | |
composer(F0 f0, Fn const&... fn): composer<Fn...>(fn...), f(f0){} | |
template<typename Data> auto operator()(Data d)->decltype(f(composer<Fn...>::operator()(d))) | |
{ return f(composer<Fn...>::operator()(d)); } | |
}; | |
template <typename... Fn> | |
composer<Fn...> comp(Fn const&... fn) | |
{ return composer<Fn...>(fn...); } | |
template <typename F> | |
struct compose_functions { | |
F operator()(F f1, F f2) const { return comp(f1, f2); } | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <iterator> | |
#include <string> | |
#include <tuple> | |
#include <functional> | |
#include "transducers.hxx" | |
#include "compose.hxx" | |
#include "tuple_reader.hxx" | |
// usage: seq 1 20 |./fizz-buzz-args 3 Fizz 5 Buzz | |
int main(int argc, char* argv[]){ | |
typedef int data_t; | |
typedef std::tuple<data_t, std::string> tuple_t; | |
typedef std::function<tuple_t(tuple_t)> fun_t; // for type erasure & copy cstor of lambda | |
typedef decltype(std::cout)& out_t; | |
typedef std::istream_iterator<data_t> in_t; | |
transduce(comp(map([](data_t v){return tuple_t(v, "");}) | |
, map(transduce(comp(tuple_reader<tuple_t>() | |
, map([](tuple_t f_n){ return [f_n](tuple_t v_n){ | |
return (std::get<0>(v_n) % std::get<0>(f_n)) | |
? v_n : tuple_t(std::get<0>(v_n), std::get<1>(f_n) + std::get<1>(v_n));};})) | |
, compose_functions<fun_t>{} | |
, fun_t([](tuple_t t){ return t;}) | |
, argv+1, argv+argc)) | |
, map([](tuple_t const& v_n){ return std::get<1>(v_n).empty() ? std::to_string(std::get<0>(v_n)) : std::get<1>(v_n);})) | |
, [](out_t out, std::string const& s)->out_t { return out << s << ' ';} | |
, std::ref(std::cout), in_t(std::cin), in_t()).get() << std::endl; | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <numeric> | |
#include <algorithm> | |
#include <tuple> | |
#include <sstream> | |
#include <functional> | |
/* const correctness and pass by value vs const ref, move semantics | |
left as an exercise to the reader. | |
iterator range API prevents a flatmap as the flatmapped function | |
could not either return a value or a range. | |
(would return the paste-the-end iterator of an output range)*/ | |
template<typename Op, template<typename, typename> class Transducer > | |
struct transducer_helper { | |
Op op; | |
transducer_helper(Op o):op(o){} | |
template <typename Reducer> | |
Transducer<Op, Reducer> operator()(Reducer r) | |
{return Transducer<Op, Reducer>(op, r);} | |
}; | |
template <typename Op, typename Reducer> | |
struct transducer_base { | |
Op op; | |
Reducer reducer; | |
transducer_base(Op o, Reducer r): op(o), reducer(r){} | |
}; | |
template <typename Op, typename Reducer> | |
struct map_transducer : transducer_base<Op, Reducer> { | |
using transducer_base<Op, Reducer>::transducer_base; | |
template<typename Result, typename Input> | |
Result operator()(Result r, Input data) | |
{ return this->reducer(r, this->op(data));} | |
}; | |
template <typename Op> | |
transducer_helper<Op, map_transducer> map(Op const& op) | |
{ return transducer_helper<Op, map_transducer>(op); } | |
template <typename Op, typename Reducer> | |
struct filter_transducer : transducer_base<Op, Reducer>{ | |
using transducer_base<Op, Reducer>::transducer_base; | |
template<typename Result, typename Input> | |
Result operator()(Result r, Input data) | |
{ return this->op(data) ? this->reducer(r, data) : r ;} | |
}; | |
template <typename Op> | |
transducer_helper<Op, filter_transducer> filter(Op const& op) | |
{ return transducer_helper<Op, filter_transducer>(op); } | |
// the flatmap Op takes two args, the data and an output iter | |
// (and returns the past-the-end output iter) | |
template <typename Op, typename Reducer> | |
struct flatmap_transducer : transducer_base<Op, Reducer>{ | |
using transducer_base<Op, Reducer>::transducer_base; | |
template<typename Result, typename Input> | |
Result operator()(Result r, Input data){ | |
return (this->op(data, make_reducing_output_iterator(this->reducer, r))).res; | |
} | |
}; | |
template <typename Op> | |
transducer_helper<Op, flatmap_transducer> flatmap(Op const& op) | |
{ return transducer_helper<Op, flatmap_transducer>(op); } | |
template < typename Transducer, typename Reducer, typename Init, typename In> | |
Init transduce (Transducer xform, Reducer f, Init res, In b, In e) | |
{ return std::accumulate(b, e, res, xform(f)); } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <tuple> | |
#include <sstream> | |
struct lexical_reader { | |
std::string data; | |
lexical_reader(std::string str):data(str){} | |
lexical_reader(char const* str):data(str){} | |
template<typename V> | |
lexical_reader(V d){ std::ostringstream oss; oss<<d; data= oss.str();} | |
template<class E> void operator()(E& elt){ | |
std::istringstream iss(data); | |
iss >> elt; | |
} | |
}; | |
template<int... Is> struct seq {}; | |
template<int N, int... Is> struct gen_seq : gen_seq<N-1, N-1, Is...> {}; | |
template<int... Is> struct gen_seq<0, Is...> : seq<Is...> {}; | |
template<int N, class T, class F> | |
void apply_one(T& p, F func){ func( std::get<N>(p)); } | |
template<class T, class F, int... Is> | |
void apply(T& p, int index, F func, seq<Is...>){ | |
using FT = void(T&, F); | |
static constexpr FT* arr[] = { &apply_one<Is, T, F>... }; | |
arr[index](p, func); | |
} | |
template<class T, class F> | |
void apply(T& p, int index, F func) | |
{ apply(p, index, func, gen_seq<std::tuple_size<T>::value>()); } | |
template<typename T> struct tuple_reader{ | |
template <typename Reducer> struct tuple_reader_transducer { | |
T t; | |
std::size_t i; | |
Reducer reducer; | |
tuple_reader_transducer(Reducer r):i(0), reducer(r){} | |
template<typename Result, typename Input> | |
Result operator()(Result r, Input data) { | |
apply(t, i, lexical_reader(data)); ++i; | |
if(i == std::tuple_size<T>::value ){ i= 0; } | |
return i ? r : this->reducer(r, t) ; | |
} | |
}; | |
template <typename Reducer> | |
tuple_reader_transducer<Reducer> operator()(Reducer r) const | |
{ return tuple_reader_transducer<Reducer>(r); } | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment