add example: compile-time lifegame

This commit is contained in:
bolero-MURAKAMI 2015-05-28 13:11:39 +09:00
parent 559db060ab
commit feac3f52c7
3 changed files with 318 additions and 0 deletions

222
example/lifegame/main.cpp Normal file
View file

@ -0,0 +1,222 @@
/*=============================================================================
Copyright (c) 2011-2015 Bolero MURAKAMI
https://github.com/bolero-MURAKAMI/Sprout
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#include <sprout/config.hpp>
#include <sprout/container/traits.hpp>
#include <sprout/container/functions.hpp>
#include <sprout/container/indexes.hpp>
#include <sprout/algorithm/fixed/unfold.hpp>
#include <sprout/utility/pair.hpp>
#include <sprout/array.hpp>
//
// next_cell
//
template<typename Value, typename Size>
inline SPROUT_CONSTEXPR Value
next_cell(Value const& val, Size n) {
return val ? n == 2 || n == 3 : n == 3;
}
template<typename Container, typename Difference1, typename Difference2>
inline SPROUT_CONSTEXPR typename sprout::container_traits<typename sprout::container_traits<Container>::value_type>::value_type
next_cell(Container const& cont, Difference1 i, Difference2 j) {
return i == 0
// +----
// | o x
// | x x
? j == 0
? ::next_cell(
cont[i][j],
0
+ cont[i][j + 1]
+ cont[i + 1][j] + cont[i + 1][j + 1]
)
// ----+
// x o |
// x x |
: j == static_cast<Difference2>(sprout::size(cont[i]) - 1)
? ::next_cell(
cont[i][j],
0
+ cont[i][j - 1]
+ cont[i + 1][j - 1] + cont[i + 1][j]
)
// -----
// x o x
// x x x
: ::next_cell(
cont[i][j],
0
+ cont[i][j - 1] + cont[i][j + 1]
+ cont[i + 1][j - 1] + cont[i + 1][j] + cont[i + 1][j + 1]
)
: i == static_cast<Difference1>(sprout::size(cont) - 1)
// | x x
// | o x
// +----
? j == 0
? ::next_cell(
cont[i][j],
0
+ cont[i - 1][j] + cont[i - 1][j + 1]
+ cont[i][j + 1]
)
// x x |
// x o |
// ----+
: j == static_cast<Difference2>(sprout::size(cont[i]) - 1)
? ::next_cell(
cont[i][j],
0
+ cont[i - 1][j - 1] + cont[i - 1][j]
+ cont[i][j - 1]
)
// x x x
// x o x
// -----
: ::next_cell(
cont[i][j],
0
+ cont[i - 1][j - 1] + cont[i - 1][j] + cont[i - 1][j + 1]
+ cont[i][j - 1] + cont[i][j + 1]
)
// | x x
// | o x
// | x x
: j == 0
? ::next_cell(
cont[i][j],
0
+ cont[i - 1][j] + cont[i - 1][j + 1]
+ cont[i][j + 1]
+ cont[i + 1][j] + cont[i + 1][j + 1])
// x x |
// x o |
// x x |
: j == static_cast<Difference2>(sprout::size(cont[i]) - 1)
? ::next_cell(
cont[i][j],
0
+ cont[i - 1][j - 1] + cont[i - 1][j]
+ cont[i][j - 1]
+ cont[i + 1][j - 1] + cont[i + 1][j]
)
// x x x
// x o x
// x x x
: ::next_cell(
cont[i][j],
0
+ cont[i - 1][j - 1] + cont[i - 1][j] + cont[i - 1][j + 1]
+ cont[i][j - 1] + cont[i][j + 1]
+ cont[i + 1][j - 1] + cont[i + 1][j] + cont[i + 1][j + 1]
)
;
}
namespace detail {
template<typename Container, sprout::index_t... Js>
inline SPROUT_CONSTEXPR typename sprout::container_traits<Container>::value_type
next_cells_2(Container const& cont, sprout::index_t i, sprout::index_tuple<Js...>) {
return sprout::remake<typename sprout::container_traits<Container>::value_type>(
cont[i], sprout::size(cont[i]),
::next_cell(cont, i, Js)...
);
}
template<typename Container, sprout::index_t... Is>
inline SPROUT_CONSTEXPR Container
next_cells_1(Container const& cont, sprout::index_tuple<Is...>) {
return sprout::remake<Container>(
cont, sprout::size(cont),
detail::next_cells_2(cont, Is, sprout::container_indexes<typename sprout::container_traits<Container>::value_type>::make())...
);
}
} // namespace detail
//
// next_cells
//
template<typename Container>
inline SPROUT_CONSTEXPR Container
next_cells(Container const& cont) {
return detail::next_cells_1(cont, sprout::container_indexes<Container>::make());
}
namespace detail {
struct gen_next_cells {
public:
template<typename Container>
SPROUT_CONSTEXPR sprout::pair<Container, Container>
operator()(Container const& cont) const {
return sprout::pair<Container, Container>(cont, ::next_cells(cont));
}
};
} // namespace detail
//
// next_cells
//
template<std::size_t N, typename Container>
inline SPROUT_CONSTEXPR sprout::array<Container, N>
next_cells(Container const& cont) {
return sprout::fixed::unfold<sprout::array<Container, N> >(detail::gen_next_cells(), cont);
}
#include <sprout/array.hpp>
#include <testspr/print.hpp>
#define BOARD_WIDTH 16
#define BOARD_HEIGHT 16
#define BOARD_COUNT 16
template<typename Container>
void SPROUT_NON_CONSTEXPR print_board(Container const& board) {
testspr::print_hl();
for (auto&& line : board) {
for (auto&& cell : line) {
testspr::print(cell ? "" : "", ' ');
}
testspr::print_ln();
}
}
int main() {
typedef sprout::array<sprout::array<int, BOARD_WIDTH>, BOARD_HEIGHT> board_type;
// セルの初期配置
#define _ 0
#define X 1
SPROUT_STATIC_CONSTEXPR board_type board0
{{
{{_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _}},
{{_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _}},
{{_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _}},
{{_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _}},
{{_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _}},
{{_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _}},
{{_, _, _, _, _, X, _, _, _, _, _, _, _, _, _, _}},
{{_, _, _, _, _, _, _, X, _, _, _, _, _, _, _, _}},
{{_, _, _, _, X, X, _, _, X, X, X, _, _, _, _, _}},
{{_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _}},
{{_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _}},
{{_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _}},
{{_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _}},
{{_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _}},
{{_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _}},
{{_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _}}
}};
#undef _
#undef X
// ライフゲームの実行
SPROUT_STATIC_CONSTEXPR auto boards = ::next_cells<BOARD_COUNT>(board0);
// 表示
for (auto&& board : boards) {
::print_board(board);
}
}

View file

@ -15,5 +15,6 @@
#include <sprout/stateful/typed_counter.hpp> #include <sprout/stateful/typed_counter.hpp>
#include <sprout/stateful/typed_rand.hpp> #include <sprout/stateful/typed_rand.hpp>
#include <sprout/stateful/typed_slot.hpp> #include <sprout/stateful/typed_slot.hpp>
#include <sprout/stateful/type_index.hpp>
#endif // #ifndef SPROUT_STATEFUL_HPP #endif // #ifndef SPROUT_STATEFUL_HPP

View file

@ -0,0 +1,95 @@
/*=============================================================================
Copyright (c) 2011-2015 Bolero MURAKAMI
https://github.com/bolero-MURAKAMI/Sprout
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#ifndef SPROUT_STATEFUL_TYPE_INDEX_HPP
#define SPROUT_STATEFUL_TYPE_INDEX_HPP
#include <typeinfo>
#include <sprout/config.hpp>
#include <sprout/workaround/std/cstddef.hpp>
#include <sprout/functional/hash.hpp>
#include <sprout/stateful/typed_id.hpp>
namespace sprout {
#ifndef SPROUT_CONFIG_DISABLE_CONSTEXPR
class type_index {
private:
int id_;
public:
template<typename T>
explicit SPROUT_CONSTEXPR type_index(sprout::typed_id<T>) SPROUT_NOEXCEPT
: id_(sprout::typed_id<T>::value)
{}
explicit SPROUT_CONSTEXPR type_index(int id) SPROUT_NOEXCEPT
: id_(id)
{}
SPROUT_CONSTEXPR bool
operator==(sprout::type_index const& rhs) const SPROUT_NOEXCEPT {
return id_ == rhs.id_;
}
SPROUT_CONSTEXPR bool
operator!=(sprout::type_index const& rhs) const SPROUT_NOEXCEPT {
return !(*this == rhs);
}
SPROUT_CONSTEXPR bool
operator<(sprout::type_index const& rhs) const SPROUT_NOEXCEPT {
return id_ < rhs.id_;
}
SPROUT_CONSTEXPR bool
operator<=(sprout::type_index const& rhs) const SPROUT_NOEXCEPT {
return !(rhs < *this);
}
SPROUT_CONSTEXPR bool
operator>(sprout::type_index const& rhs) const SPROUT_NOEXCEPT {
return rhs < *this;
}
SPROUT_CONSTEXPR bool
operator>=(sprout::type_index const& rhs) const SPROUT_NOEXCEPT {
return !(*this < rhs);
}
SPROUT_CONSTEXPR std::size_t
hash_code() const SPROUT_NOEXCEPT {
return sprout::hash_value(id_);
}
} ;
#endif
} // namespace sprout
#ifndef SPROUT_CONFIG_DISABLE_CONSTEXPR
namespace sprout {
//
// hash_value
//
inline SPROUT_CONSTEXPR std::size_t
hash_value(sprout::type_index const& v) {
return v.hash_code();
}
} // namespace sprout
namespace std {
#if defined(__clang__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wmismatched-tags"
#endif
//
// hash
//
template<>
struct hash<sprout::type_index>
: public sprout::hash<sprout::type_index>
{};
#if defined(__clang__)
# pragma clang diagnostic pop
#endif
} // namespace std
#endif
#endif // #ifndef SPROUT_STATEFUL_TYPE_INDEX_HPP