Advertisement
Guest User

Untitled

a guest
Oct 14th, 2017
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.42 KB | None | 0 0
  1. #include <array>
  2. #include <iostream>
  3. #include <functional>
  4. #include <string>
  5. #include <utility>
  6. #include <vector>
  7.  
  8. #include <cctype>
  9. #include <cstring>
  10.  
  11. #include "exprtk.hpp"
  12.  
  13.  
  14. using expr_t = exprtk::expression<float>;
  15. using parser_t = exprtk::parser<float>;
  16.  
  17.  
  18. template<size_t N, size_t M>
  19. struct usage_matrix : std::array<bool, N*M> {
  20.     usage_matrix() {
  21.         memset(this, 0, sizeof(*this));
  22.     }
  23.     usage_matrix(const usage_matrix&) = default;
  24.     usage_matrix(usage_matrix&&) = default;
  25.     usage_matrix& operator=(const usage_matrix&) = default;
  26.     usage_matrix& operator=(usage_matrix&&) = default;
  27.  
  28.     decltype(auto) operator()(size_t i, size_t j) const {
  29.         return (*this)[i*M + j];
  30.     }
  31.     decltype(auto) operator()(size_t i, size_t j) {
  32.         return (*this)[i*M + j];
  33.     }
  34. };
  35.  
  36. template<size_t N, size_t M, typename P>
  37. usage_matrix<N, M> to_usage_matrix(const char* field, P&& predicate)
  38. {
  39.     usage_matrix<N, M> ret;
  40.  
  41.     for (unsigned i = 0; i < N; i++)
  42.         for (unsigned j = 0; j < M; j++)
  43.             ret(i, j) = predicate(field[i*M + j]);
  44.  
  45.     return ret;
  46. }
  47.  
  48.  
  49. class move {
  50. public:
  51.     enum enam : char {
  52.         U, UR,
  53.         R, DR,
  54.         D, DL,
  55.         L, UL,
  56.     };
  57. };
  58.  
  59. const char* move_to_arrow[] = {
  60.     "↑", "↗",
  61.     "→", "↘",
  62.     "↓", "↙",
  63.     "←", "↖",
  64. };
  65.  
  66. using seq_of_moves = std::vector<move::enam>;
  67.  
  68. std::ostream& operator<<(std::ostream& os, const seq_of_moves& moves)
  69. {
  70.     for (auto move : moves)
  71.         os << move_to_arrow[move];
  72.  
  73.     return os;
  74. }
  75.  
  76. const std::pair<int, int> move_to_dxdy[] = {
  77.     { -1,  0 }, // up
  78.     { -1, +1 }, // up-right
  79.     {  0, +1 }, // right
  80.     { +1, +1 }, // down-right
  81.     { +1,  0 }, // down
  82.     { +1, -1 }, // down-left
  83.     {  0, -1 }, // left
  84.     { -1, -1 }, // up-left
  85. };
  86.  
  87. std::pair<int, int> operator+(std::pair<int, int> x, std::pair<int, int> dx)
  88. {
  89.     return { x.first + dx.first, x.second + dx.second };
  90. }
  91.  
  92. template<size_t N, size_t M>
  93. bool is_move_possible(usage_matrix<N, M>& matrix, std::pair<int, int> cur_pos, std::pair<int, int> dxdy)
  94. {
  95.     std::pair<int, int> upd_pos = cur_pos + dxdy;
  96.     int i = upd_pos.first;
  97.     int j = upd_pos.second;
  98.  
  99.     if (i < 0 || size_t(i) >= N)
  100.         return false;
  101.  
  102.     if (j < 0 || size_t(j) >= M)
  103.         return false;
  104.  
  105.     return matrix(i, j) == 0;
  106. }
  107.  
  108. template<size_t N, size_t M>
  109. unsigned char get_possible_moves(usage_matrix<N, M>& matrix, std::pair<int, int> cur_pos)
  110. {
  111.     unsigned char ret = 0;
  112.     for (int i = 0; i < 8; i++) {
  113.         ret |= is_move_possible(matrix, cur_pos, move_to_dxdy[i]) << i;
  114.     }
  115.     return ret;
  116. }
  117.  
  118. parser_t parser;
  119. expr_t expression;
  120.  
  121. template<size_t N, size_t M>
  122. void find_solutions(usage_matrix<N, M> digits, usage_matrix<N, M> signs,
  123.                     std::pair<int, int> cur_pos,
  124.                     const char* fld, std::string expr, size_t sol_length,
  125.                     seq_of_moves moves, std::vector<seq_of_moves>& out)
  126. {
  127.     if (expr.length() == sol_length) {
  128.         parser.compile(expr, expression);
  129.         if (expression.value() == 0) {
  130.             std::cout << expr << '\t' << moves << '\n';
  131.             out.push_back(std::move(moves));
  132.         }
  133.         return;
  134.     }
  135.  
  136.     unsigned char sign_moves = get_possible_moves(signs, cur_pos);
  137.     for (int i = 0; i < 8; i++) {
  138.         if (((sign_moves >> i) & 1) == 0)
  139.             continue;
  140.  
  141.         auto upd_pos_1 = cur_pos + move_to_dxdy[i];
  142.         auto upd_signs = signs;
  143.         auto upd_expr_1 = expr;
  144.         auto upd_moves_1 = moves;
  145.  
  146.         upd_signs(upd_pos_1.first, upd_pos_1.second) = 1;
  147.         upd_expr_1 += fld[upd_pos_1.first * M + upd_pos_1.second];
  148.         upd_moves_1.push_back(move::enam(i));
  149.  
  150.         unsigned char digit_moves = get_possible_moves(digits, upd_pos_1);
  151.         for (int j = 0; j < 8; j++) {
  152.             if (((digit_moves >> j) & 1) == 0)
  153.                 continue;
  154.  
  155.             auto upd_pos_2 = upd_pos_1 + move_to_dxdy[j];
  156.             auto upd_digits = digits;
  157.             auto upd_expr_2 = upd_expr_1;
  158.             auto upd_moves_2 = upd_moves_1;
  159.  
  160.             upd_digits(upd_pos_2.first, upd_pos_2.second) = 1;
  161.             upd_expr_2 += fld[upd_pos_2.first * M + upd_pos_2.second];
  162.             upd_moves_2.push_back(move::enam(j));
  163.  
  164.             find_solutions(std::move(upd_digits), std::move(upd_signs),
  165.                            upd_pos_2,
  166.                            fld, std::move(upd_expr_2), sol_length,
  167.                            std::move(upd_moves_2), out);
  168.         }
  169.     }
  170. }
  171.  
  172.  
  173. #ifndef __TEST__
  174.  
  175. int main(int argc, char* argv[])
  176. {
  177.  
  178.     const int width = 4;
  179.     const int height = 6;
  180.     const char* field =
  181.         "1+5-"
  182.         "2-7+"
  183.         "3+3*"
  184.         "4+2-"
  185.         "2-4+"
  186.         "62-4"
  187.     ;
  188.  
  189.     auto initial_digits = to_usage_matrix<height, width>(field, [](auto c) {
  190.         return !isdigit(c);
  191.     });
  192.     auto initial_signs  = to_usage_matrix<height, width>(field, [](auto c) {
  193.         return isdigit(c);
  194.     });
  195.     initial_digits(0, 0) = 1;
  196.     initial_digits(0, 2) = 1;
  197.  
  198.     std::pair<int, int> initial_pos = {0, 0};
  199.     std::string initial_expr = "1";
  200.     const int solution_length = 11;
  201.     seq_of_moves initial_moves = { };
  202.  
  203.     std::vector<seq_of_moves> solutions;
  204.  
  205.     find_solutions(std::move(initial_digits), std::move(initial_signs),
  206.                    initial_pos,
  207.                    field, std::move(initial_expr), solution_length,
  208.                    std::move(initial_moves), solutions);
  209.  
  210.     std::cout << solutions.size() << '\n';
  211. }
  212.  
  213. #else
  214.  
  215. #define CATCH_CONFIG_MAIN
  216. #include "catch.hpp"
  217.  
  218. TEST_CASE("Test is_move_possible", "[is_move_possible]") {
  219.     usage_matrix<2, 2> matrix_1;
  220.  
  221.     REQUIRE( is_move_possible(matrix_1, {0, 0}, { -1,  0 }) == false );
  222.     REQUIRE( is_move_possible(matrix_1, {0, 0}, { -1, -1 }) == false );
  223.     REQUIRE( is_move_possible(matrix_1, {0, 0}, { +1, +1 }) == true );
  224.     REQUIRE( is_move_possible(matrix_1, {0, 0}, {  0, +1 }) == true );
  225.     REQUIRE( is_move_possible(matrix_1, {1, 1}, { -1,  0 }) == true );
  226.     REQUIRE( is_move_possible(matrix_1, {1, 1}, { -1, -1 }) == true );
  227.     REQUIRE( is_move_possible(matrix_1, {1, 1}, { +1, +1 }) == false );
  228.     REQUIRE( is_move_possible(matrix_1, {1, 1}, {  0, +1 }) == false );
  229. }
  230.  
  231. TEST_CASE("Test get_possible_moves", "[get_possible_moves]") {
  232.     usage_matrix<2, 2> matrix_1;
  233.  
  234.     REQUIRE( get_possible_moves(matrix_1, {0, 0}) == (1 << move::R) + (1 << move::DR) + (1 << move::D) );
  235.     REQUIRE( get_possible_moves(matrix_1, {0, 1}) == (1 << move::L) + (1 << move::DL) + (1 << move::D) );
  236.     REQUIRE( get_possible_moves(matrix_1, {1, 0}) == (1 << move::R) + (1 << move::UR) + (1 << move::U) );
  237.     REQUIRE( get_possible_moves(matrix_1, {1, 1}) == (1 << move::L) + (1 << move::UL) + (1 << move::U) );
  238.  
  239.     matrix_1(0, 0) = 1;
  240.  
  241.     REQUIRE( get_possible_moves(matrix_1, {1, 1}) == (1 << move::L) + (0 << move::UL) + (1 << move::U) );
  242.  
  243.     usage_matrix<3, 3> matrix_2;
  244.  
  245.     REQUIRE( get_possible_moves(matrix_2, {1, 1}) == 0xff );
  246. }
  247.  
  248. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement