-
Notifications
You must be signed in to change notification settings - Fork 0
/
rule110.hpp
70 lines (50 loc) · 2.26 KB
/
rule110.hpp
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
#include <array>
/* Index sequence */
template <unsigned int... Sequence>
struct sequence { };
template <unsigned int N, unsigned int... Rest>
struct make_sequence : make_sequence<N-1, N-1, Rest...> { };
template <unsigned int... Rest>
struct make_sequence<0, Rest...> : sequence<Rest...> { };
/* State data structure */
template <unsigned int N>
using State = std::array<bool, N>;
/* Cell evolution */
constexpr bool evolveCell(bool left, bool center, bool right) {
return static_cast<bool>((110 >> ((left << 2) | (center << 1) | (right << 0))) & 0x1);
}
/* State evolution */
template <unsigned int N>
constexpr bool evolveCell(unsigned int index, const State<N> &state) {
return evolveCell(state[(index-1) % N], state[index], state[(index+1) % N]);
}
template <unsigned int N, unsigned int... Indices>
constexpr State<N> _evolveState(sequence<Indices...> seq, const State<N> &state) {
return {{evolveCell<N>(Indices, state)...}};
}
template <unsigned int N>
constexpr State<N> evolveState(const State<N> &state) {
return _evolveState<N>(make_sequence<N>(), state);
}
/* State evolution for a specified number of generations */
template <unsigned int N>
constexpr State<N> _iterateEvolveState(sequence<> seq, const State<N> &initialState) {
return initialState;
}
template <unsigned int N, unsigned int Generation, unsigned int... Rest>
constexpr State<N> _iterateEvolveState(sequence<Generation, Rest...> seq, const State<N> &initialState) {
return evolveState<N>(_iterateEvolveState<N, Rest...>(sequence<Rest...>(), initialState));
}
template <unsigned int N, unsigned int Generations>
constexpr State<N> iterateEvolveState(const State<N> &initialState) {
return _iterateEvolveState<N>(make_sequence<Generations>(), initialState);
}
/* State evolutions, recorded across a specified number of generations */
template <unsigned int N, unsigned int... Generations>
constexpr std::array<State<N>, sizeof...(Generations)> _evolve(sequence<Generations...> seq, const State<N> &initialState) {
return {{iterateEvolveState<N, Generations>(initialState)...}};
}
template <unsigned int N, unsigned int Generations>
constexpr std::array<State<N>, Generations> evolve(const State<N> &initialState) {
return _evolve<N>(make_sequence<Generations>(), initialState);
}