#include <type_traits>
#include <utility>
#include <iostream>
template<int... s>
struct seq {};
template<int n, typename seq, typename=void>
struct can_be_factored_into;
template<int n, int first, int... rest>
struct can_be_factored_into< n, seq<first, rest...>, typename std::enable_if< (n > 1) && (n%first) >::type >: can_be_factored_into< n, seq<rest...> > {};
template<int n, int first, int... rest>
struct can_be_factored_into< n, seq<first, rest...>, typename std::enable_if< (n > 1) && !(n%first) >::type >: can_be_factored_into< n/first, seq<first, rest...> > {};
template<int n, int... rest>
struct can_be_factored_into< n, seq<rest...>, typename std::enable_if< n == 1 >::type: std::true_type {};
template<int n>
struct can_be_factored_into< n, seq<>, typename std::enable_if< n != 1 >::type: std::false_type {};
template<int n>
using my_test = can_be_factored_into< n, seq<2,3,5> >;
template<template<int n>class test, int cnt, int start=1, typename=void>
struct nth_element;
template<template<int n>class test, int cnt, int start>
struct nth_element<test, cnt, start, typename std::enable_if< (cnt>1)&&test<start>::value >::type >:
nth_element<test, cnt-1, start+1 > {};
template<template<int n>class test, int cnt, int start>
struct nth_element<test, cnt, start, typename std::enable_if< (cnt==1)&&test<start>::value >::type >
{ enum { value = start }; };
template<template<int n>class test, int cnt, int start>
struct nth_element<test, cnt, start, typename std::enable_if< !test<start>::value >::type >:
nth_element<test, cnt, start+1 > {};
int main() {
std::cout << nth_element< my_test, 1500 >::value << "\n";
}
Once you compile the above code, it will execute in far less than 1 minute.
The downside is that it will blow the compile time recursion limit of most compilers. (this was your daily understatement)
To improve this, nth_element
needs to be rewritten to do an exponential blow up search and a divide and conquer within that range. You may also have to modify the code to work with 64 bit values, as the 1500th element of the mentioned sequence might be bigger than 2^32.
Or is having it compile fast also a requirement? :)
And here is a first pass at a Hamming implementation. Not compiled yet:
#include <iostream>
#include <utility>
template<long long... s>
struct seq;
template<long long cnt, typename seq, typename=void>
struct Hamming;
template<long long cnt, long long first, long long... rest>
struct Hamming<cnt, seq<first, rest...>, typename std::enable_if< cnt == 0 >::type> {
static const long long value = first;
};
template<long long x, typename seq>
struct prepend;
template<long long x, long long... s>
struct prepend<x, seq<s...>>
{
typedef seq<x, s...> type;
};
template<typename s1, typename s2, typename=void>
struct merge;
template<long long begin_s1, long long... s1, long long begin_s2, long long... s2>
struct merge< seq< begin_s1, s1... >, seq< begin_s2, s2... >, typename std::enable_if< (begin_s1 < begin_s2) >::type > {
typedef typename prepend< begin_s1, typename merge< seq< s1... >, seq< begin_s2, s2... > >::type >::type type;
};
template<long long begin_s1, long long... s1, long long begin_s2, long long... s2>
struct merge< seq< begin_s1, s1... >, seq< begin_s2, s2... >, typename std::enable_if< (begin_s1 >= begin_s2) >::type > {
typedef typename prepend< begin_s2, typename merge< seq< begin_s1, s1... >, seq< s2... > >::type >::type type;
};
template<long long begin_s1, long long... s1>
struct merge< seq< begin_s1, s1... >, seq<>, void > {
typedef seq< begin_s1, s1... > type;
};
template<long long... s2>
struct merge< seq<>, seq<s2...>, void > {
typedef seq< s2... > type;
};
template<long long cnt, long long first, long long... rest>
struct Hamming<cnt, seq<first, rest...>, typename std::enable_if< cnt != 0 >::type>:
Hamming<cnt-1, typename merge< seq<first*2, first*3, first*5>, seq<rest...> >::type >
{};
int main() {
std::cout << Hamming<1500, seq<1>>::value << "\n";
};