File size: 3,041 Bytes
497f2f3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#include <iostream>    // compiled with clang (tags/RELEASE_600/final)
#include <type_traits> // or g++ (GCC) 7.3.1 20180406 -- from hare1039
namespace functional_list // basic building block for template meta programming
{
struct NIL
{
	using head = NIL;
	using tail = NIL;
	friend std::ostream& operator << (std::ostream& os, NIL const) { return os; }
};

template <typename H, typename T = NIL>
struct list
{
	using head = H;
	using tail = T;
};

template <int i>
struct integer
{
	static constexpr int value = i;
	friend std::ostream& operator << (std::ostream& os, integer<i> const) { os << integer<i>::value; return os;}
};

template <typename L, int nTH> constexpr
auto at()
{
	if constexpr (nTH == 0)
		return (typename L::head){};
	else if constexpr (not std::is_same_v<typename L::tail, NIL>) 
		return at<typename L::tail, nTH - 1>();
	else
		return NIL{};
}
template <typename L, int nTH>
using at_t = decltype(at<L, nTH>());

template <typename L, typename elem> constexpr
auto prepend() { return list<elem, L>{}; }

template <typename L, typename elem>
using prepend_t = decltype(prepend<L, elem>());
	
template <int Size, typename Dat = integer<0>> constexpr
auto gen_list()
{
	if constexpr (Size == 0)
		return NIL{};
	else
	{
		using next = decltype(gen_list<Size - 1, Dat>());
		return prepend<next, Dat>();
	}
}
template <int Size, typename Dat = integer<0>>
using gen_list_t = decltype(gen_list<Size, Dat>());
	
} namespace fl = functional_list;

constexpr int door_amount = 101; // index from 1 to 100

template <typename L, int current, int moder> constexpr
auto construct_loop()
{
	using val_t = fl::at_t<L, current>;
	if constexpr (std::is_same_v<val_t, fl::NIL>)
		return fl::NIL{};
	else
	{
		constexpr int val = val_t::value;
		using val_add_t = fl::integer<val + 1>;
		using val_old_t = fl::integer<val>;
	
		if constexpr (current == door_amount)
		{
			if constexpr(current % moder == 0)
				return fl::list<val_add_t>{};
			else
				return fl::list<val_old_t>{};
		}
		else
		{
			using sub_list = decltype(construct_loop<L, current + 1, moder>());
			if constexpr(current % moder == 0)
				return fl::prepend<sub_list, val_add_t>();
			else
				return fl::prepend<sub_list, val_old_t>();
		}
	}
}

template <int iteration> constexpr
auto construct()
{
	if constexpr (iteration == 1) // door index = 1
	{
		using l = fl::gen_list_t<door_amount>;
		return construct_loop<l, 0, iteration>();
	}
	else
	{
		using prev_iter_list = decltype(construct<iteration - 1>());
		return construct_loop<prev_iter_list, 0, iteration>();
	}
}

template <typename L, int pos> constexpr
void show_ans()
{
	if constexpr (std::is_same_v<typename L::head, fl::NIL>)
		return;
	else
	{
		if constexpr (L::head::value % 2 == 1)
			std::cout << "Door " << pos << " is opened.\n";
		show_ans<typename L::tail, pos + 1>();
	}
}

int main()
{
	using result = decltype(construct<100>());
	show_ans<result, 0>();
}