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
|
#pragma once
#include "cell_helper.hpp"
#include <memory>
#include <range/v3/action/insert.hpp>
#include <range/v3/action/sort.hpp>
#include <range/v3/action/unique.hpp>
#include <range/v3/algorithm/count_if.hpp>
#include <range/v3/algorithm/fold_left.hpp>
#include <range/v3/range/conversion.hpp>
#include <range/v3/view/filter.hpp>
#include <utility>
template <typename MatrixElement>
CellHelper<MatrixElement>::CellHelper(
std::shared_ptr<IMatrix<MatrixElement>> matrix) noexcept
: _matrix(std::move(matrix))
{
}
template <typename MatrixElement>
auto CellHelper<MatrixElement>::compute_is_cell_dying(
const Vector2 &cell_pos) const noexcept -> bool
{
int64_t neighbour_cell_cnt = ranges::count_if(
_get_valid_pos_neighbours(cell_pos),
[this](const Vector2 &pos)
{
return _matrix->get(pos) == 'x';
});
return neighbour_cell_cnt < 2 || neighbour_cell_cnt >= 4;
}
template <typename MatrixElement>
auto CellHelper<MatrixElement>::compute_birth_cell_positions(
const std::vector<Vector2> &cell_positions) const noexcept -> std::vector<Vector2>
{
std::vector<Vector2> empty_neighbour_positions =
ranges::fold_left(
cell_positions,
std::vector<Vector2>(),
[this](std::vector<Vector2> acc, const Vector2 &pos)
{
std::vector<Vector2> neighbours = _get_valid_pos_neighbours(pos);
auto empty_neighbours =
neighbours | ranges::views::filter(
[this](const Vector2 &neighbour_pos)
{
return _matrix->get(neighbour_pos) == ' ';
});
ranges::actions::insert(acc, acc.end(), empty_neighbours);
return acc;
}) |
ranges::actions::sort | ranges::actions::unique;
auto birth_cell_positions = empty_neighbour_positions |
ranges::views::filter(
[this](const Vector2 &cell_pos)
{
auto neighbours =
_get_valid_pos_neighbours(cell_pos);
int64_t neighbour_cell_cnt = ranges::count_if(
neighbours,
[this](const Vector2 &neighbour_pos)
{
return _matrix->get(neighbour_pos) == 'x';
});
return neighbour_cell_cnt == 3;
});
return birth_cell_positions | ranges::to<std::vector>();
}
template <typename MatrixElement>
auto CellHelper<MatrixElement>::_get_valid_pos_neighbours(
const Vector2 &position) const noexcept -> std::vector<Vector2>
{
const auto neighbours = {
position + Vector2::up(),
position + Vector2::down(),
position + Vector2::left(),
position + Vector2::right(),
position + Vector2::up() + Vector2::left(),
position + Vector2::up() + Vector2::right(),
position + Vector2::down() + Vector2::left(),
position + Vector2::down() + Vector2::right()};
const auto matrix_size =
Bounds({.width = _matrix->get_column_cnt(), .height = _matrix->get_row_cnt()});
return neighbours |
ranges::views::filter(
[&matrix_size](const Vector2 &neighbour_pos)
{
return matrix_size.validate_coords(neighbour_pos) ==
CoordsValidation::VALID;
}) |
ranges::to<std::vector>();
}
|