Skip to content

Instantly share code, notes, and snippets.

@scientific-coder
Last active August 29, 2015 14:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save scientific-coder/4d6c6c058d06c1251a3b to your computer and use it in GitHub Desktop.
Save scientific-coder/4d6c6c058d06c1251a3b to your computer and use it in GitHub Desktop.
FizzBuzz
#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); }
};
#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;
}
#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)); }
#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