24-Point Poker game algorithm implementation

Source: Internet
Author: User
Tags arithmetic assert

The 24-point poker game is probably played by everyone, the rule is very simple, randomly pulling out four cards, consisting of numbers from 1 to 9 (and, of course, extending to any integer), and then using subtraction and parentheses to form an arithmetic expression that evaluates whether the expression can be 24 (or any integer). The first reaction to this problem is to use the exhaustive method, which is to create a search tree, enumerate all the possibilities, and then check each possible result to be 24. Based on this idea, we can divide the problem into three steps:

First you can list all the permutations of 4 integers, that is, the question of all the permutations of the elements in the set, is it familiar? I believe many people have seen this problem, the general way is to use the recursive function of the realization: If you use an array a[4] to hold these 4 integers, then the No. 0 position may be 4, the 1th position may be 3 (because 1 elements have been identified before), the 2nd position may be 2, and the 3rd position may be 1 kinds , so that all may happen to be P (4,4) = 24. Of course, for cases with repeating elements, such as {1,5,5,5}, where the total number of permutations is 4, we need to eliminate duplication in recursive functions to reduce unnecessary computations.

Second, we want to determine the 3 operators between the 4 integers in an arithmetic expression. The operator is determined in the same way that the integer was previously determined, except that we were selected three times from 4 operators, so the 1th operator might be 4, the 2nd operator might be 4, and the 3rd. Because 4 operators can be selected each time, according to the algorithm principle, all of the possible 4*4*4=64 species. If all the operators have the same precedence, then the problem will be the result, all of which may be 24*64=1536 species. Is it easy? OK, let's continue with the analysis.

The third step is to add the precedence of the operator and the possible parentheses. Priority level? Brackets? These two things are more troublesome, because each integer can appear before and after parentheses, the contents of parentheses have a high priority, and operators in the multiplication and division of precedence is higher than the addition and subtraction, even if they appear in the back to the first operation, how to do? Let's take a look at the idea of compiling principles: ordinary arithmetic expressions are infix expressions, such as ((1+2) +3) *4, to remove these two troublesome things, the best way is to use the suffix expression (reverse-Polish, Reverse Polish notation) to express, For example the reverse-Polish form of the preceding arithmetic expression for 12+3+4*. So it's easy to understand? This step can be done this way, for the determined integers and operators, find all possible inverse Polish operations, if the result is 24, then the inverse of the Polish into infix form for output (the reason for this is infix expression more in line with people's reading habits, of course, you can skip this step). Now that the idea is clear, then the rest of the work is how to achieve the problem.

The standard algorithm for parsing inverse polish is to use stack, subtraction are two-dollar operators, which means that the elements in the stack must be more than 2 to be legitimate, so this problem of finding all the inverse poles becomes an additional condition for all possible stack sequences. The parsed recursive function can be constructed like this: the end condition is that all of the operators have been computed, at which point all integers have been calculated, the stack has only a top position of the value, which is the final calculation, you can directly compare it with 24; there are two recursive paths, One is to check whether the elements in the stack are greater than or equal to 2, and if so, pop them out, take out the current operator, push the result back to stack, and then recursively, the other is to push the current integer into the stack and direct recursion. This builds the search tree to cover all possible stack sequences, which is the reverse Polish we want.

(Code compiled by vc++2005/2008)

#include "stdafx.h"
#include <assert.h>
#include <iostream>
#include <vector>
#include <string>
#include <utility>
#include <stack>
#include <queue>
#include <algorithm>

#define Double_equal (A, B) ((a-b<0.00001) && (b-a) <0.00001)
#define OPSSIZE 4
#define Expresult 24
Std::vector<std::string> outputlist;
Char Operators[opssize] = {' + ', '-', ' * ', '/'};

void Antipolish (std::stack<double>& s, std::queue<int>& Q, std::vector<int>& nums, std: :vector<char>& OPS)
{
if (ops.size () = = 0)
{
ASSERT (Nums.size () ==0 && s.size () ==1);
if (Double_equal (S.top (), Expresult))
{
std::string str;
while (!q.empty ())
{
str = Q.front ();
Q.pop ();
}
Outputlist.push_back (str);
}
Return
}
Std::stack<double> temps = s;
std::queue<int> TEMPQ = q;
std::vector<int> tempnums = nums;
Std::vector<char> tempops = OPS;
if (S.size () >= 2)
{
Double operand2 = S.top ();
S.pop ();
Double operand1 = S.top ();
S.pop ();

Switch (Ops.front ())
{
Case ' + ':
Operand1 + = Operand2;
Break
Case '-':
Operand1-= Operand2;
Break
Case ' * ':
Operand1 *= Operand2;
Break
Case '/':
if (!double_equal (operand2, 0))
Operand1/= Operand2;
Else
Return
Break
Default
Return
}
S.push (OPERAND1);
Q.push (Ops.front ());
Ops.erase (Ops.begin ());
Antipolish (S, Q, Nums, OPS);
s = temps;
Q = TEMPQ;
OPS = Tempops;
}
if (Nums.size () >0)
{
S.push (Nums.front ());
Q.push (Nums.front () +0x30);
Nums.erase (Nums.begin ());
Antipolish (S, Q, Nums, OPS);
s = temps;
Q = TEMPQ;
Nums = Tempnums;
}
}

void Search (std::vector<int> nums, int n, std::vector<char> Ops)
{
if (n = = (static_cast<int> (nums.size ())-1)
{
Std::stack<double> s;
Std::queue<int> Q;
Antipolish (S, Q, Nums, OPS);
Return
}
for (int i=n; i<static_cast<int> (Nums.size ()); i++)
{
bool duplicated = false;
for (int k=n; k<i; k++)
if (Nums[i]==nums[k])
{
duplicated = true;
Break
}
if (!duplicated)
{
Std::swap (Nums[n], nums[i]);
for (int j=0; j<opssize; j + +)
{
Ops.push_back (Operators[j]);
Search (Nums, n+1, OPS);
Ops.pop_back ();
}
Std::swap (Nums[n], nums[i]);
}
}
}

int _tmain (int argc, _tchar* argv[])
{
Std::vector<char> str;
Std::vector<int> numbers;
Numbers.push_back (1);
Numbers.push_back (2);
Numbers.push_back (3);
Numbers.push_back (4);
Search (numbers, 0, str);
return 0;
}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.