1
0

testlib.h 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605
  1. #ifndef _TESTLIB_H_
  2. #define _TESTLIB_H_
  3. /*
  4. *
  5. * Copyright (c) 2005-2009
  6. */
  7. #define VERSION "0.6.?"
  8. /*
  9. * Mike Mirzayanov
  10. *
  11. * This material is provided "as is", with absolutely no warranty expressed
  12. * or implied. Any use is at your own risk.
  13. *
  14. * Permission to use or copy this software for any purpose is hereby granted
  15. * without fee, provided the above notices are retained on all copies.
  16. * Permission to modify the code and to distribute modified code is granted,
  17. * provided the above notices are retained, and a notice that the code was
  18. * modified is included with the above copyright notice.
  19. *
  20. */
  21. /* NOTE: This file contains testlib library for C++.
  22. *
  23. * Program, using testlib running format:
  24. * check.exe <Input_File> <Output_File> <Answer_File> [<Result_File> [-appes]],
  25. *
  26. * If result file is specified it will contain results.
  27. */
  28. const char* latestFeatures[] = {
  29. "Added InStream::readLong() and removed InStream::readLongint()",
  30. "Now no footer added to each report by default (use directive FOOTER to switch on)",
  31. "Now every checker has a name, use setName(const char* format, ...) to set it",
  32. "Now it is compatible with TTS (by Kittens Computing)",
  33. "Added \'ensure(condition, message = \"\")\' feature, it works like assert()",
  34. "Fixed compatibility with MS C++ 7.1",
  35. "Added footer with exit code information",
  36. "Added compatibility with EJUDGE (compile with EJUDGE directive)"
  37. };
  38. #ifdef _MSC_VER
  39. #define _CRT_SECURE_NO_DEPRECATE
  40. #endif
  41. #define random __random_depricated
  42. #include <stdlib.h>
  43. #include <climits>
  44. #undef random
  45. #include <cstdio>
  46. #include <cctype>
  47. #include <string>
  48. #include <vector>
  49. #include <set>
  50. #include <sstream>
  51. #include <string.h>
  52. #include <stdarg.h>
  53. #include <fcntl.h>
  54. #include <io.h>
  55. #if ( _WIN32 || __WIN32__ || _WIN64 || __WIN64__ )
  56. #include <windows.h>
  57. #define ON_WINDOWS
  58. #else
  59. #define WORD unsigned short
  60. #endif
  61. #ifndef LLONG_MIN
  62. #define LLONG_MIN (-9223372036854775807LL - 1)
  63. #endif
  64. #define ABS(f) ((f) < 0 ? -(f) : (f))
  65. #define MIN(a, b) ((a) < (b) ? (a) : (b))
  66. #define MAX(a, b) ((a) > (b) ? (a) : (b))
  67. #define OUTPUT_BUFFER_SIZE (2097152)
  68. #define LF ((char)10)
  69. #define CR ((char)13)
  70. #define TAB ((char)9)
  71. #define SPACE ((char)' ')
  72. #define EOFC ((char)26)
  73. #ifndef EJUDGE
  74. #define OK_EXIT_CODE 0
  75. #define WA_EXIT_CODE 1
  76. #define PE_EXIT_CODE 2
  77. #define FAIL_EXIT_CODE 3
  78. #define DIRT_EXIT_CODE 4
  79. #else
  80. #define OK_EXIT_CODE 0
  81. #define WA_EXIT_CODE 5
  82. #define PE_EXIT_CODE 4
  83. #define FAIL_EXIT_CODE 6
  84. #define DIRT_EXIT_CODE 6
  85. #endif
  86. /* Random routine */
  87. class random;
  88. class pattern
  89. {
  90. public:
  91. pattern(std::string s);
  92. std::string next(random& rnd) const;
  93. bool matches(const std::string& s) const;
  94. private:
  95. bool matches(const std::string& s, size_t pos) const;
  96. std::vector<pattern> children;
  97. std::set<char> chars;
  98. int from;
  99. int to;
  100. };
  101. class random
  102. {
  103. private:
  104. long long seed;
  105. static const long long multiplier;
  106. static const long long addend;
  107. static const long long mask;
  108. public:
  109. long long nextBits(int bits)
  110. {
  111. if (bits <= 48)
  112. {
  113. seed = (seed * multiplier + addend) & mask;
  114. return (long long)(seed >> (48 - bits));
  115. }
  116. else
  117. {
  118. if (bits > 63)
  119. throw "n must be less than 64";
  120. return ((nextBits(31) << 32) ^ nextBits(31));
  121. }
  122. }
  123. public:
  124. random()
  125. : seed(3905348978240129619LL)
  126. {
  127. }
  128. void setSeed(int argc, char* argv[])
  129. {
  130. random p;
  131. seed = 3905348978240129619LL;
  132. for (int i = 0; i < argc; i++)
  133. {
  134. std::size_t le = std::strlen(argv[i]);
  135. for (std::size_t j = 0; j < le; j++)
  136. seed = seed * multiplier * (unsigned int)(argv[i][j]) + addend;
  137. seed += multiplier / addend;
  138. }
  139. seed = seed & mask;
  140. }
  141. void setSeed(long long _seed)
  142. {
  143. _seed = (_seed ^ multiplier) & mask;
  144. seed = _seed;
  145. }
  146. int next(int n)
  147. {
  148. if (n <= 0)
  149. throw "n must be positive";
  150. if ((n & -n) == n) // n is a power of 2
  151. return (int)((n * (long long)nextBits(31)) >> 31);
  152. int bits, val;
  153. do
  154. {
  155. bits = nextBits(31);
  156. val = bits % n;
  157. } while (bits - val + (n - 1) < 0);
  158. return val;
  159. }
  160. int next(unsigned int n)
  161. {
  162. if (n >= INT_MAX)
  163. throw "n must be less INT_MAX";
  164. return next(int(n));
  165. }
  166. long long next(long long n)
  167. {
  168. if (n <= 0)
  169. throw "n must be positive";
  170. long long bits, val;
  171. do
  172. {
  173. bits = nextBits(63);
  174. val = bits % n;
  175. } while (bits - val + (n - 1) < 0);
  176. return val;
  177. }
  178. int nextInt(int n)
  179. {
  180. return next(n);
  181. }
  182. long long nextLong(long long n)
  183. {
  184. return next(n);
  185. }
  186. double next()
  187. {
  188. return (((long long)(nextBits(26)) << 27) + nextBits(27)) / (double)(1LL << 53);
  189. }
  190. double next(double n)
  191. {
  192. return n * next();
  193. }
  194. std::string next(const std::string& ptrn)
  195. {
  196. pattern p(ptrn);
  197. return p.next(*this);
  198. }
  199. };
  200. const long long random::multiplier = 0x5DEECE66DLL;
  201. const long long random::addend = 0xBLL;
  202. const long long random::mask = (1LL << 48) - 1;
  203. /* End of random routine */
  204. /* Pattern routine */
  205. bool pattern::matches(const std::string& s) const
  206. {
  207. return matches(s, 0);
  208. }
  209. static bool __pattern_isSlash(const std::string& s, size_t pos)
  210. {
  211. return s[pos] == '\\';
  212. }
  213. static bool __pattern_isCommandChar(const std::string& s, size_t pos, char value)
  214. {
  215. if (pos >= s.length())
  216. return false;
  217. int slashes = 0;
  218. int before = pos - 1;
  219. while (before >= 0 && s[before] == '\\')
  220. before--, slashes++;
  221. return slashes % 2 == 0 && s[pos] == value;
  222. }
  223. static char __pattern_getChar(const std::string& s, size_t& pos)
  224. {
  225. if (__pattern_isSlash(s, pos))
  226. pos += 2;
  227. else
  228. pos++;
  229. return s[pos - 1];
  230. }
  231. static int __pattern_greedyMatch(const std::string& s, size_t pos, const std::set<char> chars)
  232. {
  233. int result = 0;
  234. while (pos < s.length())
  235. {
  236. char c = __pattern_getChar(s, pos);
  237. if (chars.count(c) == 0)
  238. break;
  239. else
  240. result++;
  241. }
  242. return result;
  243. }
  244. bool pattern::matches(const std::string& s, size_t pos) const
  245. {
  246. std::string result;
  247. if (to > 0)
  248. {
  249. int size = __pattern_greedyMatch(s, pos, chars);
  250. if (size < from)
  251. return false;
  252. if (size > to)
  253. size = to;
  254. pos += size;
  255. }
  256. if (children.size() > 0)
  257. {
  258. for (size_t child = 0; child < children.size(); child++)
  259. if (children[child].matches(s, pos))
  260. return true;
  261. return false;
  262. }
  263. else
  264. return pos == s.length();
  265. }
  266. std::string pattern::next(random& rnd) const
  267. {
  268. std::string result;
  269. if (to == INT_MAX)
  270. throw "Can't process character '*' for generation";
  271. if (to > 0)
  272. {
  273. std::vector<char> possible(chars.begin(), chars.end());
  274. int count = rnd.nextInt(to - from + 1) + from;
  275. for (int i = 0; i < count; i++)
  276. result += possible[rnd.nextInt(possible.size())];
  277. }
  278. if (children.size() > 0)
  279. {
  280. int child = rnd.nextInt(children.size());
  281. result += children[child].next(rnd);
  282. }
  283. return result;
  284. }
  285. static void __pattern_scanCounts(const std::string& s, size_t& pos, int& from, int& to)
  286. {
  287. if (pos >= s.length())
  288. {
  289. from = to = 1;
  290. return;
  291. }
  292. if (__pattern_isCommandChar(s, pos, '{'))
  293. {
  294. std::vector<std::string> parts;
  295. std::string part;
  296. pos++;
  297. while (pos < s.length() && !__pattern_isCommandChar(s, pos, '}'))
  298. {
  299. if (__pattern_isCommandChar(s, pos, ','))
  300. parts.push_back(part), part = "", pos++;
  301. else
  302. part += __pattern_getChar(s, pos);
  303. }
  304. if (part != "")
  305. parts.push_back(part);
  306. if (!__pattern_isCommandChar(s, pos, '}'))
  307. throw "Illegal pattern";
  308. pos++;
  309. if (parts.size() < 1 || parts.size() > 2)
  310. throw "Illegal pattern";
  311. std::vector<int> numbers;
  312. for (size_t i = 0; i < parts.size(); i++)
  313. {
  314. if (parts[i].length() == 0)
  315. throw "Illegal pattern";
  316. int number;
  317. if (std::sscanf(parts[i].c_str(), "%d", &number) != 1)
  318. throw "Illegal pattern";
  319. numbers.push_back(number);
  320. }
  321. if (numbers.size() == 1)
  322. from = to = numbers[0];
  323. else
  324. from = numbers[0], to = numbers[1];
  325. if (from > to)
  326. throw "Illegal pattern";
  327. }
  328. else
  329. {
  330. if (__pattern_isCommandChar(s, pos, '?'))
  331. {
  332. from = 0, to = 1, pos++;
  333. return;
  334. }
  335. if (__pattern_isCommandChar(s, pos, '*'))
  336. {
  337. from = 0, to = INT_MAX, pos++;
  338. return;
  339. }
  340. from = to = 1;
  341. }
  342. }
  343. static std::set<char> __pattern_scanCharSet(const std::string& s, size_t& pos)
  344. {
  345. if (pos >= s.length())
  346. throw "Illegal pattern";
  347. std::set<char> result;
  348. if (__pattern_isCommandChar(s, pos, '['))
  349. {
  350. pos++;
  351. bool negative = __pattern_isCommandChar(s, pos, '^');
  352. std::vector<std::string> parts;
  353. char prev = 0;
  354. while (pos < s.length() && !__pattern_isCommandChar(s, pos, ']'))
  355. {
  356. if (__pattern_isCommandChar(s, pos, '-') && prev != 0)
  357. {
  358. pos++;
  359. if (pos + 1 == s.length())
  360. {
  361. result.insert(prev);
  362. prev = '-';
  363. continue;
  364. }
  365. char next = __pattern_getChar(s, pos);
  366. if (prev > next)
  367. throw "Illegal pattern";
  368. for (char c = prev; c <= next; c++)
  369. result.insert(c);
  370. }
  371. else
  372. {
  373. if (prev != 0)
  374. result.insert(prev);
  375. prev = __pattern_getChar(s, pos);
  376. }
  377. }
  378. if (prev != 0)
  379. result.insert(prev);
  380. if (!__pattern_isCommandChar(s, pos, ']'))
  381. throw "Illegal pattern";
  382. pos++;
  383. if (negative)
  384. {
  385. std::set<char> actuals;
  386. for (int code = 0; code < 255; code++)
  387. {
  388. char c = char(code);
  389. if (result.count(c) == 0)
  390. actuals.insert(c);
  391. }
  392. result = actuals;
  393. }
  394. }
  395. else
  396. result.insert(__pattern_getChar(s, pos));
  397. return result;
  398. }
  399. pattern::pattern(std::string s): from(0), to(0)
  400. {
  401. std::string t;
  402. for (size_t i = 0; i < s.length(); i++)
  403. if (!__pattern_isCommandChar(s, i, ' '))
  404. t += s[i];
  405. s = t;
  406. int opened = 0;
  407. int firstClose = -1;
  408. std::vector<int> seps;
  409. for (size_t i = 0; i < s.length(); i++)
  410. {
  411. if (__pattern_isCommandChar(s, i, '('))
  412. {
  413. opened++;
  414. continue;
  415. }
  416. if (__pattern_isCommandChar(s, i, ')'))
  417. {
  418. opened--;
  419. if (opened == 0 && firstClose == -1)
  420. firstClose = i;
  421. continue;
  422. }
  423. if (opened < 0)
  424. throw "Illegal pattern";
  425. if (__pattern_isCommandChar(s, i, '|') && opened == 0)
  426. seps.push_back(i);
  427. }
  428. if (opened != 0)
  429. throw "Illegal pattern";
  430. if (seps.size() == 0 && firstClose + 1 == (int)s.length()
  431. && __pattern_isCommandChar(s, 0, '(') && __pattern_isCommandChar(s, s.length() - 1, ')'))
  432. {
  433. children.push_back(pattern(s.substr(1, s.length() - 2)));
  434. }
  435. else
  436. {
  437. if (seps.size() > 0)
  438. {
  439. seps.push_back(s.length());
  440. int last = 0;
  441. for (size_t i = 0; i < seps.size(); i++)
  442. {
  443. children.push_back(pattern(s.substr(last, seps[i] - last)));
  444. last = seps[i] + 1;
  445. }
  446. }
  447. else
  448. {
  449. size_t pos = 0;
  450. chars = __pattern_scanCharSet(s, pos);
  451. __pattern_scanCounts(s, pos, from, to);
  452. if (pos < s.length())
  453. children.push_back(pattern(s.substr(pos)));
  454. }
  455. }
  456. }
  457. /* End of pattern routine */
  458. inline bool isEof(char c)
  459. {
  460. return (c == EOF || c == EOFC);
  461. }
  462. inline bool isEoln(char c)
  463. {
  464. return (c == LF || c == CR);
  465. }
  466. inline bool isBlanks(char c)
  467. {
  468. return (c == LF || c == CR || c == SPACE || c == TAB);
  469. }
  470. enum TMode
  471. {
  472. _input, _output, _answer
  473. };
  474. enum TResult
  475. {
  476. _ok, _wa, _pe, _fail, _dirt
  477. };
  478. const std::string outcomes[] =
  479. {"accepted", "wrong-answer", "presentation-error", "fail", "fail"};
  480. struct InStream
  481. {
  482. InStream();
  483. std::FILE * file;
  484. std::string name;
  485. TMode mode;
  486. bool opened;
  487. bool stdfile;
  488. bool strict;
  489. void init(std::string fileName, TMode mode);
  490. void init(std::FILE* f, TMode mode);
  491. void skipBlanks();
  492. char curChar();
  493. void skipChar();
  494. char nextChar();
  495. char readChar();
  496. char readChar(char c);
  497. char readSpace();
  498. void unreadChar(char c);
  499. void reset();
  500. bool eof();
  501. bool seekEof();
  502. bool eoln();
  503. bool seekEoln();
  504. void nextLine();
  505. std::string readWord();
  506. std::string readToken();
  507. std::string readWord(const std::string& ptrn);
  508. std::string readToken(const std::string& ptrn);
  509. long long readLong();
  510. int readInteger();
  511. int readInt();
  512. long long readLong(long long minv, long long maxv);
  513. int readInteger(int minv, int maxv);
  514. int readInt(int minv, int maxv);
  515. double readReal();
  516. double readDouble();
  517. double readReal(double minv, double maxv);
  518. double readDouble(double minv, double maxv);
  519. std::string readString();
  520. std::string readLine();
  521. void readEoln();
  522. void readEof();
  523. void quit(TResult result, const char * msg);
  524. void quits(TResult result, std::string msg);
  525. void close();
  526. const static WORD LightGray = 0x07;
  527. const static WORD LightRed = 0x0c;
  528. const static WORD LightCyan = 0x0b;
  529. const static WORD LightGreen = 0x0a;
  530. static void textColor(WORD color);
  531. static void quitscr(WORD color, const char * msg);
  532. static void quitscrS(WORD color, std::string msg);
  533. void xmlSafeWrite(std::FILE * file, const char * msg);
  534. };
  535. InStream inf;
  536. InStream ouf;
  537. InStream ans;
  538. bool appesMode;
  539. std::string resultName;
  540. std::string checkerName = "untitled checker";
  541. random rnd;
  542. /* implementation
  543. */
  544. template <typename T>
  545. static std::string vtos(const T& t)
  546. {
  547. std::string s;
  548. std::stringstream ss;
  549. ss << t;
  550. ss >> s;
  551. return s;
  552. }
  553. InStream::InStream()
  554. {
  555. file = NULL;
  556. name = "";
  557. mode = _input;
  558. strict = false;
  559. stdfile = false;
  560. }
  561. int resultExitCode(TResult r)
  562. {
  563. if (r == _ok)
  564. return OK_EXIT_CODE;
  565. if (r == _wa)
  566. return WA_EXIT_CODE;
  567. if (r == _pe)
  568. return PE_EXIT_CODE;
  569. if (r == _fail)
  570. return FAIL_EXIT_CODE;
  571. if (r == _dirt)
  572. return DIRT_EXIT_CODE;
  573. return FAIL_EXIT_CODE;
  574. }
  575. void InStream::textColor(WORD color)
  576. {
  577. #ifdef ON_WINDOWS
  578. HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
  579. SetConsoleTextAttribute(handle, color);
  580. #endif
  581. }
  582. void halt(int exitCode)
  583. {
  584. #ifdef FOOTER
  585. InStream::textColor(InStream::LightGray);
  586. std::printf("Checker: \"%s\"\n", checkerName.c_str());
  587. std::printf("Exit code: %d\n", exitCode);
  588. InStream::textColor(InStream::LightGray);
  589. #endif
  590. std::exit(exitCode);
  591. }
  592. void InStream::quit(TResult result, const char * msg)
  593. {
  594. if (mode != _output && result != _fail)
  595. quits(_fail, std::string(msg) + " (" + name + ")");
  596. std::FILE * resultFile;
  597. std::string errorName;
  598. if (result == _ok)
  599. {
  600. if (!ouf.seekEof())
  601. quit(_dirt, "Extra information in the output file");
  602. }
  603. switch (result)
  604. {
  605. case _fail:
  606. errorName = "FAIL ";
  607. quitscrS(LightRed, errorName);
  608. break;
  609. case _dirt:
  610. errorName = "wrong output format ";
  611. quitscrS(LightCyan, errorName);
  612. result = _pe;
  613. break;
  614. case _pe:
  615. errorName = "wrong output format ";
  616. quitscrS(LightRed, errorName);
  617. break;
  618. case _ok:
  619. errorName = "ok ";
  620. quitscrS(LightGreen, errorName);
  621. break;
  622. case _wa:
  623. errorName = "wrong answer ";
  624. quitscrS(LightRed, errorName);
  625. break;
  626. default:
  627. quit(_fail, "What is the code ??? ");
  628. }
  629. if (resultName != "")
  630. {
  631. resultFile = std::fopen(resultName.c_str(), "w");
  632. if (resultFile == NULL)
  633. quit(_fail, "Can not write to Result file");
  634. if (appesMode)
  635. {
  636. fprintf(resultFile, "<?xml version=\"1.0\" encoding=\"windows-1251\"?>");
  637. fprintf(resultFile, "<result outcome = \"%s\">", outcomes[(int)result].c_str());
  638. xmlSafeWrite(resultFile, msg);
  639. fprintf(resultFile, "</result>\n");
  640. }
  641. else
  642. fprintf(resultFile, "%s", msg);
  643. if (NULL == resultFile || fclose(resultFile) != 0)
  644. quit(_fail, "Can not write to Result file");
  645. }
  646. quitscr(LightGray, msg);
  647. std::printf("\n");
  648. if (inf.file)
  649. fclose(inf.file);
  650. if (ouf.file)
  651. fclose(ouf.file);
  652. if (ans.file)
  653. fclose(ans.file);
  654. textColor(LightGray);
  655. if (resultName != "")
  656. std::printf("See file to check exit message\n");
  657. halt(resultExitCode(result));
  658. }
  659. void InStream::quits(TResult result, std::string msg)
  660. {
  661. InStream::quit(result, msg.c_str());
  662. }
  663. void InStream::xmlSafeWrite(std::FILE * file, const char * msg)
  664. {
  665. size_t lmsg = strlen(msg);
  666. for (size_t i = 0; i < lmsg; i++)
  667. {
  668. if (msg[i] == '&')
  669. {
  670. fprintf(file, "%s", "&amp;");
  671. continue;
  672. }
  673. if (msg[i] == '<')
  674. {
  675. fprintf(file, "%s", "&lt;");
  676. continue;
  677. }
  678. if (msg[i] == '>')
  679. {
  680. fprintf(file, "%s", "&gt;");
  681. continue;
  682. }
  683. if (msg[i] == '"')
  684. {
  685. fprintf(file, "%s", "&quot;");
  686. continue;
  687. }
  688. if (0 <= msg[i] && msg[i] <= 31)
  689. {
  690. fprintf(file, "%c", '.');
  691. continue;
  692. }
  693. fprintf(file, "%c", msg[i]);
  694. }
  695. }
  696. void InStream::quitscrS(WORD color, std::string msg)
  697. {
  698. quitscr(color, msg.c_str());
  699. }
  700. void InStream::quitscr(WORD color, const char * msg)
  701. {
  702. if (resultName == "")
  703. {
  704. textColor(color);
  705. std::printf("%s", msg);
  706. textColor(LightGray);
  707. }
  708. }
  709. void InStream::reset()
  710. {
  711. if (opened && stdfile)
  712. quit(_fail, "Can't reset standard handle");
  713. if (opened)
  714. close();
  715. if (!stdfile)
  716. if (NULL == (file = std::fopen(name.c_str(), "rb")))
  717. {
  718. if (mode == _output)
  719. quits(_pe, std::string("File not found: \"") + name + "\"");
  720. }
  721. opened = true;
  722. if (NULL != file)
  723. {
  724. #ifdef _MSC_VER
  725. _setmode(_fileno(file), O_BINARY);
  726. #else
  727. setmode(fileno(file), O_BINARY);
  728. #endif
  729. }
  730. }
  731. void InStream::init(std::string fileName, TMode mode)
  732. {
  733. opened = false;
  734. name = fileName;
  735. stdfile = false;
  736. this->mode = mode;
  737. reset();
  738. }
  739. void InStream::init(std::FILE* f, TMode mode)
  740. {
  741. opened = false;
  742. name = "untitled";
  743. if (f == stdin)
  744. name = "stdin", stdfile = true;
  745. if (f == stdout)
  746. name = "stdout", stdfile = true;
  747. if (f == stderr)
  748. name = "stderr", stdfile = true;
  749. this->file = f;
  750. this->mode = mode;
  751. reset();
  752. }
  753. char InStream::curChar()
  754. {
  755. char c = (char)getc(file);
  756. ungetc(c, file);
  757. return c;
  758. }
  759. char InStream::nextChar()
  760. {
  761. return (char)getc(file);
  762. }
  763. char InStream::readChar()
  764. {
  765. return nextChar();
  766. }
  767. char InStream::readChar(char c)
  768. {
  769. char found = readChar();
  770. if (c != found)
  771. {
  772. if (!isEoln(found))
  773. quit(_pe, ("Unexpected character '" + std::string(1, found) + "', but '" + std::string(1, c) + "' expected").c_str());
  774. else
  775. quit(_pe, ("Unexpected character " + ("#" + vtos(int(found))) + ", but '" + std::string(1, c) + "' expected").c_str());
  776. }
  777. return found;
  778. }
  779. char InStream::readSpace()
  780. {
  781. return readChar(' ');
  782. }
  783. void InStream::unreadChar(char c)
  784. {
  785. ungetc(c, file);
  786. }
  787. void InStream::skipChar()
  788. {
  789. getc(file);
  790. }
  791. void InStream::skipBlanks()
  792. {
  793. char cur;
  794. while (isBlanks(cur = readChar()));
  795. unreadChar(cur);
  796. }
  797. std::string InStream::readWord()
  798. {
  799. if (!strict)
  800. skipBlanks();
  801. char cur = readChar();
  802. if (isEof(cur))
  803. quit(_pe, "Unexpected end of file - token expected");
  804. if (isBlanks(cur))
  805. quit(_pe, "Unexpected white-space - token expected");
  806. std::string result = "";
  807. while (!(isBlanks(cur) || cur == EOF))
  808. {
  809. result += cur;
  810. cur = nextChar();
  811. }
  812. unreadChar(cur);
  813. if (result.length() == 0)
  814. quit(_pe, "Unexpected end of file or white-space - token expected");
  815. return result;
  816. }
  817. std::string InStream::readToken()
  818. {
  819. return readWord();
  820. }
  821. static std::string __testlib_part(const std::string& s)
  822. {
  823. if (s.length() <= 64)
  824. return s;
  825. else
  826. return s.substr(0, 30) + "..." + s.substr(s.length() - 31, 31);
  827. }
  828. std::string InStream::readWord(const std::string& ptrn)
  829. {
  830. pattern p(ptrn);
  831. std::string result = readWord();
  832. if (!p.matches(result))
  833. quit(_pe, ("Token \"" + __testlib_part(result) + "\" doesn't correspond to pattern \"" + ptrn + "\"").c_str());
  834. return result;
  835. }
  836. std::string InStream::readToken(const std::string& ptrn)
  837. {
  838. return readWord(ptrn);
  839. }
  840. static bool equals(long long integer, const char* s)
  841. {
  842. if (integer == LLONG_MIN)
  843. return strcmp(s, "-9223372036854775808") == 0;
  844. if (integer == 0LL)
  845. return strcmp(s, "0") == 0;
  846. size_t length = strlen(s);
  847. if (length == 0)
  848. return false;
  849. if (integer < 0 && s[0] != '-')
  850. return false;
  851. if (integer < 0)
  852. s++, length--, integer = -integer;
  853. if (length == 0)
  854. return false;
  855. while (integer > 0)
  856. {
  857. int digit = integer % 10;
  858. if (s[length - 1] != '0' + digit)
  859. return false;
  860. length--;
  861. integer /= 10;
  862. }
  863. return length == 0;
  864. }
  865. static double stringToDouble(InStream& in, const char* buffer)
  866. {
  867. double retval;
  868. size_t length = strlen(buffer);
  869. for (size_t i = 0; i < length; i++)
  870. if (isBlanks(buffer[i]))
  871. in.quit(_pe, ("Expected double, but \"" + (std::string)buffer + "\" found").c_str());
  872. if (std::sscanf(buffer, "%lf", &retval) == 1)
  873. return retval;
  874. else
  875. in.quit(_pe, ("Expected double, but \"" + (std::string)buffer + "\" found").c_str());
  876. throw "Unexpected exception";
  877. }
  878. static long long stringToLongLong(InStream& in, const char* buffer)
  879. {
  880. if (strcmp(buffer, "-9223372036854775808") == 0)
  881. return LLONG_MIN;
  882. bool minus = false;
  883. size_t length = strlen(buffer);
  884. if (length > 1 && buffer[0] == '-')
  885. minus = true;
  886. if (length > 20)
  887. in.quit(_pe, ("Expected integer, but \"" + (std::string)buffer + "\" found").c_str());
  888. long long retval = 0LL;
  889. int zeroes = 0;
  890. int processingZeroes = true;
  891. for (size_t i = (minus ? 1 : 0); i < length; i++)
  892. {
  893. if (buffer[i] == '0' && processingZeroes)
  894. zeroes++;
  895. else
  896. processingZeroes = false;
  897. if (buffer[i] < '0' || buffer[i] > '9')
  898. in.quit(_pe, ("Expected integer, but \"" + (std::string)buffer + "\" found").c_str());
  899. retval = retval * 10 + (buffer[i] - '0');
  900. }
  901. if (retval < 0)
  902. in.quit(_pe, ("Expected integer, but \"" + (std::string)buffer + "\" found").c_str());
  903. if ((zeroes > 0 && (retval != 0 || minus)) || zeroes > 1)
  904. in.quit(_pe, ("Expected integer, but \"" + (std::string)buffer + "\" found").c_str());
  905. retval = (minus ? -retval : +retval);
  906. if (length < 19)
  907. return retval;
  908. if (equals(retval, buffer))
  909. return retval;
  910. else
  911. in.quit(_pe, ("Expected int64, but \"" + (std::string)buffer + "\" found").c_str());
  912. throw "Unexpected exception";
  913. }
  914. int InStream::readInteger()
  915. {
  916. if (!strict && seekEof())
  917. quit(_pe, "Unexpected end of file - int32 expected");
  918. std::string token = readWord();
  919. long long value = stringToLongLong(*this, token.c_str());
  920. if (value < INT_MIN || value > INT_MAX)
  921. quit(_pe, ("Expected int32, but \"" + token + "\" found").c_str());
  922. return value;
  923. }
  924. long long InStream::readLong()
  925. {
  926. if (!strict && seekEof())
  927. quit(_pe, "Unexpected end of file - int64 expected");
  928. std::string token = readWord();
  929. return stringToLongLong(*this, token.c_str());
  930. }
  931. long long InStream::readLong(long long minv, long long maxv)
  932. {
  933. long long result = readLong();
  934. if (result < minv || result > maxv)
  935. quit(_pe, ("Integer " + vtos(result) + " violates the range [" + vtos(minv) + ", " + vtos(maxv) + "]").c_str());
  936. return result;
  937. }
  938. int InStream::readInt()
  939. {
  940. return readInteger();
  941. }
  942. int InStream::readInt(int minv, int maxv)
  943. {
  944. int result = readInt();
  945. if (result < minv || result > maxv)
  946. quit(_pe, ("Integer " + vtos(result) + " violates the range [" + vtos(minv) + ", " + vtos(maxv) + "]").c_str());
  947. return result;
  948. }
  949. int InStream::readInteger(int minv, int maxv)
  950. {
  951. return readInt(minv, maxv);
  952. }
  953. double InStream::readReal()
  954. {
  955. if (!strict && seekEof())
  956. quit(_pe, "Unexpected end of file - double expected");
  957. return stringToDouble(*this, readWord().c_str());
  958. }
  959. double InStream::readDouble()
  960. {
  961. return readReal();
  962. }
  963. double InStream::readReal(double minv, double maxv)
  964. {
  965. double result = readReal();
  966. if (result < minv || result > maxv)
  967. quit(_pe, ("Double " + vtos(result) + " violates the range [" + vtos(minv) + ", " + vtos(maxv) + "]").c_str());
  968. return result;
  969. }
  970. double InStream::readDouble(double minv, double maxv)
  971. {
  972. return readReal(minv, maxv);
  973. }
  974. bool InStream::eof()
  975. {
  976. if (!strict && NULL == file)
  977. return true;
  978. if (feof(file) != 0)
  979. return true;
  980. else
  981. {
  982. int cur = getc(file);
  983. if (isEof(cur))
  984. return true;
  985. else
  986. {
  987. ungetc(cur, file);
  988. return false;
  989. }
  990. }
  991. }
  992. bool InStream::seekEof()
  993. {
  994. if (NULL == file)
  995. return true;
  996. skipBlanks();
  997. return eof();
  998. }
  999. bool InStream::eoln()
  1000. {
  1001. if (!strict && NULL == file)
  1002. return true;
  1003. char c = nextChar();
  1004. if (!strict)
  1005. {
  1006. if (isEof(c))
  1007. return true;
  1008. if (c == CR)
  1009. {
  1010. c = nextChar();
  1011. std::printf("%d\n", c);
  1012. if (c != LF)
  1013. {
  1014. unreadChar(CR);
  1015. unreadChar(c);
  1016. return false;
  1017. }
  1018. else
  1019. return true;
  1020. }
  1021. if (c == LF)
  1022. return true;
  1023. unreadChar(c);
  1024. return false;
  1025. }
  1026. else
  1027. {
  1028. bool returnCr = false;
  1029. #ifdef ON_WINDOWS
  1030. if (c != CR)
  1031. {
  1032. unreadChar(c);
  1033. return false;
  1034. }
  1035. else
  1036. {
  1037. if (!returnCr)
  1038. returnCr = true;
  1039. c = nextChar();
  1040. }
  1041. #endif
  1042. if (c != LF)
  1043. {
  1044. if (returnCr)
  1045. unreadChar(CR);
  1046. unreadChar(LF);
  1047. return false;
  1048. }
  1049. return true;
  1050. }
  1051. }
  1052. void InStream::readEoln()
  1053. {
  1054. if (!eoln())
  1055. quit(_pe, "Expected EOLN");
  1056. }
  1057. void InStream::readEof()
  1058. {
  1059. if (!eof())
  1060. quit(_pe, "Expected EOF");
  1061. }
  1062. bool InStream::seekEoln()
  1063. {
  1064. if (NULL == file)
  1065. return true;
  1066. char cur;
  1067. do
  1068. {
  1069. cur = nextChar();
  1070. }
  1071. while (cur == SPACE || cur == TAB);
  1072. ungetc(cur, file);
  1073. return eoln();
  1074. }
  1075. void InStream::nextLine()
  1076. {
  1077. if (NULL == file)
  1078. return;
  1079. char cur;
  1080. while (!isEoln(cur = readChar()));
  1081. if (cur == CR)
  1082. {
  1083. cur = readChar();
  1084. if (cur != LF)
  1085. unreadChar(cur);
  1086. }
  1087. else
  1088. {
  1089. if (cur != LF)
  1090. unreadChar(cur);
  1091. }
  1092. }
  1093. std::string InStream::readString()
  1094. {
  1095. if (NULL == file)
  1096. quit(_pe, "Expected line");
  1097. std::string retval = "";
  1098. char cur;
  1099. while (true)
  1100. {
  1101. cur = readChar();
  1102. if (isEoln(cur))
  1103. break;
  1104. if (isEof(cur))
  1105. break;
  1106. retval += cur;
  1107. }
  1108. eoln();
  1109. return retval;
  1110. }
  1111. std::string InStream::readLine()
  1112. {
  1113. return readString();
  1114. }
  1115. void InStream::close()
  1116. {
  1117. if (opened)
  1118. fclose(file);
  1119. opened = false;
  1120. }
  1121. void quit(TResult result, const std::string& msg)
  1122. {
  1123. ouf.quit(result, msg.c_str());
  1124. }
  1125. void quit(TResult result, const char * msg)
  1126. {
  1127. ouf.quit(result, msg);
  1128. }
  1129. void quitf(TResult result, const char * format, ...)
  1130. {
  1131. char * buffer = new char [OUTPUT_BUFFER_SIZE];
  1132. va_list ap;
  1133. va_start(ap, format);
  1134. std::vsprintf(buffer, format, ap);
  1135. va_end(ap);
  1136. std::string output(buffer);
  1137. delete[] buffer;
  1138. quit(result, output);
  1139. }
  1140. void registerGen(int argc, char* argv[])
  1141. {
  1142. rnd.setSeed(argc, argv);
  1143. }
  1144. void registerValidation()
  1145. {
  1146. inf.init(stdin, _input);
  1147. inf.strict = true;
  1148. }
  1149. void registerTestlibCmd(int argc, char * argv[])
  1150. {
  1151. if (argc > 1 && !strcmp("--help", argv[1]))
  1152. {
  1153. InStream::textColor(InStream::LightCyan);
  1154. std::printf("TESTLIB %s ", VERSION);
  1155. std::printf("by Mike Mirzayanov, copyright(c) 2005-2009\n");
  1156. std::printf("Checker name: \"%s\"\n", checkerName.c_str());
  1157. InStream::textColor(InStream::LightGray);
  1158. std::printf("\n");
  1159. std::printf("Latest features: \n");
  1160. for (size_t i = 0; i < sizeof(latestFeatures) / sizeof(char*); i++)
  1161. {
  1162. std::printf("*) %s\n", latestFeatures[i]);
  1163. }
  1164. std::printf("\n");
  1165. std::printf("Program must be run with the following arguments: \n");
  1166. std::printf(" <input-file> <output-file> <answer-file> [<report-file> [<-appes>]]\n\n");
  1167. std::exit(0);
  1168. }
  1169. if (sizeof(int) != 4)
  1170. quit(_fail, "'testlib' unit assumes 'sizeof(int) = 4'");
  1171. if (sizeof(long long) != 8)
  1172. quit(_fail, "'testlib' unit assumes 'sizeof(long long) = 8'");
  1173. if (argc < 4 || argc > 6)
  1174. {
  1175. quit(_fail, std::string("Program must be run with the following arguments: ") +
  1176. std::string("<input-file> <output-file> <answer-file> [<report-file> [<-appes>]]") +
  1177. "\nUse \"--help\" to get help information");
  1178. }
  1179. if (argc == 4)
  1180. {
  1181. resultName = "";
  1182. appesMode = false;
  1183. }
  1184. if (argc == 5)
  1185. {
  1186. resultName = argv[4];
  1187. appesMode = false;
  1188. }
  1189. if (argc == 6)
  1190. {
  1191. if (strcmp("-APPES", argv[5]) && strcmp("-appes", argv[5]))
  1192. {
  1193. quit(_fail, std::string("Program must be run with the following arguments: ") +
  1194. "<input-file> <output-file> <answer-file> [<report-file> [<-appes>]]");
  1195. }
  1196. else
  1197. {
  1198. resultName = argv[4];
  1199. appesMode = true;
  1200. }
  1201. }
  1202. inf.init(argv[1], _input);
  1203. ouf.init(argv[2], _output);
  1204. ans.init(argv[3], _answer);
  1205. }
  1206. void registerTestlib(int argc, ...)
  1207. {
  1208. if (argc < 3 || argc > 5)
  1209. quit(_fail, std::string("Program must be run with the following arguments: ") +
  1210. "<input-file> <output-file> <answer-file> [<report-file> [<-appes>]]");
  1211. char ** argv = new char*[argc + 1];
  1212. va_list ap;
  1213. va_start(ap, argc);
  1214. argv[0] = NULL;
  1215. for (int i = 0; i < argc; i++)
  1216. {
  1217. argv[i + 1] = va_arg(ap, char *);
  1218. }
  1219. va_end(ap);
  1220. registerTestlibCmd(argc + 1, argv);
  1221. delete[] argv;
  1222. }
  1223. inline bool isNaN(double r)
  1224. {
  1225. return ((r != r) == true) && ((r == r) == false) && ((1.0 > r) == false) && ((1.0 < r) == false);
  1226. }
  1227. inline bool isInfinite(double r)
  1228. {
  1229. return (r > 1E100 || r < -1E100);
  1230. }
  1231. bool doubleCompare(double expected, double result, double MAX_DOUBLE_ERROR)
  1232. {
  1233. if(isNaN(expected))
  1234. {
  1235. return isNaN(result);
  1236. }
  1237. else
  1238. if(isInfinite(expected))
  1239. {
  1240. if(expected > 0)
  1241. {
  1242. return result > 0 && isInfinite(result);
  1243. }
  1244. else
  1245. {
  1246. return result < 0 && isInfinite(result);
  1247. }
  1248. }
  1249. else
  1250. if(isNaN(result) || isInfinite(result))
  1251. {
  1252. return false;
  1253. }
  1254. else
  1255. if(ABS(result - expected) < MAX_DOUBLE_ERROR)
  1256. {
  1257. return true;
  1258. }
  1259. else
  1260. {
  1261. double minv = MIN(expected * (1.0 - MAX_DOUBLE_ERROR),
  1262. expected * (1.0 + MAX_DOUBLE_ERROR));
  1263. double maxv = MAX(expected * (1.0 - MAX_DOUBLE_ERROR),
  1264. expected * (1.0 + MAX_DOUBLE_ERROR));
  1265. return result > minv && result < maxv;
  1266. }
  1267. }
  1268. double doubleDelta(double expected, double result)
  1269. {
  1270. double absolute = ABS(result - expected);
  1271. if (ABS(expected) > 1E-9)
  1272. {
  1273. double relative = ABS(absolute / expected);
  1274. return MIN(absolute, relative);
  1275. }
  1276. else
  1277. return absolute;
  1278. }
  1279. static void __testlib_ensure(bool cond, const std::string msg)
  1280. {
  1281. if (!cond)
  1282. quitf(_fail, msg.c_str());
  1283. }
  1284. #define ensure(cond) __testlib_ensure(cond, std::string("Condition failed: \"") + #cond + "\"")
  1285. void ensuref(bool cond, const char* format, ...)
  1286. {
  1287. char * buffer = new char [OUTPUT_BUFFER_SIZE];
  1288. va_list ap;
  1289. va_start(ap, format);
  1290. std::vsprintf(buffer, format, ap);
  1291. va_end(ap);
  1292. std::string message(buffer);
  1293. delete[] buffer;
  1294. __testlib_ensure(cond, message);
  1295. }
  1296. void setName(const char* format, ...)
  1297. {
  1298. char * buffer = new char [OUTPUT_BUFFER_SIZE];
  1299. va_list ap;
  1300. va_start(ap, format);
  1301. std::vsprintf(buffer, format, ap);
  1302. va_end(ap);
  1303. std::string name(buffer);
  1304. delete[] buffer;
  1305. checkerName = name;
  1306. }
  1307. #endif