1
1
#include < algorithm>
2
2
#include < cassert>
3
+ #include < concepts>
3
4
#include < execution>
4
5
#include < format>
5
6
#include < iostream>
13
14
#include < utility>
14
15
#include < vector>
15
16
17
+ using Reel = std::vector<int >;
18
+
16
19
// Listing 9.1 Make the first few triangle numbers
17
- std::vector<int > make_triangle_numbers (int count)
20
+ // constexpr added in section 9.2
21
+ constexpr std::vector<int > make_triangle_numbers (int count)
18
22
{
19
23
std::vector<int > numbers (count);
20
24
std::iota (numbers.begin (), numbers.end (), 1 );
@@ -56,19 +60,36 @@ void demo_further_properties()
56
60
}
57
61
}
58
62
59
- // std::any_of
63
+ // Listing 9.5 Setup reels
64
+ template <std::invocable<std::vector<Reel>::iterator, std::vector<Reel>::iterator> T>
65
+ constexpr std::vector<Reel> make_reels (int numbers, int number_of_reels, T shuffle)
66
+ {
67
+ std::vector<Reel> reels (number_of_reels, make_triangle_numbers (numbers));
68
+
69
+ for (auto & reel : reels)
70
+ {
71
+ shuffle (reel.begin (), reel.end ());
72
+ }
73
+ return reels;
74
+ }
75
+
76
+ // Listing 9.6 Display reels
77
+ void show_reels (std::ostream& s, const std::vector<int >& left, const std::vector<int >& middle, const std::vector<int >& right)
78
+ {
79
+ s << std::format (" {:>3} {:>3} {:>3}\n " , left.back (), middle.back (), right.back ());
80
+ s << std::format (" -{:>3} {:>3} {:>3}-\n " , left[0 ], middle[0 ], right[0 ]);
81
+ s << std::format (" {:>3} {:>3} {:>3}\n " , left[1 ], middle[1 ], right[1 ]);
82
+ }
60
83
84
+ // Listing 9.7 Calculate payout
61
85
int calculate_payout_v1 (int left, int middle, int right)
62
86
{
63
- const int left_unit = left % 10 ;
64
- const int middle_unit = middle % 10 ;
65
- const int right_unit = right % 10 ;
66
87
int payout = 0 ;
67
- if (left_unit == middle_unit && middle_unit == right_unit )
88
+ if (left == middle && middle == right )
68
89
{
69
90
payout = 2 ;
70
91
}
71
- else if (left_unit == middle_unit || middle_unit == right_unit || left_unit == right_unit )
92
+ else if (left == middle || middle == right || left == right )
72
93
{
73
94
payout = 1 ;
74
95
}
@@ -85,7 +106,7 @@ std::map<int, size_t> frequencies(std::convertible_to<int> auto ...numbers)
85
106
86
107
int calculate_payout (int left, int middle, int right)
87
108
{
88
- std::map<int , size_t > counter= frequencies (left, middle, right);
109
+ std::map<int , size_t > counter = frequencies (left, middle, right);
89
110
// for loop first then dots:
90
111
// for (int number : {left, middle, right})
91
112
// {
@@ -116,7 +137,7 @@ int calculate_payout(int left, int middle, int right)
116
137
* The function-like entities described on this page are niebloids, that is:
117
138
* Explicit template argument lists cannot be specified when calling any of them.
118
139
* None of them are visible to argument-dependent lookup.
119
- * When any of them are found by normal unqualified lookup as the name to the left of the function-call operator,
140
+ * When any of them are found by normal unqualified lookup as the name to the left of the function-call operator,
120
141
* argument-dependent lookup is inhibited.
121
142
*/
122
143
auto it = std::max_element (counter.begin (), counter.end (),
@@ -127,45 +148,37 @@ int calculate_payout(int left, int middle, int right)
127
148
{
128
149
int digit = it->first ;
129
150
size_t count = it->second ;
130
- constexpr int value[] = {0 , 0 , 1 , 2 };
151
+ constexpr int value[] = { 0 , 0 , 1 , 2 };
131
152
auto pay = ((digit == 8 || digit == 3 ) ? 2 : 1 ) * value[count];
132
153
return pay;
133
154
}
134
155
return 0 ;
135
156
}
136
157
137
-
158
+ // Listing 9.8 A simple one armed bandit game
138
159
void triangle_machine_spins_only ()
139
160
{
140
161
constexpr int numbers = 20 ;
141
162
constexpr size_t number_of_reels = 3u ;
142
- std::vector<std::vector<int >> reels (number_of_reels, make_triangle_numbers (numbers));
143
163
std::random_device rd;
144
164
std::mt19937 gen{ rd () };
165
+ auto shuffle = [&gen](auto begin, auto end) { std::shuffle (begin, end, gen); };
145
166
146
- for (auto & reel : reels)
147
- {
148
- std::shuffle (reel.begin (), reel.end (), gen);
149
- }
167
+ std::vector<Reel> reels = make_reels (numbers, number_of_reels, shuffle);
150
168
151
- std::uniform_int_distribution dist (1 , numbers - 1 ); // int dis includes last number, but rotate mustn't use a middle equal to or beyond end
169
+ std::uniform_int_distribution dist (1 , numbers - 1 );
152
170
int credit = 1 ;
153
171
while (true )
154
172
{
155
- const int left = reels[0 ][0 ];
156
- const int middle = reels[1 ][0 ];
157
- const int right = reels[2 ][0 ];
158
- std::cout << std::format (" {:>3} {:>3} {:>3}\n " , reels[0 ][numbers - 1 ], reels[1 ][numbers - 1 ], reels[2 ][numbers - 1 ]);
159
- std::cout << std::format (" -{:>3} {:>3} {:>3}-\n " , reels[0 ][0 ], reels[1 ][0 ], reels[2 ][0 ]);
160
- std::cout << std::format (" {:>3} {:>3} {:>3}\n " , reels[0 ][1 ], reels[1 ][1 ], reels[2 ][1 ]);
173
+ show_reels (std::cout, reels[0 ], reels[1 ], reels[2 ]);
174
+ const int won = calculate_payout (reels[0 ][0 ]%10 , reels[1 ][0 ]%10 , reels[2 ][0 ]%10 );
161
175
--credit;
162
- int won = calculate_payout (left, middle, right);
163
176
credit += won;
164
177
std::cout << " won " << won << " credit = " << credit << ' \n ' ;
165
178
166
179
std::string response;
167
180
std::getline (std::cin, response);
168
- if (response == " q " ) // for quit
181
+ if (response != " " )
169
182
{
170
183
break ;
171
184
}
@@ -215,6 +228,13 @@ void check_properties()
215
228
assert (calculate_payout (0 , 0 , 0 ) == 2 );
216
229
assert (calculate_payout (3 , 3 , 3 ) == 4 );
217
230
assert (calculate_payout (8 , 8 , 8 ) == 4 );
231
+
232
+ constexpr auto no_op = [](auto begin, auto end) { };
233
+ static_assert (make_reels (1 , 1 , no_op).size () == 1 );
234
+
235
+ std::vector v{ 1 ,2 ,3 ,4 ,5 };
236
+ std::rotate (v.begin (), v.begin () + 3 , v.end ());
237
+ assert (v[0 ] == 4 );
218
238
}
219
239
220
240
int main ()
0 commit comments