challenge ライフゲーム

セルオートマトンに関するお題です. 
2次元タイプの'ライフゲーム'を実装して下さい. 
初期値としては10行10列程度の格子上の平面に0.3程度の人口(?)密度を考え, 
末端はループするようにして下さい. (例: 座標[-1, -1] = [10, 10])

それだけだと簡単すぎると思われる方は, 
過密状態で間引きが発生するような機能を組み込んで下さい. 
間引きは, 少なくともその後の1時間ステップにおける死亡率が, 
それをしなかった場合よりも小さくなれば結構です. 
(死亡率の最小化は複雑性が高すぎる感がありますし. )
サンプル:
t = 0
[ ][*][ ][ ][ ][ ][*][*][*][ ]
[ ][ ][ ][ ][*][ ][ ][*][*][ ]
[ ][ ][ ][*][ ][ ][*][ ][*][ ]
[*][ ][*][*][ ][ ][*][ ][ ][ ]
[ ][*][ ][ ][ ][ ][ ][ ][*][ ]
[*][ ][ ][ ][*][ ][*][*][ ][*]
[ ][*][ ][ ][ ][ ][*][ ][ ][ ]
[ ][ ][ ][ ][ ][ ][ ][ ][ ][*]
[*][ ][ ][ ][ ][ ][*][ ][ ][*]
[ ][ ][ ][ ][*][*][ ][ ][*][ ]
t = 1
[ ][ ][ ][ ][*][ ][ ][ ][ ][*]
[ ][ ][ ][ ][ ][*][ ][ ][ ][*]
[ ][ ][*][ ][*][*][*][ ][*][*]
[ ][*][ ][*][ ][ ][ ][ ][ ][*]
[ ][ ][*][*][ ][*][*][ ][*][ ]
[ ][*][ ][ ][ ][*][*][ ][*][*]
[ ][ ][ ][ ][ ][*][*][*][*][*]
[ ][ ][ ][ ][ ][ ][ ][ ][ ][*]
[*][ ][ ][ ][ ][*][ ][ ][*][ ]
[*][ ][ ][ ][ ][ ][ ][ ][ ][ ]

Posted feedbacks - C++

実直に組んでみました。C++っぽさが出てるといいんですが...

# 間引きはよくわからなかったので未対応です。

  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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
#include <iostream>
#include <vector>
#include <cstdlib>
#include <algorithm>
#include <iterator>
#include <utility>
#include <string>

class Cell
{
  bool is_alive_;

  public:
  Cell();
  bool is_alive() const;
  void born();
  void die();
};

std::ostream& operator<<(std::ostream& os, const Cell& c);

class Rule
{
  std::vector<int> alive_cond_;
  std::vector<int> born_cond_;
  public:
  Rule(const std::string& alive_cond, const std::string& born_cond); 
  bool operator()(bool is_alive, int surround_alives) const;
};

class CellTable
{
  std::vector<Cell> cells_;
  int xmax_, ymax_;

  public:
  CellTable(int xmax, int ymax);

  void proceed_next_gen(const CellTable& current_gen, const Rule& rule);

  void swap(CellTable& ct);

  const Cell& get_cell(int x, int y) const;
  Cell& get_cell(int x, int y);

  private:
  friend
    std::ostream& operator<<(std::ostream& os, const CellTable& ct);
};

std::ostream& operator<<(std::ostream& os, const CellTable& ct);

// Cell の実装
Cell::Cell() : is_alive_(false) {}
bool Cell::is_alive() const { return this->is_alive_; }
void Cell::born() { this->is_alive_ = true; }
void Cell::die() { this->is_alive_ = false; }

std::ostream& operator<<(std::ostream& os, const Cell& c)
{
  return os << "[" << (c.is_alive() ? "*" : " ") << "]";
}

// Rule の実装
Rule::Rule(const std::string& alive_cond, const std::string& born_cond)
{
  std::string::const_iterator cit;
  for ( cit = alive_cond.begin(); cit != alive_cond.end(); ++cit )
    if ( '0' <= *cit && *cit <= '8' )
      alive_cond_.push_back(*cit - '0');
  std::sort(alive_cond_.begin(), alive_cond_.end());

  for ( cit = born_cond.begin(); cit != born_cond.end(); ++cit )
    if ( '0' <= *cit && *cit <= '8' )
      born_cond_.push_back(*cit - '0');
  std::sort(born_cond_.begin(), born_cond_.end());
}

bool Rule::operator()(bool is_alive, int surround_alives)
  const
{
  if ( !is_alive &&
       std::binary_search(born_cond_.begin(), born_cond_.end(), surround_alives) )
    // born
    return true;
  else if ( is_alive && 
      std::binary_search(alive_cond_.begin(), alive_cond_.end(), surround_alives ) )
    // still alive
    return true;

  // die
  return false;
}

// CellTable の実装
CellTable::CellTable(int xmax, int ymax)
  : xmax_(xmax), ymax_(ymax)
{
  if ( xmax_ <= 0 || ymax_ <= 0 )
    throw "invalid xmax or ymax!";
  cells_.resize(xmax_*ymax_);
}

void
CellTable::proceed_next_gen(const CellTable& current_gen, const Rule& rule)
{
  for ( int x = 0; x < xmax_; ++x ) {
    for ( int y = 0; y < ymax_; ++y ) {
      int surround_alives = 0;
      for ( int dx = -1; dx < 2; ++dx )
        for (int dy = -1; dy < 2; ++dy )
          if ( !(dx == 0 && dy == 0) && current_gen.get_cell(x+dx,y+dy).is_alive() )
            ++surround_alives;

      const Cell& current_cell = current_gen.get_cell(x,y);
      Cell& next_cell = this->get_cell(x,y);
      if ( rule(current_cell.is_alive(), surround_alives) )
        // born or alive
        next_cell.born();
      else
        // die
        next_cell.die();
    }
  }
}

void
CellTable::swap(CellTable& ct)
{
  cells_.swap(ct.cells_);
  std::swap(xmax_, ct.xmax_);
  std::swap(ymax_, ct.ymax_);
}

const Cell&
CellTable::get_cell(int x, int y) 
  const
{
  while ( x < 0 ) x += xmax_;
  while ( y < 0 ) y += ymax_;
  return cells_[(x%xmax_)+((y%ymax_)*xmax_)];
}

Cell&
CellTable::get_cell(int x, int y) 
{
  while ( x < 0 ) x += xmax_;
  while ( y < 0 ) y += ymax_;
  return cells_[(x%xmax_)+((y%ymax_)*xmax_)];
}

std::ostream&
operator<<(std::ostream& os, const CellTable& ct)
{
  std::vector<Cell>::const_iterator it = ct.cells_.begin();
  while ( it != ct.cells_.end() ) {
    std::copy(
        it, it+ct.xmax_,
        std::ostream_iterator<Cell>(os, "") );
    os << "\n";
    std::advance(it, ct.xmax_);
  }
  return os;
}

const char* const first_pattern =
// ja.doukaku.org 例題パターン
#if 0
"0100001110"
"0000100110"
"0001001010"
"1011001000"
"0100000010"
"1000101101"
"0100001000"
"0000000001"
"1000001001"
"0000110010";
#endif
// グライダーパターン
#if 1
"0000000000"
"0000000000"
"0000000000"
"0000000000"
"0001000000"
"0010000000"
"0011100000"
"0000000000"
"0000000000"
"0000000000";
#endif

int main(int argc, char** argv)
{
  int xmax = 10, ymax = 10;
  int max_gen = 256;

  CellTable current(xmax,ymax), next(xmax,ymax);

  // create first pattern
  const char *p = first_pattern;
  for ( int y = 0; y < ymax; ++y )
    for ( int x = 0; x < xmax; ++x )
      if (*p++ == '1')
        current.get_cell(x,y).born();

  // ja.doukaku.org 出題の 2/3 ルール
  //const Rule rule("2", "3");
  // 標準的な 23/3 ルール
  const Rule rule("23", "3");

  for (int t = 0; t < max_gen; ++t) {
    std::cout << "t = " << t << "\n" << current;

    next.proceed_next_gen(current, rule);
    current.swap(next);
  } 
  return 0;
}

Index

Feed

Other

Link

Pathtraq

loading...