1 /* Copyright (C) 2013-2014 Michal Brzozowski (rusolis@poczta.fm)
2
3 This file is part of KeeperRL.
4
5 KeeperRL is free software; you can redistribute it and/or modify it under the terms of the
6 GNU General Public License as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 KeeperRL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along with this program.
14 If not, see http://www.gnu.org/licenses/ . */
15
16 #include "stdafx.h"
17
18 #include "util.h"
19 #include "position.h"
20
init(int seed)21 void RandomGen::init(int seed) {
22 generator.seed(seed);
23 }
24
get(int max)25 int RandomGen::get(int max) {
26 return get(0, max);
27 }
28
getLL()29 long long RandomGen::getLL() {
30 return uniform_int_distribution<long long>(-(1LL << 62), 1LL << 62)(generator);
31 }
32
get(Range r)33 int RandomGen::get(Range r) {
34 return get(r.getStart(), r.getEnd());
35 }
36
get(int min,int max)37 int RandomGen::get(int min, int max) {
38 CHECK(max > min);
39 return uniform_int_distribution<int>(min, max - 1)(generator);
40 }
41
operator ""_s(const char * str,size_t)42 std::string operator "" _s(const char* str, size_t) {
43 return std::string(str);
44 }
45
getCardinalName(Dir d)46 string getCardinalName(Dir d) {
47 switch (d) {
48 case Dir::N: return "north";
49 case Dir::S: return "south";
50 case Dir::E: return "east";
51 case Dir::W: return "west";
52 case Dir::NE: return "north-east";
53 case Dir::NW: return "north-west";
54 case Dir::SE: return "south-east";
55 case Dir::SW: return "south-west";
56 }
57 }
58
get(const vector<double> & weights)59 int RandomGen::get(const vector<double>& weights) {
60 double sum = 0;
61 for (double elem : weights)
62 sum += elem;
63 CHECK(sum > 0);
64 double r = getDouble(0, sum);
65 sum = 0;
66 for (int i : All(weights)) {
67 sum += weights[i];
68 if (sum >= r)
69 return i;
70 }
71 return weights.size() - 1;
72 }
73
roll(int chance)74 bool RandomGen::roll(int chance) {
75 return get(chance) == 0;
76 }
77
chance(double v)78 bool RandomGen::chance(double v) {
79 return getDouble(0, 1) <= v;
80 }
81
getDouble()82 double RandomGen::getDouble() {
83 return defaultDist(generator);
84 }
85
getDouble(double a,double b)86 double RandomGen::getDouble(double a, double b) {
87 return uniform_real_distribution<double>(a, b)(generator);
88 }
89
90 RandomGen Random;
91
92 template string toString<int>(const int&);
93 template string toString<unsigned int>(const unsigned int&);
94 //template string toString<size_t>(const size_t&);
95 template string toString<char>(const char&);
96 template string toString<double>(const double&);
97 //template string toString<Vec2>(const Vec2&);
98
99 template int fromString<int>(const string&);
100 template double fromString<double>(const string&);
101
102 template optional<int> fromStringSafe<int>(const string&);
103 template optional<double> fromStringSafe<double>(const string&);
104
105
106 template <class T>
fromStringSafe(const string & s)107 optional<T> fromStringSafe(const string& s){
108 std::stringstream ss(s);
109 T t;
110 ss >> t;
111 if (!ss)
112 return none;
113 return t;
114 }
115
trim(string & s)116 void trim(string& s) {
117 while (!s.empty() && isspace(s[0]))
118 s.erase(s.begin());
119 while (!s.empty() && isspace(*s.rbegin()))
120 s.erase(s.size() - 1);
121 }
122
toUpper(const string & s)123 string toUpper(const string& s) {
124 string ret(s);
125 transform(ret.begin(), ret.end(), ret.begin(), ::toupper);
126 return ret;
127 }
128
toLower(const string & s)129 string toLower(const string& s) {
130 string ret(s);
131 transform(ret.begin(), ret.end(), ret.begin(), ::tolower);
132 return ret;
133 }
134
endsWith(const string & s,const string & suffix)135 bool endsWith(const string& s, const string& suffix) {
136 return s.size() >= suffix.size() && s.substr(s.size() - suffix.size()) == suffix;
137 }
138
split(const string & s,const set<char> & delim)139 vector<string> split(const string& s, const set<char>& delim) {
140 if (s.empty())
141 return {};
142 int begin = 0;
143 vector<string> ret;
144 for (int i : Range(s.size() + 1))
145 if (i == s.size() || delim.count(s[i])) {
146 string tmp = s.substr(begin, i - begin);
147 ret.push_back(tmp);
148 begin = i + 1;
149 }
150 return ret;
151 }
152
contains(const string & s,const string & p)153 bool contains(const string& s, const string& p) {
154 return s.find(p) != string::npos;
155 }
156
toString(const Vec2 & v)157 string toString(const Vec2& v) {
158 stringstream ss;
159 ss << "(" << v.x << ", " << v.y << ")";
160 return ss.str();
161 }
162
Vec2(int _x,int _y)163 Vec2::Vec2(int _x, int _y) : x(_x), y(_y) {
164 }
165
Vec2(Dir dir)166 Vec2::Vec2(Dir dir) {
167 switch (dir) {
168 case Dir::N: x = 0; y = -1; break;
169 case Dir::S: x = 0; y = 1; break;
170 case Dir::E: x = 1; y = 0; break;
171 case Dir::W: x = -1; y = 0; break;
172 case Dir::NE: x = 1; y = -1; break;
173 case Dir::SE: x = 1; y = 1; break;
174 case Dir::NW: x = -1; y = -1; break;
175 case Dir::SW: x = -1; y = 1; break;
176 }
177 }
178
mult(const Vec2 & v) const179 Vec2 Vec2::mult(const Vec2& v) const {
180 return Vec2(x * v.x, y * v.y);
181 }
182
div(const Vec2 & v) const183 Vec2 Vec2::div(const Vec2& v) const {
184 return Vec2(x / v.x, y / v.y);
185 }
186
dotProduct(Vec2 a,Vec2 b)187 int Vec2::dotProduct(Vec2 a, Vec2 b) {
188 return a.x * b.x + a.y * b.y;
189 }
190
191 static const vector<Vec2> dir8 {
192 Vec2(0, -1), Vec2(0, 1), Vec2(1, 0), Vec2(-1, 0), Vec2(1, -1), Vec2(-1, -1), Vec2(1, 1), Vec2(-1, 1)
193 };
194
directions8()195 const vector<Vec2>& Vec2::directions8() {
196 return dir8;
197 }
198
neighbors8() const199 vector<Vec2> Vec2::neighbors8() const {
200 return {Vec2(x, y + 1), Vec2(x + 1, y), Vec2(x, y - 1), Vec2(x - 1, y), Vec2(x + 1, y + 1), Vec2(x + 1, y - 1),
201 Vec2(x - 1, y - 1), Vec2(x - 1, y + 1)};
202 }
203
204 static const vector<Vec2> dir4 {
205 Vec2(0, -1), Vec2(0, 1), Vec2(1, 0), Vec2(-1, 0)
206 };
207
directions4()208 const vector<Vec2>& Vec2::directions4() {
209 return dir4;
210 }
211
neighbors4() const212 vector<Vec2> Vec2::neighbors4() const {
213 return { Vec2(x, y + 1), Vec2(x + 1, y), Vec2(x, y - 1), Vec2(x - 1, y)};
214 }
215
directions8(RandomGen & random)216 vector<Vec2> Vec2::directions8(RandomGen& random) {
217 return random.permutation(directions8());
218 }
219
neighbors8(RandomGen & random) const220 vector<Vec2> Vec2::neighbors8(RandomGen& random) const {
221 return random.permutation(neighbors8());
222 }
223
directions4(RandomGen & random)224 vector<Vec2> Vec2::directions4(RandomGen& random) {
225 return random.permutation(directions4());
226 }
227
neighbors4(RandomGen & random) const228 vector<Vec2> Vec2::neighbors4(RandomGen& random) const {
229 return random.permutation(neighbors4());
230 }
231
isCardinal4() const232 bool Vec2::isCardinal4() const {
233 return abs(x) + abs(y) == 1;
234 }
235
isCardinal8() const236 bool Vec2::isCardinal8() const {
237 return max(abs(x), abs(y)) == 1;
238 }
239
getCardinalDir() const240 Dir Vec2::getCardinalDir() const {
241 switch (x) {
242 case 0:
243 switch (y) {
244 case -1: return Dir::N;
245 case 1: return Dir::S;
246 }
247 break;
248 case 1:
249 switch (y) {
250 case 0: return Dir::E;
251 case -1: return Dir::NE;
252 case 1: return Dir::SE;
253 }
254 break;
255 case -1:
256 switch (y) {
257 case 0: return Dir::W;
258 case -1: return Dir::NW;
259 case 1: return Dir::SW;
260 }
261 break;
262 }
263 FATAL << "Not cardinal dir " << *this;
264 return {};
265 }
266
corners()267 vector<Vec2> Vec2::corners() {
268 return { Vec2(1, 1), Vec2(1, -1), Vec2(-1, -1), Vec2(-1, 1)};
269 }
270
calculateLayers(set<Vec2> elems)271 vector<set<Vec2>> Vec2::calculateLayers(set<Vec2> elems) {
272 vector<set<Vec2>> ret;
273 while (1) {
274 ret.emplace_back();
275 set<Vec2> curElems(elems);
276 for (Vec2 v : curElems)
277 for (Vec2 v2 : v.neighbors4())
278 if (!curElems.count(v2)) {
279 ret.back().insert(v);
280 elems.erase(v);
281 break;
282 }
283 if (elems.empty())
284 break;
285 }
286 return ret;
287 }
288
289 SERIALIZE_DEF(Rectangle, px, py, kx, ky, w, h)
290
291 SERIALIZATION_CONSTRUCTOR_IMPL(Rectangle);
292
boundingBox(const vector<Vec2> & verts)293 Rectangle Rectangle::boundingBox(const vector<Vec2>& verts) {
294 CHECK(!verts.empty());
295 int infinity = 1000000;
296 int minX = infinity, maxX = -infinity, minY = infinity, maxY = -infinity;
297 for (Vec2 v : verts) {
298 minX = min(minX, v.x);
299 maxX = max(maxX, v.x);
300 minY = min(minY, v.y);
301 maxY = max(maxY, v.y);
302 }
303 return Rectangle(minX, minY, maxX + 1, maxY + 1);
304 }
305
centered(Vec2 center,int radius)306 Rectangle Rectangle::centered(Vec2 center, int radius) {
307 return Rectangle(center - Vec2(radius, radius), center + Vec2(radius + 1, radius + 1));
308 }
309
centered(int radius)310 Rectangle Rectangle::centered(int radius) {
311 return Rectangle(-Vec2(radius, radius), Vec2(radius + 1, radius + 1));
312 }
313
getAllSquares() const314 vector<Vec2> Rectangle::getAllSquares() const {
315 vector<Vec2> ret;
316 for (Vec2 v : (*this))
317 ret.push_back(v);
318 return ret;
319 }
320
apply(Vec2::LinearMap map) const321 Rectangle Rectangle::apply(Vec2::LinearMap map) const {
322 Vec2 v1 = map(Vec2(px, py));
323 Vec2 v2 = map(Vec2(kx - 1, ky - 1));
324 return Rectangle(min(v1.x, v2.x), min(v1.y, v2.y), max(v1.x, v2.x) + 1, max(v1.y, v2.y) + 1);
325 }
326
operator ==(const Rectangle & r) const327 bool Rectangle::operator == (const Rectangle& r) const {
328 return px == r.px && py == r.py && kx == r.kx && ky == r.ky;
329 }
330
operator !=(const Rectangle & r) const331 bool Rectangle::operator != (const Rectangle& r) const {
332 return !(*this == r);
333 }
334
335 template <class Archive>
serialize(Archive & ar,const unsigned int)336 void Vec2::serialize(Archive& ar, const unsigned int) {
337 ar(x, y);
338 }
339
340 SERIALIZABLE(Vec2);
341
inRectangle(int px,int py,int kx,int ky) const342 bool Vec2::inRectangle(int px, int py, int kx, int ky) const {
343 return x >= px && x < kx && y >= py && y < ky;
344 }
345
inRectangle(const Rectangle & r) const346 bool Vec2::inRectangle(const Rectangle& r) const {
347 return x >= r.px && x < r.kx && y >= r.py && y < r.ky;
348 }
349
operator ==(const Vec2 & v) const350 bool Vec2::operator== (const Vec2& v) const {
351 return v.x == x && v.y == y;
352 }
353
operator !=(const Vec2 & v) const354 bool Vec2::operator!= (const Vec2& v) const {
355 return v.x != x || v.y != y;
356 }
357
operator +=(const Vec2 & v)358 Vec2& Vec2::operator +=(const Vec2& v) {
359 x += v.x;
360 y += v.y;
361 return *this;
362 }
363
operator +(const Vec2 & v) const364 Vec2 Vec2::operator + (const Vec2& v) const {
365 return Vec2(x + v.x, y + v.y);
366 }
367
operator *(int a) const368 Vec2 Vec2::operator * (int a) const {
369 return Vec2(x * a, y * a);
370 }
371
operator *(double a) const372 Vec2 Vec2::operator * (double a) const {
373 return Vec2(x * a, y * a);
374 }
375
operator /(int a) const376 Vec2 Vec2::operator / (int a) const {
377 return Vec2(x / a, y / a);
378 }
379
operator -=(const Vec2 & v)380 Vec2& Vec2::operator -=(const Vec2& v) {
381 x -= v.x;
382 y -= v.y;
383 return *this;
384 }
385
operator -(const Vec2 & v) const386 Vec2 Vec2::operator - (const Vec2& v) const {
387 return Vec2(x - v.x, y - v.y);
388 }
389
operator -() const390 Vec2 Vec2::operator - () const {
391 return Vec2(-x, -y);
392 }
393
operator <(Vec2 v) const394 bool Vec2::operator < (Vec2 v) const {
395 return x < v.x || (x == v.x && y < v.y);
396 }
397
length8() const398 int Vec2::length8() const {
399 return max(abs(x), abs(y));
400 }
401
dist8(Vec2 v) const402 int Vec2::dist8(Vec2 v) const {
403 return (v - *this).length8();
404 }
405
distD(Vec2 v) const406 double Vec2::distD(Vec2 v) const {
407 return (v - *this).lengthD();
408 }
409
length4() const410 int Vec2::length4() const {
411 return abs(x) + abs(y);
412 }
413
lengthD() const414 double Vec2::lengthD() const {
415 return sqrt(x * x + y * y);
416 }
417
shorten() const418 Vec2 Vec2::shorten() const {
419 CHECK(x == 0 || y == 0 || abs(x) == abs(y));
420 int d = length8();
421 return Vec2(x / d, y / d);
422 }
423
sgn(int a)424 static int sgn(int a) {
425 if (a == 0)
426 return 0;
427 if (a < 0)
428 return -1;
429 else
430 return 1;
431 }
432
sgn(int a,int b)433 static int sgn(int a, int b) {
434 if (abs(a) >= abs(b))
435 return sgn(a);
436 else
437 return 0;
438 }
439
approxL1() const440 pair<Vec2, Vec2> Vec2::approxL1() const {
441 return make_pair(Vec2(sgn(x, x), sgn(y,y)), Vec2(sgn(x, y), sgn(y, x)));
442 }
443
getBearing() const444 Vec2 Vec2::getBearing() const {
445 double ang = atan2(y, x) / 3.14159265359 * 180 / 45;
446 if (ang < 0)
447 ang += 8;
448 if (ang < 0.5 || ang >= 7.5)
449 return Vec2(1, 0);
450 if (ang >= 0.5 && ang < 1.5)
451 return Vec2(1, 1);
452 if (ang >= 1.5 && ang < 2.5)
453 return Vec2(0, 1);
454 if (ang >= 2.5 && ang < 3.5)
455 return Vec2(-1, 1);
456 if (ang >= 3.5 && ang < 4.5)
457 return Vec2(-1, 0);
458 if (ang >= 4.5 && ang < 5.5)
459 return Vec2(-1, -1);
460 if (ang >= 5.5 && ang < 6.5)
461 return Vec2(0, -1);
462 if (ang >= 6.5 && ang < 7.5)
463 return Vec2(1, -1);
464 FATAL << ang;
465 return Vec2(0, 0);
466 }
467
getCenterOfWeight(vector<Vec2> vs)468 Vec2 Vec2::getCenterOfWeight(vector<Vec2> vs) {
469 Vec2 ret;
470 for (Vec2 v : vs)
471 ret += v;
472 return ret / vs.size();
473 }
474
Rectangle(int _w,int _h)475 Rectangle::Rectangle(int _w, int _h) : px(0), py(0), kx(_w), ky(_h), w(_w), h(_h) {
476 if (w <= 0 || h <= 0) {
477 kx = ky = 0;
478 w = h = 0;
479 }
480 }
481
Rectangle(Vec2 d)482 Rectangle::Rectangle(Vec2 d) : Rectangle(d.x, d.y) {
483 }
484
Rectangle(int px1,int py1,int kx1,int ky1)485 Rectangle::Rectangle(int px1, int py1, int kx1, int ky1) : px(px1), py(py1), kx(kx1), ky(ky1), w(kx1 - px1),
486 h(ky1 - py1) {
487 if (kx <= px || ky <= py) {
488 kx = px;
489 ky = py;
490 w = h = 0;
491 }
492 }
493
Rectangle(Vec2 p,Vec2 k)494 Rectangle::Rectangle(Vec2 p, Vec2 k) : Rectangle(p.x, p.y, k.x, k.y) {
495 }
496
Rectangle(Range xRange,Range yRange)497 Rectangle::Rectangle(Range xRange, Range yRange)
498 : Rectangle(xRange.getStart(), yRange.getStart(), xRange.getEnd(), yRange.getEnd()) {
499 }
500
Iter(int x1,int y1,int px1,int py1,int kx1,int ky1)501 Rectangle::Iter::Iter(int x1, int y1, int px1, int py1, int kx1, int ky1) : pos(x1, y1), px(px1), py(py1), kx(kx1), ky(ky1) {}
502
randomVec2() const503 Vec2 Rectangle::randomVec2() const {
504 return Vec2(Random.get(px, kx), Random.get(py, ky));
505 }
506
middle() const507 Vec2 Rectangle::middle() const {
508 return Vec2((px + kx) / 2, (py + ky) / 2);
509 }
510
left() const511 int Rectangle::left() const {
512 return px;
513 }
514
top() const515 int Rectangle::top() const {
516 return py;
517 }
518
getXRange() const519 Range Rectangle::getXRange() const {
520 return Range(px, kx);
521 }
522
getYRange() const523 Range Rectangle::getYRange() const {
524 return Range(py, ky);
525 }
526
right() const527 int Rectangle::right() const {
528 return kx;
529 }
530
bottom() const531 int Rectangle::bottom() const {
532 return ky;
533 }
534
width() const535 int Rectangle::width() const {
536 return w;
537 }
538
height() const539 int Rectangle::height() const {
540 return h;
541 }
542
area() const543 int Rectangle::area() const {
544 return w * h;
545 }
546
getSize() const547 Vec2 Rectangle::getSize() const {
548 return Vec2(w, h);
549 }
550
topLeft() const551 Vec2 Rectangle::topLeft() const {
552 return Vec2(px, py);
553 }
554
bottomRight() const555 Vec2 Rectangle::bottomRight() const {
556 return Vec2(kx, ky);
557 }
558
topRight() const559 Vec2 Rectangle::topRight() const {
560 return Vec2(kx, py);
561 }
562
bottomLeft() const563 Vec2 Rectangle::bottomLeft() const {
564 return Vec2(px, ky);
565 }
566
intersects(const Rectangle & other) const567 bool Rectangle::intersects(const Rectangle& other) const {
568 return max(px, other.px) < min(kx, other.kx) && max(py, other.py) < min(ky, other.ky);
569 }
570
contains(const Rectangle & other) const571 bool Rectangle::contains(const Rectangle& other) const {
572 return px <= other.px && py <= other.py && kx >= other.kx && ky >= other.ky;
573 }
574
intersection(const Rectangle & other) const575 Rectangle Rectangle::intersection(const Rectangle& other) const {
576 return Rectangle(max(px, other.px), max(py, other.py), min(kx, other.kx), min(ky, other.ky));
577 }
578
translate(Vec2 v) const579 Rectangle Rectangle::translate(Vec2 v) const {
580 return Rectangle(topLeft() + v, bottomRight() + v);
581 }
582
minusMargin(int margin) const583 Rectangle Rectangle::minusMargin(int margin) const {
584 return Rectangle(px + margin, py + margin, kx - margin, ky - margin);
585 }
586
operator *() const587 Vec2 Rectangle::Iter::operator* () const {
588 return pos;
589 }
operator !=(const Iter & other) const590 bool Rectangle::Iter::operator != (const Iter& other) const {
591 return pos != other.pos;
592 }
593
operator ++()594 const Rectangle::Iter& Rectangle::Iter::operator++ () {
595 ++pos.y;
596 if (pos.y >= ky) {
597 pos.y = py;
598 ++pos.x;
599 }
600 return *this;
601 }
602
begin() const603 Rectangle::Iter Rectangle::begin() const {
604 return Iter(px, py, px, py, kx, ky);
605 }
606
end() const607 Rectangle::Iter Rectangle::end() const {
608 return Iter(kx, py, px, py, kx, ky);
609 }
610
Range(int a,int b)611 Range::Range(int a, int b) : start(a), finish(b) {
612 }
Range(int a)613 Range::Range(int a) : Range(0, a) {}
614
singleElem(int a)615 Range Range::singleElem(int a) {
616 return Range(a, a + 1);
617 }
618
reverse()619 Range Range::reverse() {
620 Range r(finish - 1, start - 1);
621 r.increment = -1;
622 return r;
623 }
624
isEmpty() const625 bool Range::isEmpty() const {
626 return (increment == 1 && start >= finish) || (increment == -1 && start <= finish);
627 }
628
shorten(int r)629 Range Range::shorten(int r) {
630 if (start < finish) {
631 if (finish - start >= 2 * r)
632 return Range(start + r, finish - r);
633 else
634 return Range(0, 0);
635 } else {
636 if (start - finish >= 2 * r)
637 return Range(start - r, finish + r);
638 else
639 return Range(0, 0);
640 }
641 }
642
getStart() const643 int Range::getStart() const {
644 return start;
645 }
646
getEnd() const647 int Range::getEnd() const {
648 return finish;
649 }
650
getLength() const651 int Range::getLength() const {
652 return finish - start;
653 }
654
contains(int p) const655 bool Range::contains(int p) const {
656 return (increment > 0 && p >= start && p < finish) || (increment < 0 && p <= start && p > finish);
657 }
658
begin()659 Range::Iter Range::begin() {
660 if ((increment > 0 && start < finish) || (increment < 0 && start > finish))
661 return Iter(start, start, finish, increment);
662 else
663 return end();
664 }
665
end()666 Range::Iter Range::end() {
667 return Iter(finish, start, finish, increment);
668 }
669
Iter(int i,int a,int b,int inc)670 Range::Iter::Iter(int i, int a, int b, int inc) : ind(i), min(a), max(b), increment(inc) {}
671
operator *() const672 int Range::Iter::operator* () const {
673 return ind;
674 }
675
operator !=(const Iter & other) const676 bool Range::Iter::operator != (const Iter& other) const {
677 return other.ind != ind;
678 }
679
operator ++()680 const Range::Iter& Range::Iter::operator++ () {
681 ind += increment;
682 //CHECK(ind <= max && ind >= min) << ind << " " << min << " " << max;
683 return *this;
684 }
685
686 SERIALIZE_DEF(Range, start, finish, increment)
687 SERIALIZATION_CONSTRUCTOR_IMPL(Range);
688
combine(const vector<string> & adj,bool commasOnly)689 string combine(const vector<string>& adj, bool commasOnly) {
690 string res;
691 for (int i : All(adj)) {
692 if (i == adj.size() - 1 && i > 0 && !commasOnly)
693 res.append(" and ");
694 else if (i > 0)
695 res.append(", ");
696 res.append(adj[i]);
697 }
698 return res;
699 }
700
hasSentenceEnding(const string & s)701 bool hasSentenceEnding(const string& s) {
702 return s.back() == '.' || s.back() == '?' || s.back() == '!' || s.back() == '\"';
703 }
704
combineSentences(const vector<string> & v)705 string combineSentences(const vector<string>& v) {
706 if (v.empty())
707 return "";
708 string ret;
709 for (string s : v) {
710 if (s.empty())
711 continue;
712 if (!ret.empty()) {
713 if (!hasSentenceEnding(ret))
714 ret += ".";
715 ret += " ";
716 }
717 ret += s;
718 }
719 return ret;
720 }
721
addAParticle(const string & s)722 string addAParticle(const string& s) {
723 if (isupper(s[0]))
724 return s;
725 if (contains({'a', 'e', 'u', 'i', 'o'}, s[0]))
726 return string("an ") + s;
727 else
728 return string("a ") + s;
729 }
730
capitalFirst(string s)731 string capitalFirst(string s) {
732 if (!s.empty() && islower(s[0]))
733 s[0] = toupper(s[0]);
734 return s;
735 }
736
noCapitalFirst(string s)737 string noCapitalFirst(string s) {
738 if (!s.empty() && isupper(s[0]))
739 s[0] = tolower(s[0]);
740 return s;
741 }
742
makeSentence(string s)743 string makeSentence(string s) {
744 if (s.empty())
745 return s;
746 s = capitalFirst(s);
747 if (s.size() > 1 && s[0] == '\"' && islower(s[1]))
748 s[1] = toupper(s[1]);
749 if (!hasSentenceEnding(s))
750 s.append(".");
751 return s;
752 }
753
makeSentences(string s)754 vector<string> makeSentences(string s) {
755 vector<string> ret = split(s, {'.'});
756 for (auto& elem : ret) {
757 trim(elem);
758 elem = makeSentence(elem);
759 }
760 return ret;
761 }
762
lowercase(string s)763 string lowercase(string s) {
764 for (int i : All(s))
765 if (isupper(s[i]))
766 s[i] = tolower(s[i]);
767 return s;
768 }
769
getPlural(const string & a,const string & b,int num)770 string getPlural(const string& a, const string&b, int num) {
771 if (num == 1)
772 return "1 " + a;
773 else
774 return toString(num) + " " + b;
775 }
776
getPlural(const string & a,int num)777 string getPlural(const string& a, int num) {
778 if (num == 1)
779 return "1 " + a;
780 else
781 return toString(num) + " " + a + "s";
782 }
783
toText(int num)784 static string toText(int num) {
785 switch (num) {
786 case 0: return "zero";
787 case 1: return "one";
788 case 2: return "two";
789 case 3: return "three";
790 case 4: return "four";
791 case 5: return "five";
792 case 6: return "six";
793 case 7: return "seven";
794 case 8: return "eight";
795 case 9: return "nine";
796 default: FATAL << "Unsupported number " << num;
797 return "";
798 }
799 }
800
getPluralText(const string & a,int num)801 string getPluralText(const string& a, int num) {
802 if (num == 1)
803 return "a " + a;
804 else
805 return toText(num) + " " + a + "s";
806 }
807
Semaphore(int v)808 Semaphore::Semaphore(int v) : value(v) {}
809
p()810 void Semaphore::p() {
811 std::unique_lock<std::mutex> lock(mut);
812 while (!value) {
813 cond.wait(lock);
814 }
815 --value;
816 }
817
get()818 int Semaphore::get() {
819 std::unique_lock<std::mutex> lock(mut);
820 return value;
821 }
822
v()823 void Semaphore::v() {
824 std::unique_lock<std::mutex> lock(mut);
825 ++value;
826 lock.unlock();
827 cond.notify_one();
828 }
829
__anonbfec713f0102null830 AsyncLoop::AsyncLoop(function<void()> f) : AsyncLoop([]{}, f) {
831 }
832
AsyncLoop(function<void ()> init,function<void ()> loop)833 AsyncLoop::AsyncLoop(function<void()> init, function<void()> loop)
834 : done(false), t([=] { init(); while (!done) { loop(); }}) {
835 }
836
setDone()837 void AsyncLoop::setDone() {
838 done = true;
839 }
840
finishAndWait()841 void AsyncLoop::finishAndWait() {
842 setDone();
843 if (t.joinable())
844 t.join();
845 }
846
~AsyncLoop()847 AsyncLoop::~AsyncLoop() {
848 finishAndWait();
849 }
850
ConstructorFunction(function<void ()> fun)851 ConstructorFunction::ConstructorFunction(function<void()> fun) {
852 fun();
853 }
854
DestructorFunction(function<void ()> dest)855 DestructorFunction::DestructorFunction(function<void()> dest) : destFun(dest) {
856 }
857
~DestructorFunction()858 DestructorFunction::~DestructorFunction() {
859 destFun();
860 }
861
contains(DirSet dirSet) const862 bool DirSet::contains(DirSet dirSet) const {
863 return intersection(dirSet) == dirSet;
864 }
865
DirSet(const initializer_list<Dir> & dirs)866 DirSet::DirSet(const initializer_list<Dir>& dirs) {
867 for (Dir dir : dirs)
868 content |= (1 << int(dir));
869 }
870
DirSet(const vector<Dir> & dirs)871 DirSet::DirSet(const vector<Dir>& dirs) {
872 for (Dir dir : dirs)
873 content |= (1 << int(dir));
874 }
875
DirSet(unsigned char c)876 DirSet::DirSet(unsigned char c) : content(c) {
877 }
878
DirSet()879 DirSet::DirSet() {
880 }
881
DirSet(bool n,bool s,bool e,bool w,bool ne,bool nw,bool se,bool sw)882 DirSet::DirSet(bool n, bool s, bool e, bool w, bool ne, bool nw, bool se, bool sw) {
883 content = n | (s << 1) | (e << 2) | (w << 3) | (ne << 4) | (nw << 5) | (se << 6) | (sw << 7);
884 }
885
insert(Dir dir)886 void DirSet::insert(Dir dir) {
887 content |= (1 << int(dir));
888 }
889
has(Dir dir) const890 bool DirSet::has(Dir dir) const {
891 return content & (1 << int(dir));
892 }
893
oneElement(Dir dir)894 DirSet DirSet::oneElement(Dir dir) {
895 return DirSet(1 << int(dir));
896 }
897
fullSet()898 DirSet DirSet::fullSet() {
899 return 255;
900 }
901
intersection(DirSet s) const902 DirSet DirSet::intersection(DirSet s) const {
903 s.content &= content;
904 return s;
905 }
906
complement() const907 DirSet DirSet::complement() const {
908 return ~content;
909 }
910
Iter(const DirSet & s,Dir num)911 DirSet::Iter::Iter(const DirSet& s, Dir num) : set(s), ind(num) {
912 goForward();
913 }
914
goForward()915 void DirSet::Iter::goForward() {
916 while (ind < Dir(8) && !set.has(ind))
917 ind = Dir(int(ind) + 1);
918 }
919
operator *() const920 Dir DirSet::Iter::operator* () const {
921 return ind;
922 }
923
operator !=(const Iter & other) const924 bool DirSet::Iter::operator != (const Iter& other) const {
925 return ind != other.ind;
926 }
927
operator ++()928 const DirSet::Iter& DirSet::Iter::operator++ () {
929 ind = Dir(int(ind) + 1);
930 goForward();
931 return *this;
932 }
933
DisjointSets(int s)934 DisjointSets::DisjointSets(int s) : father(s), size(s, 1) {
935 for (int i : Range(s))
936 father[i] = i;
937 }
938
join(int i,int j)939 void DisjointSets::join(int i, int j) {
940 i = getSet(i);
941 j = getSet(j);
942 if (size[i] < size[j])
943 swap(i, j);
944 father[j] = i;
945 size[i] += size[j];
946 }
947
same(int i,int j)948 bool DisjointSets::same(int i, int j) {
949 return getSet(i) == getSet(j);
950 }
951
same(const vector<int> & v)952 bool DisjointSets::same(const vector<int>& v) {
953 for (int i : All(v))
954 if (!same(v[i], v[0]))
955 return false;
956 return true;
957 }
958
getSet(int i)959 int DisjointSets::getSet(int i) {
960 int ret = i;
961 while (father[ret] != ret)
962 ret = father[ret];
963 while (i != ret) {
964 int j = father[i];
965 father[i] = ret;
966 i = j;
967 }
968 return ret;
969 }
970
getSize(const std::string & s)971 int getSize(const std::string& s) {
972 return s.size();
973 }
974
getString(const std::string & s)975 const char* getString(const std::string& s) {
976 return s.c_str();
977 }
978
combineWithOr(const vector<string> & elems)979 string combineWithOr(const vector<string>& elems) {
980 string ret;
981 for (auto& elem : elems) {
982 if (!ret.empty())
983 ret += " or ";
984 ret += elem;
985 }
986 return ret;
987 }
988