source3.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
  1. #ifndef __source3_H__
  2. #define __source3_H__
  3. #include <iostream>
  4. #include <vector>
  5. #include <math.h>
  6. using namespace std;
  7. class Triehard // compressed decimal trie
  8. // constructor should make 1-10 base nodes that are empty for search to work
  9. // magnitude is 1 for length 1, so it must be >= 1
  10. // no more flag, instead we have a count field which counts the number of instances
  11. // the node represents. A small change, but much more functionality
  12. {
  13. private:
  14. class Trienode
  15. {
  16. private:
  17. int magnitude;
  18. int count;
  19. vector<Trienode *> children(10);
  20. public:
  21. Trienode(int magnitude, int count):
  22. magnitude{magnitude}, count{count}
  23. {
  24. for (int i = 0; i < 10; ++i)
  25. {
  26. children[i] = nullptr;
  27. }
  28. }
  29. ~Trienode()
  30. {
  31. for (int i = 0; i < 10; ++i)
  32. {
  33. delete children[i];
  34. }
  35. }
  36. int getMag()
  37. {
  38. return magnitude;
  39. }
  40. int getCount()
  41. {
  42. return count;
  43. }
  44. Trienode * getX(int x)
  45. {
  46. return children[x];
  47. }
  48. void addMag()
  49. {
  50. ++magnitude;
  51. }
  52. void subMag()
  53. {
  54. --magnitude;
  55. }
  56. void addCount()
  57. {
  58. ++count;
  59. }
  60. void subCount()
  61. {
  62. --count;
  63. }
  64. void zeroCount()
  65. {
  66. count = 0;
  67. }
  68. void setCount(int x)
  69. {
  70. count = x;
  71. }
  72. Trienode * setX(int x, int mag, int cnt)
  73. {
  74. children[x] = new Trienode(mag, cnt);
  75. return children[x];
  76. }
  77. void copyX(int x, Trienode * node)
  78. {
  79. children[x] = node;
  80. }
  81. bool isLeaf()
  82. {
  83. for (int i = 0; i < 10; ++i)
  84. {
  85. if (children[i]) return false;
  86. }
  87. return true;
  88. }
  89. // true if x is the only child node
  90. bool onlyKid(x)
  91. {
  92. for (int i = 0; i < 10; ++i)
  93. {
  94. if (i == x)
  95. {
  96. if (!children[i]) return false;
  97. continue;
  98. }
  99. if (children[i]) return false;
  100. }
  101. return true;
  102. }
  103. void changeCustody(Trienode * parent)
  104. {
  105. for (int i = 0; i < 10; ++i)
  106. {
  107. parent->copyX(i, children[i]);
  108. }
  109. }
  110. int sumMag()
  111. {
  112. int result = magnitude;
  113. for (int i = 0; i < 10; ++i)
  114. {
  115. if (children[i]) result += children[i]->sumMag();
  116. }
  117. return result;
  118. }
  119. int sumCount()
  120. {
  121. int result = 1;
  122. for (int i = 0; i < 10; ++i)
  123. {
  124. if (children[i]) result += children[i]->sumCount();
  125. }
  126. return result;
  127. }
  128. };
  129. vector<Trienode *> nodes(10);
  130. public:
  131. Triehard() // Initializes both sides as empty, but makes it searchable, mutatable
  132. {
  133. for (int i = 0; i < 10; ++i)
  134. {
  135. nodes[i] = nullptr;
  136. }
  137. }
  138. ~Triehard() // Same concern (syntax) as nodes, don't forget to write an erase method as well, maybe an empty/wipe
  139. {
  140. for (int i = 0; i < 10; ++i)
  141. {
  142. delete nodes[i];
  143. }
  144. }
  145. // build an array of what is "processed" so far. then when a flag is hit, print that array.
  146. void mainPrint(Trienode * curnode, vector<int> * chars, int val)
  147. {
  148. if (!curnode) return;
  149. int curmag = curnode->getMag();
  150. int curcount = curnode->getCount();
  151. while (curmag)
  152. {
  153. chars->push_back(val);
  154. --curmag;
  155. }
  156. while (curcount)
  157. {
  158. int len = chars->size();
  159. for (int i = 0; i < len; i++)
  160. {
  161. cout << (*chars)[i] << " ";
  162. }
  163. cout << endl;
  164. --curcount;
  165. }
  166. for (int i = 0; i < 10; ++i)
  167. {
  168. mainPrint(children[i], chars, i)
  169. }
  170. curmag = curnode->getMag();
  171. while (curmag)
  172. {
  173. chars->pop_back();
  174. --curmag;
  175. }
  176. }
  177. void myPrintIsBetterThanYoursLogan()
  178. {
  179. for (int i = 0; i < 10; ++i)
  180. {
  181. vector<int> * chars = new vector<int>();
  182. mainPrint(nodes[i], chars, i);
  183. delete side;
  184. }
  185. }
  186. int search(vector<int> * val) // val is the string
  187. {
  188. Trienode * curnode = nodes[(*val)[0]];
  189. int pos = (*val)[0]; // represents what value your current node is
  190. int curmag = curnode->getMag();
  191. for (int i = 0; i < val->size(); i++) // each iteration checks the current character for accuracy.
  192. {
  193. if ((*val)[i] == pos) // if we are on the correct node already
  194. {
  195. if (curmag) // if your current magnitude is >= 1 (still info "left" in this node)
  196. {
  197. --curmag;
  198. }
  199. else if (curnode->getX(pos)) // if our current node is exhausted, move on to the next one
  200. {
  201. curnode = curnode->getX(pos);
  202. curmag = curnode->getMag() - 1;
  203. }
  204. else
  205. {
  206. return 0;
  207. }
  208. }
  209. else // we are not on the right node
  210. {
  211. if (curmag) // if we have magnitude left
  212. {
  213. return 0;
  214. }
  215. else if (curnode->getX(pos)) // if our child for that # exists
  216. {
  217. curnode = curnode->getX(pos);
  218. curmag = curnode->getMag() - 1;
  219. }
  220. else // we don't have the child, must be absent
  221. {
  222. return 0;
  223. }
  224. }
  225. }
  226. if (!curmag)
  227. {
  228. return curnode->getCount();
  229. }
  230. return 0;
  231. }
  232. void insert(vector<int> * val) // assumes valid input
  233. {
  234. Trienode * curnode = nodes[(*val)[0]];
  235. int pos = (*val)[0]; // represents what value your current node is
  236. int curmag = curnode->getMag(); // "remaining" magnitude of the current node
  237. for (int i = 0; i < val->size(); i++) // each iteration validates against curnode for position i
  238. {
  239. if ((*val)[i] == pos) // curnode matches current value
  240. {
  241. if (curmag) // curnode has magnitude left, just sub1 and continue
  242. {
  243. --curmag;
  244. }
  245. else if (curnode->getX(pos)) // curnode is exhausted, but we have the same child with mag >=1, so use that
  246. {
  247. curnode = curnode->getX(pos);
  248. curmag = curnode->getMag() - 1;
  249. }
  250. else if (!(curnode->getCount()) && curnode->isLeaf()) // we aren't flagged and are a leaf, so add mag
  251. {
  252. curnode->addMag();
  253. }
  254. else
  255. {
  256. curnode = curnode->setX(pos, 1, 0) // we must create a child with mag1, curmag is 0 so no change
  257. }
  258. }
  259. else // curnode is not the same digit as val[i]
  260. {
  261. if (curmag) // this means we are going to have to decompress
  262. {
  263. Trienode * newnode = new Trienode(0, curnode->getCount()); // this'll be the second half of curnode-
  264. curnode->zeroCount; // newnode should be flagged (if curnode was), not curnode
  265. while (curmag) // put extra magnitude into newnode
  266. {
  267. curnode->subMag();
  268. --curmag;
  269. newnode->addMag();
  270. }
  271. for (int i = 0; i < 10; i++) // move children to newnode
  272. {
  273. newnode->copyX(i, curnode->getX(i));
  274. curnode->copyX(i, nullptr);
  275. }
  276. curnode->copyX(pos, newnode); // put newnode in its place
  277. curnode = curnode->setX((*val)[i], 1, 0); // insert new node for the string being inserted
  278. curmag = curnode->getMag() - 1; // reset curmag
  279. pos = (*val)[i]; // update pos
  280. }
  281. else if (curnode->getX((*val)[i])) // we have a child of the correct val
  282. {
  283. pos = (*val)[i];
  284. curnode = curnode->getX(pos);
  285. curmag = curnode->getMag() - 1;
  286. }
  287. else // insert a child, curmag is still 0
  288. {
  289. pos = (*val)[i];
  290. curnode = curnode->setX(pos, 1, 0)'
  291. }
  292. }
  293. }
  294. // at this point, the node we are at needs to be flagged. However, there is an issue: this node may have magnitude remaining
  295. // if this is the case, we need to split it up at curnode->getMag() - curmag. lets check for the easy case, then proceed
  296. // with that logic if necessary
  297. // basically curmag is our "extra" magnitude that needs to be sent along
  298. if (!curmag)
  299. {
  300. curnode->addCount();
  301. }
  302. else
  303. {
  304. Trienode * newnode = new Trienode(0, curnode->getCount()); // this is our new node, which should retain old flagging
  305. curnode->setCount(1); // curnode will now end where we want to insert, so this should be true
  306. while (curmag) // fills newnode with the extra magnitude
  307. {
  308. curnode->subMag();
  309. --curmag;
  310. newnode->addMag();
  311. }
  312. for (int i = 0; i < 10; i++) // move children to newnode
  313. {
  314. newnode->copyX(i, curnode->getX(i));
  315. curnode->copyX(i, nullptr);
  316. }
  317. curnode->copyX(pos, newnode); // ensure newnode is actually linked to curnode
  318. }
  319. }
  320. void cut(vector<int> * val) // this is delete because i can't use delete :(
  321. // NOT DONE AT ALL!!!!
  322. {
  323. Trienode * curnode;
  324. Trienode * prevnode = nullptr;
  325. int pos; // represents the represented value of curnode (0-9)
  326. int pos2; // previous node's side
  327. side = (*val)[i];
  328. side2 = side;
  329. curnode = nodes[side];
  330. int curmag = curnode->getMag();
  331. for (int i = 0; i < val->size(); i++) // each iteration checks the current character for accuracy.
  332. {
  333. if ((*val)[i] == pos) // curnode matches current value
  334. {
  335. if (curmag) // we have mag left
  336. {
  337. --curmag;
  338. pos2 = pos;
  339. }
  340. else if (curnode->getX(pos)) // if we have the correct child
  341. {
  342. prevnode = curnode;
  343. curnode = curnode->getX(pos);
  344. curmag = curnode->getMag() - 1;
  345. pos2 = pos;
  346. }
  347. else
  348. {
  349. return; // node does not exist, will make this an error later
  350. }
  351. }
  352. else // curnode does NOT match current value
  353. {
  354. if (curmag)
  355. {
  356. return; // should be error later, but the val isn't inserted, since there is mag left in the wrong number
  357. }
  358. else if (curnode->getX((*val)[i])) // if we have the correct child
  359. {
  360. pos2 = pos;
  361. pos = (*val)[i];
  362. prevnode = curnode;
  363. curnode = curnode->getX((*val)[i]);
  364. curmag = curnode->getMag();
  365. }
  366. else
  367. {
  368. return; // we don't have the right child, so return (to be error)
  369. }
  370. }
  371. }
  372. // at this point, we have curnode being the "end" of our value
  373. if (!(prevnode)) // if we are deleting one of the base trees
  374. {
  375. if (nodes[pos]->getCount()) nodes[pos]->subCount();
  376. else return; // later throw error for removing nothing
  377. }
  378. if (curnode->getCount()) curnode->subCount(); // Normally this is all that is necessary
  379. else return; // later throw error for removing nothing
  380. if (curnode->getCount()) return; // This means we aren't removing a node, so no compression is possible
  381. // Cases where nodes have to be removed/compressed
  382. // THIS NEEDS A LOT OF WORK!!!
  383. if (curnode->isLeaf()) // if our node has no children, destroy it and change parent's reference to NULL
  384. {
  385. delete curnode;
  386. prevnode->copyX(pos, nullptr);
  387. }
  388. else if (prevnode->onlyKid(pos) && pos == pos2) // we have kids (a given now), our parent has none else. compress
  389. {
  390. while (curnode->getMag()) // move mag to parent
  391. {
  392. curnode->subMag();
  393. prevnode->addMag();
  394. }
  395. curnode->changeCustody(prevnode); // move kids to parent
  396. delete curnode;
  397. // wait, can we have a parent and kid of the same # allowing us to compress into both, either, or just parent???
  398. // consider what the children of each have to be to create these conditions
  399. // eg what to do with 00 - 00 (now unflagged) -- 00 (has kids, or a flag)
  400. // no, the above is impossible. the first 00 must have another kid, or a flag or it wouldn't exist
  401. }
  402. else if (curnode->onlyKid(pos))
  403. // parent has other kids or a flag, cannot go into it (maybe like below?). if so, do those.if not,we gotta check if we can compress into our children (only if we have 1 kid, ofc)
  404. {
  405. Trienode * newnode = curnode->getX(pos);
  406. while (curnode->getMag())
  407. {
  408. curnode->subMag();
  409. newnode->addMag();
  410. }
  411. prevnode->copyX(pos, newnode);
  412. delete curnode;
  413. }
  414. }
  415. // update counter with children recursively
  416. void mainCount(Trienode * curnode, int len, int * counter)
  417. {
  418. if (!curnode) return;
  419. len += curnode->getMag();
  420. *counter += (len * curnode->getCount());
  421. for (int i = 0; i < 10; ++i)
  422. {
  423. mainCount(curnode->getX(i), len, counter)
  424. }
  425. }
  426. int countChars() // returns total word length of trie
  427. {
  428. int counter = 0;
  429. for (int i = 0; i < 10; ++i)
  430. {
  431. mainCount(nodes[i], 0, &counter);
  432. }
  433. return counter;
  434. }
  435. float compressionovertrie() // returns nodes / nodes in a normal trie
  436. {
  437. float total = 0;
  438. float compressed = 0;
  439. for (int i = 0; i < 10; ++i)
  440. {
  441. compressed += nodes[i]->sumCount();
  442. total += nodes[i]->sumMag();
  443. }
  444. return roundf(compressed/total * 100) / 100;
  445. }
  446. float compressionoverdict() // returns nodes / sum of all word length
  447. {
  448. float compressed = 0;
  449. for (int i = 0; i < 10; ++i)
  450. {
  451. compressed += nodes[i]->sumCount();
  452. }
  453. float total = countChars();
  454. return roundf(compressed/total * 100) / 100;
  455. }
  456. };
  457. #endif