Advertisement
Guest User

Untitled

a guest
Mar 28th, 2013
296
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.80 KB | None | 0 0
  1. // buspuzzle.h
  2.  
  3. #ifndef BUSPUZZLE_H
  4. #define BUSPUZZLE_H
  5.  
  6. #include <string>
  7. #include <set>
  8.  
  9. typedef uint8_t byte;
  10.  
  11. std::string busPuzzleSolve(std::string input);
  12.  
  13. class BinTree
  14. {
  15.   private:
  16.     struct BinTreeException {};
  17.     struct BinTreeIncorrectSeed: BinTreeException {};
  18.     struct BinTreeLastTree: BinTreeException {};
  19.     struct BinTreeDivisionError: BinTreeException {};
  20.  
  21.     enum Operation
  22.     {
  23.       CONCAT, ADD, SUB, MUL, DIV, NUMBER
  24.     } type;
  25.  
  26.     static const char operationSymbol[];
  27.  
  28.     byte* digit;
  29.  
  30.     byte leftSize;
  31.  
  32.     byte size;
  33.     BinTree *left, *right;
  34.  
  35.     void buildNext();
  36.     void generateSubTrees();
  37.     std::string filterSolutions(std::set<std::string> solutions);
  38.  
  39.   public:
  40.     BinTree(const char* seed);
  41.     ~BinTree();
  42.  
  43.     int compute();
  44.     Operation getType();
  45.     std::string toString(bool parentheses = true);
  46.  
  47.     std::string solve();
  48. };
  49.  
  50. #endif // BUSPUZZLE_H
  51.  
  52. //-------------------------------------------------------------------------------------//
  53.  
  54. // buspuzzle.cpp
  55.  
  56. #include <cmath>
  57. #include <cstdlib>
  58. #include <iostream>
  59. #include <cstring>
  60.  
  61. #include "buspuzzle.h"
  62.  
  63. std::string busPuzzleSolve(std::string input)
  64. {
  65.   return BinTree(input.c_str()).solve();
  66. }
  67.  
  68. const char BinTree::operationSymbol[] = {' ', '+', '-', '*', '/'};
  69.  
  70. BinTree::BinTree(const char* seed)
  71. {
  72.   size = strlen(seed);
  73.  
  74.   leftSize = 1;
  75.  
  76.   if (size == 1)
  77.     type = NUMBER;
  78.   else
  79.     type = CONCAT;
  80.  
  81.   digit = new byte[size];
  82.   for (int i = 0; i < size; i++)
  83.   {
  84.     if (!isdigit(seed[i]))
  85.       throw BinTreeIncorrectSeed();
  86.    
  87.     digit[i] = seed[i] - '0';
  88.   }
  89.  
  90.   left = right = NULL;
  91.  
  92.   if (type != NUMBER)
  93.   {
  94.     generateSubTrees();
  95.   }
  96. }
  97.  
  98. BinTree::~BinTree()
  99. {
  100.   delete left;
  101.   delete right;
  102.   delete[] digit;
  103. }
  104.  
  105. void BinTree::buildNext()
  106. {
  107.   if (type == NUMBER)
  108.       throw BinTreeLastTree();
  109.   try
  110.   {
  111.     left->buildNext();
  112.   }
  113.   catch (BinTreeLastTree)
  114.   {
  115.     try
  116.     {
  117.       right->buildNext();
  118.     }
  119.     catch (BinTreeLastTree)
  120.     {
  121.       bool isLast = false;
  122.  
  123.       leftSize++;
  124.       if (leftSize == size)
  125.       {
  126.         leftSize = 1;
  127.  
  128.         type = (Operation)(type + 1);
  129.         if (type == NUMBER)
  130.         {
  131.           type = CONCAT;
  132.           isLast = true;
  133.         }
  134.       }
  135.  
  136.       delete left;
  137.       delete right;
  138.       generateSubTrees();
  139.  
  140.       if (isLast)
  141.         throw BinTreeLastTree();
  142.     }
  143.   }
  144. }
  145.  
  146. void BinTree::generateSubTrees()
  147. {
  148.   char *leftSeed = new char[leftSize + 1];
  149.   char *rightSeed = new char[size - leftSize + 1];
  150.  
  151.   for (int i = 0; i < leftSize; i++)
  152.   {
  153.     leftSeed[i] = digit[i] + '0';
  154.   }
  155.   leftSeed[leftSize] = '\0';
  156.  
  157.   for (int i = 0; i < size - leftSize; i++)
  158.   {
  159.     rightSeed[i] = digit[i+leftSize] + '0';
  160.   }
  161.   rightSeed[size-leftSize] = '\0';
  162.  
  163.   left = new BinTree(leftSeed);
  164.   right = new BinTree(rightSeed);
  165.  
  166.   delete[] leftSeed;
  167.   delete[] rightSeed;
  168. }
  169.  
  170. int BinTree::compute()
  171. {
  172.   switch (type)
  173.   {
  174.     case CONCAT:
  175.       if ((left->getType() == NUMBER || left->getType() == CONCAT) &&
  176.           left->compute() != 0 && right->getType() == NUMBER)
  177.         return left->compute()*10 + right->compute();
  178.       else
  179.         break;
  180.  
  181.     case ADD:
  182.       return left->compute() + right->compute();
  183.  
  184.     case SUB:
  185.       return left->compute() - right->compute();
  186.  
  187.     case MUL:
  188.       return left->compute() * right->compute();
  189.  
  190.     case DIV:
  191.       {
  192.         int l = left->compute(), r = right->compute();
  193.         if ((r == 0) || (l%r != 0))
  194.           throw BinTreeDivisionError();
  195.  
  196.         return l/r;
  197.       }
  198.  
  199.     case NUMBER:
  200.       return digit[0];
  201.  
  202.     default:
  203.       ;
  204.   }
  205.   throw BinTreeException();
  206. }
  207.  
  208. BinTree::Operation BinTree::getType()
  209. {
  210.   return type;
  211. }
  212.  
  213. std::string BinTree::toString(bool parentheses)
  214. {
  215.   switch (type)
  216.   {
  217.     case CONCAT:
  218.       return left->toString() + right->toString();
  219.  
  220.     case ADD:
  221.       {
  222.         std::string leftStr = left->toString(!(left->getType() == ADD || left->getType() == SUB)),
  223.                     rightStr = right->toString(!(right->getType() == ADD || right->getType() == SUB));
  224.  
  225.         return (parentheses?"(":"") + leftStr + operationSymbol[type] + rightStr + (parentheses?")":"");
  226.       }
  227.  
  228.     case SUB:
  229.       {
  230.         std::string leftStr = left->toString(!(left->getType() == ADD || left->getType() == SUB));
  231.  
  232.         return (parentheses?"(":"") + leftStr + operationSymbol[type] + right->toString() + (parentheses?")":"");
  233.       }
  234.  
  235.     case MUL:
  236.       {
  237.         std::string leftStr = left->toString(!(left->getType() == MUL || left->getType() == DIV)),
  238.                     rightStr = right->toString(!(right->getType() == MUL || right->getType() == DIV));
  239.  
  240.         return (parentheses?"(":"") + leftStr + operationSymbol[type] + rightStr + (parentheses?")":"");
  241.       }
  242.  
  243.     case DIV:
  244.       return (parentheses?"(":"") + left->toString() + operationSymbol[type] + right->toString() + (parentheses?")":"");
  245.  
  246.     case NUMBER:
  247.       {
  248.         char str[2] = {(char)(digit[0]+'0'), '\0'};
  249.         return str;
  250.       }
  251.  
  252.     default:
  253.       ;
  254.   }
  255.   throw BinTreeException();
  256. }
  257.  
  258. std::string BinTree::solve()
  259. {
  260.   std::set<std::string> solutions;
  261.  
  262.   try
  263.   {
  264.     while (true)
  265.     {
  266.       buildNext();
  267.  
  268.       int result = 0;
  269.       try
  270.       {
  271.         result = compute();
  272.       }
  273.       catch (...)
  274.       {
  275.         //
  276.       }
  277.  
  278.       if (result == 100)
  279.         solutions.insert(toString(false));
  280.     }
  281.   }
  282.   catch (BinTreeLastTree)
  283.   {
  284.     //
  285.   }
  286.  
  287.   return filterSolutions(solutions);
  288. }
  289.  
  290. std::string BinTree::filterSolutions(std::set<std::string> solutions)
  291. {
  292.   std::string filtered = "";
  293.  
  294.   for (std::set<std::string>::iterator i = solutions.begin(); i != solutions.end(); ++i)
  295.   {
  296.     filtered += *i + "\n";
  297.   }
  298.   return filtered;
  299. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement