C++ Mathematical Expression Toolkit (ExprTk) release
Loading...
Searching...
No Matches
exprtk_game_of_life.cpp
Go to the documentation of this file.
1/*
2 **************************************************************
3 * C++ Mathematical Expression Toolkit Library *
4 * *
5 * ExprTk Conway's Game Of Life *
6 * Author: Arash Partow (1999-2024) *
7 * URL: https://www.partow.net/programming/exprtk/index.html *
8 * *
9 * Copyright notice: *
10 * Free use of the Mathematical Expression Toolkit Library is *
11 * permitted under the guidelines and in accordance with the *
12 * most current version of the MIT License. *
13 * https://www.opensource.org/licenses/MIT *
14 * SPDX-License-Identifier: MIT *
15 * *
16 **************************************************************
17*/
18
19
20#include <algorithm>
21#include <array>
22#include <chrono>
23#include <cstdio>
24#include <random>
25#include <string>
26#include <thread>
27
28#include "exprtk.hpp"
29
30
31template <typename T>
32struct rnd_01 final : public exprtk::ifunction<T>
33{
34 using exprtk::ifunction<T>::operator();
35
37 : exprtk::ifunction<T>(0)
38 {
39 std::random_device device;
40 std::array<unsigned int,std::mt19937::state_size> seed;
41 std::generate_n(seed.data(), seed.size(), std::ref(device));
42 std::seed_seq seq(std::begin(seed), std::end(seed));
43 generator.seed(seq);
44 }
45
46 inline T operator()() override
47 {
48 return distribution(generator);
49 }
50
51 std::mt19937 generator;
52 std::uniform_real_distribution<T> distribution{T(0),T(1)};
53};
54
55template <typename T>
57{
58 typedef exprtk::symbol_table<T> symbol_table_t;
59 typedef exprtk::expression<T> expression_t;
60 typedef exprtk::parser<T> parser_t;
61 typedef exprtk::function_compositor<T> compositor_t;
62 typedef typename compositor_t::function function_t;
63
64 const std::size_t width = 60;
65 const std::size_t height = 30;
66
67 std::vector<T> world(width * height, T(0));
68 rnd_01<T> rnd01;
70
71 symbol_table_t symbol_table;
72 symbol_table.add_constant("width" , static_cast<T>(width ));
73 symbol_table.add_constant("height", static_cast<T>(height));
74 symbol_table.add_vector ("world" , world);
75 symbol_table.add_package (io_package);
76 symbol_table.add_function("random", rnd01);
77 symbol_table.add_function("sleep" ,
78 [](T time) -> T
79 {
80 std::this_thread::sleep_for(
81 std::chrono::milliseconds(static_cast<std::size_t>(time)));
82 return T(1);
83 });
84
85 compositor_t compositor(symbol_table);
86
87 compositor.load_variables(true);
88 compositor.load_vectors (true);
89
90
91 compositor.add(
92 function_t("point")
93 .vars("x","y")
94 .expression
95 (
96 " world[y * width + x]; "
97 ));
98
99 compositor.add(
100 function_t("set_point")
101 .vars("x","y","value")
102 .expression
103 (
104 " world[y * width + x] := value; "
105 ));
106
107 compositor.add(
108 function_t("render")
109 .expression
110 (
111 " print('+'); "
112 " for (var x := 0; x < width; x += 1) { print('-'); } "
113 " println('+'); "
114 " "
115 " for (var y := 0; y < height; y += 1) "
116 " { "
117 " print('|'); "
118 " for (var x := 0; x < width; x += 1) "
119 " { "
120 " print( point(x,y) ? '*' : ' ' ); "
121 " }; "
122 " println('|'); "
123 " }; "
124 " "
125 " print('+'); "
126 " for (var x := 0; x < width; x += 1) { print('-'); } "
127 " println('+'); "
128 ));
129
130 compositor.add(
131 function_t("evolve")
132 .expression
133 (
134 " var next_world[world[]] := [0]; "
135 " "
136 " for (var y := 0; y < height; y += 1) "
137 " { "
138 " for (var x := 0; x < width; x += 1) "
139 " { "
140 " var alive_count := point(x,y) ? -1 : 0; "
141 " "
142 " for (var y1 := y - 1; y1 <= y + 1; y1 += 1) "
143 " { "
144 " var curr_y := (y1 + height) % height; "
145 " "
146 " for (var x1 := x - 1; x1 <= x + 1; x1 += 1) "
147 " { "
148 " var curr_x := (x1 + width) % width; "
149 " "
150 " if (point(curr_x,curr_y)) "
151 " { "
152 " alive_count += 1; "
153 " } "
154 " } "
155 " }; "
156 " "
157 " next_world[y * width + x] := "
158 " switch "
159 " { "
160 " case alive_count == 2 and point(x,y) : 1; "
161 " case alive_count == 3 : 1; "
162 " default : 0; "
163 " }; "
164 " } "
165 " }; "
166 " "
167 " world := next_world; "
168 ));
169
170 const std::string game_of_life_driver =
171 " /* Randomly setup the initial state of the world */ "
172 " for (var x := 0; x < width; x += 1) "
173 " { "
174 " for (var y := 0; y < height; y += 1) "
175 " { "
176 " set_point(x,y, (random() < 0.15) ? 1 : 0); "
177 " } "
178 " }; "
179 " "
180 " var num_generations := 200; "
181 " "
182 " for (var i := 0; i < num_generations; i += 1) "
183 " { "
184 " println('Generation: ', i); "
185 " render(); "
186 " evolve(); "
187 " sleep(200); "
188 " } ";
189
190 expression_t expression;
191 expression.register_symbol_table(symbol_table);
192
193 parser_t parser;
194 parser.compile(game_of_life_driver,expression);
195
196 expression.value();
197}
198
199int main()
200{
201 game_of_life<double>();
202 return 0;
203}
ifunction(const std::size_t &pc)
Definition exprtk.hpp:19545
int main()
void game_of_life()
std::uniform_real_distribution< T > distribution
std::mt19937 generator
T operator()() override