fork download
  1. #ifndef __PROGTEST__
  2. #include <cstring>
  3. #include <cassert>
  4. #include <cstdlib>
  5. #include <cstdio>
  6. #include <cstdint>
  7. #include <cctype>
  8. #include <cmath>
  9. #include <iostream>
  10. #include <iomanip>
  11. #include <sstream>
  12. #include <string>
  13. #include <vector>
  14. #include <map>
  15. #include <set>
  16. #include <list>
  17. #include <algorithm>
  18. #include <memory>
  19. #include <functional>
  20. #include <stdexcept>
  21. #endif /* __PROGTEST__ */
  22.  
  23. typedef unsigned int uint;
  24.  
  25. class CCell {
  26. public:
  27. virtual ~CCell() = default;
  28. virtual CCell* clone() const = 0;
  29. virtual uint getHeight() const = 0;
  30. virtual uint getWidth() const = 0;
  31. virtual void render(uint ln, uint w, uint h, char* buf) const = 0;
  32. virtual bool equals(const CCell &o) const = 0;
  33. bool operator==(const CCell &o) const { return equals(o); }
  34. bool operator!=(const CCell &o) const { return !(*this == o); }
  35. };
  36.  
  37. class CEmpty : public CCell {
  38. public:
  39. CEmpty() = default;
  40. ~CEmpty() override = default;
  41. CCell* clone() const override { return new CEmpty(*this); }
  42. uint getHeight() const override { return 0; }
  43. uint getWidth() const override { return 0; }
  44. void render(uint, uint w, uint, char* buf) const override {
  45. std::fill_n(buf, w, ' ');
  46. buf[w] = '\0';
  47. }
  48. bool equals(const CCell &o) const override {
  49. return dynamic_cast<const CEmpty*>(&o) != nullptr;
  50. }
  51. };
  52.  
  53. class CText : public CCell {
  54. public:
  55. static const int ALIGN_LEFT = 0;
  56. static const int ALIGN_RIGHT = 1;
  57.  
  58. CText(const char* s = "", int a = ALIGN_LEFT)
  59. : align(a)
  60. {
  61. setText(s);
  62. }
  63. CText(const CText &o)
  64. : lines(o.lines), align(o.align)
  65. {}
  66. ~CText() override = default;
  67.  
  68. CCell* clone() const override { return new CText(*this); }
  69. uint getHeight() const override { return (uint)lines.size(); }
  70. uint getWidth() const override {
  71. uint w = 0;
  72. for (auto &l : lines)
  73. w = std::max<uint>(w, (uint)l.size());
  74. return w;
  75. }
  76.  
  77. void render(uint ln, uint w, uint, char* buf) const override {
  78. const std::string &t = (ln < lines.size() ? lines[ln] : std::string());
  79. uint l = (uint)t.size();
  80. int pL = (align == ALIGN_RIGHT ? int(w - l) : 0);
  81. if (pL < 0) pL = 0;
  82. uint pR = w - l - pL;
  83. std::string out(pL, ' ');
  84. out += t;
  85. out.append(pR, ' ');
  86. std::memcpy(buf, out.c_str(), w + 1);
  87. }
  88.  
  89. bool equals(const CCell &o) const override {
  90. auto p = dynamic_cast<const CText*>(&o);
  91. return p && p->align == align && p->lines == lines;
  92. }
  93.  
  94. void setText(const char* s) {
  95. lines.clear();
  96. const char *p = s;
  97. while (true) {
  98. const char *nl = std::strchr(p, '\n');
  99. if (!nl) {
  100. lines.emplace_back(p);
  101. break;
  102. }
  103. lines.emplace_back(p, nl - p);
  104. p = nl + 1;
  105. }
  106. }
  107.  
  108. private:
  109. std::vector<std::string> lines;
  110. int align;
  111. };
  112.  
  113. class CImage : public CCell {
  114. public:
  115. CImage() = default;
  116. CImage(const CImage &o) : rows(o.rows) {}
  117. ~CImage() override = default;
  118.  
  119. CCell* clone() const override { return new CImage(*this); }
  120. uint getHeight() const override { return (uint)rows.size(); }
  121. uint getWidth() const override {
  122. uint w = 0;
  123. for (auto &r : rows)
  124. w = std::max<uint>(w, (uint)r.size());
  125. return w;
  126. }
  127.  
  128. void render(uint ln, uint w, uint h, char* buf) const override {
  129. int pT = (h > rows.size() ? int((h - rows.size())/2) : 0);
  130. const std::string &t =
  131. (ln >= (uint)pT && ln < (uint)(pT + rows.size()))
  132. ? rows[ln - pT]
  133. : std::string();
  134. uint l = (uint)t.size();
  135. int pL = (w > l ? int((w - l)/2) : 0);
  136. if (pL < 0) pL = 0;
  137. uint pR = w - pL - l;
  138. std::string out(pL, ' ');
  139. out += t;
  140. out.append(pR, ' ');
  141. std::memcpy(buf, out.c_str(), w + 1);
  142. }
  143.  
  144. bool equals(const CCell &o) const override {
  145. auto p = dynamic_cast<const CImage*>(&o);
  146. return p && p->rows == rows;
  147. }
  148.  
  149. CImage& addRow(const char* s) {
  150. rows.emplace_back(s);
  151. return *this;
  152. }
  153.  
  154. private:
  155. std::vector<std::string> rows;
  156. };
  157.  
  158. class CTable {
  159. public:
  160. CTable(uint r, uint c)
  161. : rows(r), cols(c), cells(r*c)
  162. {
  163. for (auto &p : cells)
  164. p = std::make_unique<CEmpty>();
  165. }
  166. CTable(const CTable &o)
  167. : rows(o.rows), cols(o.cols)
  168. {
  169. cells.reserve(o.cells.size());
  170. for (auto &p : o.cells)
  171. cells.emplace_back(p->clone());
  172. }
  173. CTable& operator=(const CTable &o) {
  174. if (this != &o) {
  175. CTable tmp(o);
  176. swap(tmp);
  177. }
  178. return *this;
  179. }
  180. ~CTable() = default;
  181.  
  182. CCell& getCell(uint r, uint c) {
  183. check(r,c);
  184. return *cells[r*cols + c];
  185. }
  186. const CCell& getCell(uint r, uint c) const {
  187. check(r,c);
  188. return *cells[r*cols + c];
  189. }
  190.  
  191. void setCell(uint r, uint c, const CCell &v) {
  192. check(r,c);
  193. auto p = std::unique_ptr<CCell>(v.clone());
  194. cells[r*cols + c] = std::move(p);
  195. }
  196.  
  197. bool operator==(const CTable &o) const {
  198. if (rows!=o.rows||cols!=o.cols) return false;
  199. for (size_t i=0;i<cells.size();++i)
  200. if (*cells[i]!=*o.cells[i]) return false;
  201. return true;
  202. }
  203. bool operator!=(const CTable &o) const {
  204. return !(*this==o);
  205. }
  206.  
  207. friend std::ostream& operator<<(std::ostream &os,const CTable &t){
  208. std::vector<uint> cw(t.cols), rh(t.rows,0);
  209. for(uint i=0;i<t.rows;i++){
  210. for(uint j=0;j<t.cols;j++){
  211. auto &cell = t.cells[i*t.cols+j];
  212. cw[j] = std::max(cw[j], cell->getWidth());
  213. rh[i] = std::max(rh[i], cell->getHeight());
  214. }
  215. }
  216. auto border=[&](){
  217. os<<'+';
  218. for(auto w:cw) os<<std::string(w,'-')<<'+';
  219. os<<'\n';
  220. };
  221. border();
  222. uint maxW = *std::max_element(cw.begin(),cw.end());
  223. std::vector<char> buf(maxW+1);
  224. for(uint i=0;i<t.rows;i++){
  225. for(uint ln=0;ln<rh[i];ln++){
  226. os<<'|';
  227. for(uint j=0;j<t.cols;j++){
  228. t.cells[i*t.cols+j]->render(ln,cw[j],rh[i],buf.data());
  229. os<<buf.data()<<'|';
  230. }
  231. os<<'\n';
  232. }
  233. border();
  234. }
  235. return os;
  236. }
  237.  
  238. private:
  239. uint rows, cols;
  240. std::vector<std::unique_ptr<CCell>> cells;
  241.  
  242. void check(uint r,uint c) const {
  243. if(r>=rows||c>=cols) throw std::out_of_range("CTable index");
  244. }
  245. void swap(CTable &o){
  246. std::swap(rows,o.rows);
  247. std::swap(cols,o.cols);
  248. cells.swap(o.cells);
  249. }
  250. };
  251.  
  252.  
  253. #ifndef __PROGTEST__
  254. int main ()
  255. {
  256. std::ostringstream oss;
  257. CTable t0 ( 3, 2 );
  258. t0 . setCell ( 0, 0, CText ( "Hello,\n"
  259. "Hello Kitty", CText::ALIGN_LEFT ) );
  260. t0 . setCell ( 1, 0, CText ( "Lorem ipsum dolor sit amet", CText::ALIGN_LEFT ) );
  261. t0 . setCell ( 2, 0, CText ( "Bye,\n"
  262. "Hello Kitty", CText::ALIGN_RIGHT ) );
  263. t0 . setCell ( 1, 1, CImage ()
  264. . addRow ( "### " )
  265. . addRow ( "# # " )
  266. . addRow ( "# # # ## ### ###" )
  267. . addRow ( "### ## # # # #" )
  268. . addRow ( "# # # # # #" )
  269. . addRow ( "# # # # # #" )
  270. . addRow ( "# # ### ###" )
  271. . addRow ( " #" )
  272. . addRow ( " ## " )
  273. . addRow ( " " )
  274. . addRow ( " # ### ### # " )
  275. . addRow ( "### # # # ### " )
  276. . addRow ( " # ##### ### # " )
  277. . addRow ( " # # # # " )
  278. . addRow ( " ## ### ### ## " ) );
  279. t0 . setCell ( 2, 1, CEmpty () );
  280. oss . str ("");
  281. oss . clear ();
  282. oss << t0;
  283. assert ( oss . str () ==
  284. "+--------------------------+----------------------+\n"
  285. "|Hello, | |\n"
  286. "|Hello Kitty | |\n"
  287. "+--------------------------+----------------------+\n"
  288. "|Lorem ipsum dolor sit amet|### |\n"
  289. "| |# # |\n"
  290. "| |# # # ## ### ###|\n"
  291. "| |### ## # # # #|\n"
  292. "| |# # # # # #|\n"
  293. "| |# # # # # #|\n"
  294. "| |# # ### ###|\n"
  295. "| | #|\n"
  296. "| | ## |\n"
  297. "| | |\n"
  298. "| | # ### ### # |\n"
  299. "| |### # # # ### |\n"
  300. "| | # ##### ### # |\n"
  301. "| | # # # # |\n"
  302. "| | ## ### ### ## |\n"
  303. "+--------------------------+----------------------+\n"
  304. "| Bye,| |\n"
  305. "| Hello Kitty| |\n"
  306. "+--------------------------+----------------------+\n" );
  307. t0 . setCell ( 0, 1, t0 . getCell ( 1, 1 ) );
  308. t0 . setCell ( 2, 1, CImage ()
  309. . addRow ( "***** * * * ******* ****** *" )
  310. . addRow ( "* * * * * * * *" )
  311. . addRow ( "* * * * * * * *" )
  312. . addRow ( "* * * * * ***** * *" )
  313. . addRow ( "**** * * * * * *" )
  314. . addRow ( "* * * * * * * " )
  315. . addRow ( "* * * * * * * *" )
  316. . addRow ( "* * ***** ****** ******* ****** *" ) );
  317. dynamic_cast<CText &> ( t0 . getCell ( 1, 0 ) ) . setText ( "Lorem ipsum dolor sit amet,\n"
  318. "consectetur adipiscing\n"
  319. "elit. Curabitur scelerisque\n"
  320. "lorem vitae lectus cursus,\n"
  321. "vitae porta ante placerat. Class aptent taciti\n"
  322. "sociosqu ad litora\n"
  323. "torquent per\n"
  324. "conubia nostra,\n"
  325. "per inceptos himenaeos.\n"
  326. "\n"
  327. "Donec tincidunt augue\n"
  328. "sit amet metus\n"
  329. "pretium volutpat.\n"
  330. "Donec faucibus,\n"
  331. "ante sit amet\n"
  332. "luctus posuere,\n"
  333. "mauris tellus" );
  334. oss . str ("");
  335. oss . clear ();
  336. oss << t0;
  337. assert ( oss . str () ==
  338. "+----------------------------------------------+------------------------------------------+\n"
  339. "|Hello, | ### |\n"
  340. "|Hello Kitty | # # |\n"
  341. "| | # # # ## ### ### |\n"
  342. "| | ### ## # # # # |\n"
  343. "| | # # # # # # |\n"
  344. "| | # # # # # # |\n"
  345. "| | # # ### ### |\n"
  346. "| | # |\n"
  347. "| | ## |\n"
  348. "| | |\n"
  349. "| | # ### ### # |\n"
  350. "| | ### # # # ### |\n"
  351. "| | # ##### ### # |\n"
  352. "| | # # # # |\n"
  353. "| | ## ### ### ## |\n"
  354. "+----------------------------------------------+------------------------------------------+\n"
  355. "|Lorem ipsum dolor sit amet, | |\n"
  356. "|consectetur adipiscing | ### |\n"
  357. "|elit. Curabitur scelerisque | # # |\n"
  358. "|lorem vitae lectus cursus, | # # # ## ### ### |\n"
  359. "|vitae porta ante placerat. Class aptent taciti| ### ## # # # # |\n"
  360. "|sociosqu ad litora | # # # # # # |\n"
  361. "|torquent per | # # # # # # |\n"
  362. "|conubia nostra, | # # ### ### |\n"
  363. "|per inceptos himenaeos. | # |\n"
  364. "| | ## |\n"
  365. "|Donec tincidunt augue | |\n"
  366. "|sit amet metus | # ### ### # |\n"
  367. "|pretium volutpat. | ### # # # ### |\n"
  368. "|Donec faucibus, | # ##### ### # |\n"
  369. "|ante sit amet | # # # # |\n"
  370. "|luctus posuere, | ## ### ### ## |\n"
  371. "|mauris tellus | |\n"
  372. "+----------------------------------------------+------------------------------------------+\n"
  373. "| Bye,|***** * * * ******* ****** *|\n"
  374. "| Hello Kitty|* * * * * * * *|\n"
  375. "| |* * * * * * * *|\n"
  376. "| |* * * * * ***** * *|\n"
  377. "| |**** * * * * * *|\n"
  378. "| |* * * * * * * |\n"
  379. "| |* * * * * * * *|\n"
  380. "| |* * ***** ****** ******* ****** *|\n"
  381. "+----------------------------------------------+------------------------------------------+\n" );
  382. CTable t1 ( t0 );
  383. t1 . setCell ( 1, 0, CEmpty () );
  384. t1 . setCell ( 1, 1, CEmpty () );
  385. oss . str ("");
  386. oss . clear ();
  387. oss << t0;
  388. assert ( oss . str () ==
  389. "+----------------------------------------------+------------------------------------------+\n"
  390. "|Hello, | ### |\n"
  391. "|Hello Kitty | # # |\n"
  392. "| | # # # ## ### ### |\n"
  393. "| | ### ## # # # # |\n"
  394. "| | # # # # # # |\n"
  395. "| | # # # # # # |\n"
  396. "| | # # ### ### |\n"
  397. "| | # |\n"
  398. "| | ## |\n"
  399. "| | |\n"
  400. "| | # ### ### # |\n"
  401. "| | ### # # # ### |\n"
  402. "| | # ##### ### # |\n"
  403. "| | # # # # |\n"
  404. "| | ## ### ### ## |\n"
  405. "+----------------------------------------------+------------------------------------------+\n"
  406. "|Lorem ipsum dolor sit amet, | |\n"
  407. "|consectetur adipiscing | ### |\n"
  408. "|elit. Curabitur scelerisque | # # |\n"
  409. "|lorem vitae lectus cursus, | # # # ## ### ### |\n"
  410. "|vitae porta ante placerat. Class aptent taciti| ### ## # # # # |\n"
  411. "|sociosqu ad litora | # # # # # # |\n"
  412. "|torquent per | # # # # # # |\n"
  413. "|conubia nostra, | # # ### ### |\n"
  414. "|per inceptos himenaeos. | # |\n"
  415. "| | ## |\n"
  416. "|Donec tincidunt augue | |\n"
  417. "|sit amet metus | # ### ### # |\n"
  418. "|pretium volutpat. | ### # # # ### |\n"
  419. "|Donec faucibus, | # ##### ### # |\n"
  420. "|ante sit amet | # # # # |\n"
  421. "|luctus posuere, | ## ### ### ## |\n"
  422. "|mauris tellus | |\n"
  423. "+----------------------------------------------+------------------------------------------+\n"
  424. "| Bye,|***** * * * ******* ****** *|\n"
  425. "| Hello Kitty|* * * * * * * *|\n"
  426. "| |* * * * * * * *|\n"
  427. "| |* * * * * ***** * *|\n"
  428. "| |**** * * * * * *|\n"
  429. "| |* * * * * * * |\n"
  430. "| |* * * * * * * *|\n"
  431. "| |* * ***** ****** ******* ****** *|\n"
  432. "+----------------------------------------------+------------------------------------------+\n" );
  433. oss . str ("");
  434. oss . clear ();
  435. oss << t1;
  436. assert ( oss . str () ==
  437. "+-----------+------------------------------------------+\n"
  438. "|Hello, | ### |\n"
  439. "|Hello Kitty| # # |\n"
  440. "| | # # # ## ### ### |\n"
  441. "| | ### ## # # # # |\n"
  442. "| | # # # # # # |\n"
  443. "| | # # # # # # |\n"
  444. "| | # # ### ### |\n"
  445. "| | # |\n"
  446. "| | ## |\n"
  447. "| | |\n"
  448. "| | # ### ### # |\n"
  449. "| | ### # # # ### |\n"
  450. "| | # ##### ### # |\n"
  451. "| | # # # # |\n"
  452. "| | ## ### ### ## |\n"
  453. "+-----------+------------------------------------------+\n"
  454. "+-----------+------------------------------------------+\n"
  455. "| Bye,|***** * * * ******* ****** *|\n"
  456. "|Hello Kitty|* * * * * * * *|\n"
  457. "| |* * * * * * * *|\n"
  458. "| |* * * * * ***** * *|\n"
  459. "| |**** * * * * * *|\n"
  460. "| |* * * * * * * |\n"
  461. "| |* * * * * * * *|\n"
  462. "| |* * ***** ****** ******* ****** *|\n"
  463. "+-----------+------------------------------------------+\n" );
  464. t1 = t0;
  465. t1 . setCell ( 0, 0, CEmpty () );
  466. t1 . setCell ( 1, 1, CImage ()
  467. . addRow ( " ******** " )
  468. . addRow ( " ********** " )
  469. . addRow ( "** ** " )
  470. . addRow ( "** ** ** " )
  471. . addRow ( "** ** ** " )
  472. . addRow ( "*** ******** ********" )
  473. . addRow ( "**** ******** ********" )
  474. . addRow ( "**** ** ** " )
  475. . addRow ( "**** ** ** " )
  476. . addRow ( "**** ** " )
  477. . addRow ( " ********** " )
  478. . addRow ( " ******** " ) );
  479. oss . str ("");
  480. oss . clear ();
  481. oss << t0;
  482. assert ( oss . str () ==
  483. "+----------------------------------------------+------------------------------------------+\n"
  484. "|Hello, | ### |\n"
  485. "|Hello Kitty | # # |\n"
  486. "| | # # # ## ### ### |\n"
  487. "| | ### ## # # # # |\n"
  488. "| | # # # # # # |\n"
  489. "| | # # # # # # |\n"
  490. "| | # # ### ### |\n"
  491. "| | # |\n"
  492. "| | ## |\n"
  493. "| | |\n"
  494. "| | # ### ### # |\n"
  495. "| | ### # # # ### |\n"
  496. "| | # ##### ### # |\n"
  497. "| | # # # # |\n"
  498. "| | ## ### ### ## |\n"
  499. "+----------------------------------------------+------------------------------------------+\n"
  500. "|Lorem ipsum dolor sit amet, | |\n"
  501. "|consectetur adipiscing | ### |\n"
  502. "|elit. Curabitur scelerisque | # # |\n"
  503. "|lorem vitae lectus cursus, | # # # ## ### ### |\n"
  504. "|vitae porta ante placerat. Class aptent taciti| ### ## # # # # |\n"
  505. "|sociosqu ad litora | # # # # # # |\n"
  506. "|torquent per | # # # # # # |\n"
  507. "|conubia nostra, | # # ### ### |\n"
  508. "|per inceptos himenaeos. | # |\n"
  509. "| | ## |\n"
  510. "|Donec tincidunt augue | |\n"
  511. "|sit amet metus | # ### ### # |\n"
  512. "|pretium volutpat. | ### # # # ### |\n"
  513. "|Donec faucibus, | # ##### ### # |\n"
  514. "|ante sit amet | # # # # |\n"
  515. "|luctus posuere, | ## ### ### ## |\n"
  516. "|mauris tellus | |\n"
  517. "+----------------------------------------------+------------------------------------------+\n"
  518. "| Bye,|***** * * * ******* ****** *|\n"
  519. "| Hello Kitty|* * * * * * * *|\n"
  520. "| |* * * * * * * *|\n"
  521. "| |* * * * * ***** * *|\n"
  522. "| |**** * * * * * *|\n"
  523. "| |* * * * * * * |\n"
  524. "| |* * * * * * * *|\n"
  525. "| |* * ***** ****** ******* ****** *|\n"
  526. "+----------------------------------------------+------------------------------------------+\n" );
  527. oss . str ("");
  528. oss . clear ();
  529. oss << t1;
  530. assert ( oss . str () ==
  531. "+----------------------------------------------+------------------------------------------+\n"
  532. "| | ### |\n"
  533. "| | # # |\n"
  534. "| | # # # ## ### ### |\n"
  535. "| | ### ## # # # # |\n"
  536. "| | # # # # # # |\n"
  537. "| | # # # # # # |\n"
  538. "| | # # ### ### |\n"
  539. "| | # |\n"
  540. "| | ## |\n"
  541. "| | |\n"
  542. "| | # ### ### # |\n"
  543. "| | ### # # # ### |\n"
  544. "| | # ##### ### # |\n"
  545. "| | # # # # |\n"
  546. "| | ## ### ### ## |\n"
  547. "+----------------------------------------------+------------------------------------------+\n"
  548. "|Lorem ipsum dolor sit amet, | |\n"
  549. "|consectetur adipiscing | |\n"
  550. "|elit. Curabitur scelerisque | ******** |\n"
  551. "|lorem vitae lectus cursus, | ********** |\n"
  552. "|vitae porta ante placerat. Class aptent taciti| ** ** |\n"
  553. "|sociosqu ad litora | ** ** ** |\n"
  554. "|torquent per | ** ** ** |\n"
  555. "|conubia nostra, | *** ******** ******** |\n"
  556. "|per inceptos himenaeos. | **** ******** ******** |\n"
  557. "| | **** ** ** |\n"
  558. "|Donec tincidunt augue | **** ** ** |\n"
  559. "|sit amet metus | **** ** |\n"
  560. "|pretium volutpat. | ********** |\n"
  561. "|Donec faucibus, | ******** |\n"
  562. "|ante sit amet | |\n"
  563. "|luctus posuere, | |\n"
  564. "|mauris tellus | |\n"
  565. "+----------------------------------------------+------------------------------------------+\n"
  566. "| Bye,|***** * * * ******* ****** *|\n"
  567. "| Hello Kitty|* * * * * * * *|\n"
  568. "| |* * * * * * * *|\n"
  569. "| |* * * * * ***** * *|\n"
  570. "| |**** * * * * * *|\n"
  571. "| |* * * * * * * |\n"
  572. "| |* * * * * * * *|\n"
  573. "| |* * ***** ****** ******* ****** *|\n"
  574. "+----------------------------------------------+------------------------------------------+\n" );
  575. assert ( t0 != t1 );
  576. assert ( !( t0 == t1 ) );
  577. assert ( t0 . getCell ( 1, 1 ) == t0 . getCell ( 0, 1 ) );
  578. assert ( ! ( t0 . getCell ( 1, 1 ) != t0 . getCell ( 0, 1 ) ) );
  579. assert ( t0 . getCell ( 0, 0 ) != t0 . getCell ( 0, 1 ) );
  580. assert ( ! ( t0 . getCell ( 0, 0 ) == t0 . getCell ( 0, 1 ) ) );
  581.  
  582. return EXIT_SUCCESS;
  583. }
  584. #endif /* __PROGTEST__ */
Success #stdin #stdout 0.01s 5320KB
stdin
Standard input is empty
stdout
Standard output is empty