-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstatistic.h
175 lines (160 loc) · 5.17 KB
/
statistic.h
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
#pragma once
#include <list>
#include <vector>
#include <algorithm>
#include <iostream>
#include <chrono>
#include <numeric>
#include "board.h"
#include "action.h"
#include "agent.h"
//unsigned int fibo_seq[18] = {0, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 258 } ;
class statistic {
public:
statistic(const size_t& total, const size_t& block = 0) : total(total), block(block ? block : total) {}
public:
/**
* show the statistic of last 'block' games
*
* the format would be
* 1000 avg = 273901, max = 382324, ops = 241563
* 512 100% (0.3%)
* 1024 99.7% (0.2%)
* 2048 99.5% (1.1%)
* 4096 98.4% (4.7%)
* 8192 93.7% (22.4%)
* 16384 71.3% (71.3%)
*
* where (assume that block = 1000)
* '1000': current index (n)
* 'avg = 273901': the average score of saved games is 273901
* 'max = 382324': the maximum score of saved games is 382324
* 'ops = 241563': the average speed of saved games is 241563
* '93.7%': 93.7% (937 games) reached 8192-tiles in saved games (a.k.a. win rate of 8192-tile)
* '22.4%': 22.4% (224 games) terminated with 8192-tiles (the largest) in saved games
*/
void show() const {
int block = std::min(data.size(), this->block);
size_t sum = 0, max = 0, opc = 0, stat[16] = { 0 };
uint64_t duration = 0;
auto it = data.end();
for (int i = 0; i < block; i++) {
auto& path = *(--it);
board game;
size_t score = 0;
for (const action& move : path){
score += move.apply(game);
//std::cout << "Action :" << move.name() << '\n' ;
//std::cout << "Score :" << score << '\n';
//std::cout << "Results: \n" << game << '\n' ;
}
sum += score;
max = std::max(score, max);
opc += (path.size() - 2) / 2;
int tile = 0;
for (int i = 0; i < 16; i++)
tile = std::max(tile, game(i));
stat[tile]++;
duration += (path.tock_time() - path.tick_time());
}
float avg = float(sum) / block;
float coef = 100.0 / block;
float ops = opc * 1000.0 / duration;
std::cout << data.size() << "\t";
std::cout << "avg = " << int(avg) << ", ";
std::cout << "max = " << int(max) << ", ";
std::cout << "ops = " << int(ops) << std::endl;
for (int t = 0, c = 0; c < block; c += stat[t++]) {
if (stat[t] == 0) continue;
int accu = std::accumulate(stat + t, stat + 16, 0);
std::cout << "\t" << fibo_seq[ t ] << "\t" << (accu * coef) << "%";
std::cout << "\t(" << (stat[t] * coef) << "%)" << std::endl;
}
std::cout << std::endl;
}
void summary() const {
auto block_temp = block;
const_cast<statistic&>(*this).block = data.size();
show();
const_cast<statistic&>(*this).block = block_temp;
}
bool is_finished() const {
return data.size() >= total;
}
void open_episode(const std::string& flag = "") {
data.emplace_back();
data.back().tick();
}
void close_episode(const std::string& flag = "") {
data.back().tock();
if (data.size() % block == 0) show();
}
board make_empty_board() {
return {};
}
void save_action(const action& move) {
data.back().push_back(move);
}
agent& take_turns(agent& play, agent& evil) {
return (std::max(data.back().size() + 1, size_t(2)) % 2) ? play : evil;
}
agent& last_turns(agent& play, agent& evil) {
return take_turns(evil, play);
}
friend std::ostream& operator <<(std::ostream& out, const statistic& stat) {
auto size = stat.data.size();
out.write(reinterpret_cast<char*>(&size), sizeof(size));
for (const record& rec : stat.data) out << rec;
return out;
}
friend std::istream& operator >>(std::istream& in, statistic& stat) {
auto size = stat.data.size();
in.read(reinterpret_cast<char*>(&size), sizeof(size));
stat.total = stat.block = size;
stat.data.resize(size);
for (record& rec : stat.data) in >> rec;
return in;
}
private:
class record : public std::vector<action> {
public:
record() { reserve(32768); }
void tick() { time[0] = milli(); }
void tock() { time[1] = milli(); }
uint64_t tick_time() const { return time[0]; }
uint64_t tock_time() const { return time[1]; }
friend std::ostream& operator <<(std::ostream& out, const record& rec) {
auto size = rec.size();
auto time = rec.time;
out.write(reinterpret_cast<char*>(&size), sizeof(size));
for (const action& act : rec) {
short opcode = int(act);
out.write(reinterpret_cast<const char*>(&opcode), sizeof(opcode));
}
out.write(reinterpret_cast<const char*>(time), sizeof(time[0]) * 2);
return out;
}
friend std::istream& operator >>(std::istream& in, record& rec) {
auto size = rec.size();
auto time = rec.time;
in.read(reinterpret_cast<char*>(&size), sizeof(size));
rec.reserve(size);
for (size_t i = 0; i < size; i++) {
short opcode;
in.read(reinterpret_cast<char*>(&opcode), sizeof(opcode));
rec.emplace_back(int(opcode));
}
in.read(reinterpret_cast<char*>(time), sizeof(time[0]) * 2);
return in;
}
private:
uint64_t milli() const {
auto now = std::chrono::system_clock::now().time_since_epoch();
return std::chrono::duration_cast<std::chrono::milliseconds>(now).count();
}
uint64_t time[2];
};
size_t total;
size_t block;
std::list<record> data;
};