24点 计算器

24点计算器


没别的办法,只有把各种可能都计算一遍,然后得到能计算出24的表达式,并且尽可能的排除掉重复的表达式

假设有a b c d四个数,操作符用op代替,则有(a op b) op (c op d) 或 ((a op b) op c) op d 两种形式

程序用C# 2.0开发,支持计算 8 / (3 - 8 / 3) = 24 这种

这个程序最伤脑筋的地方就是如何去掉重复的结果,我自己改写了GetHashCode()方法,以尽可能的让重复的表达式计算出相同的值出来


Syntax:

Calc24 [num1 [num2 [num3 [num4]]]]


Example:

Calc24 3 3 8 8
Calc24 3 3 8
Calc24 3 3
Calc24 3
Calc24

若省略参数,则程序自动随机生成一个24以内的数代替

Code:

=============================================================================================

#define Debug
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;

namespace Calculate24
{
class Program
{
static void Main(string[] args)
{
#if Debug
args = new string[] { "2", "2", "2", "4" };
#endif
string[] list = new string[] { "", "", "", "" };

int v1 = 0;
int v2 = 0;
int v3 = 0;
int v4 = 0;

int i = 0;

Console.WriteLine("24 Point Calculator rn");

if (args.Length > 0)
Array.Copy(args, list, Math.Min(args.Length, list.Length));

foreach (string item in list)
{
switch (i)
{
case 0:
v1 = TryParse(item);
i++;
break;
case 1:
v2 = TryParse(item);
i++;
break;
case 2:
v3 = TryParse(item);
i++;
break;
case 3:
v4 = TryParse(item);
i++;
break;
}
}

string outString = Calculate.Run(v1, v2, v3, v4);

if (!string.IsNullOrEmpty(outString))
{
Console.WriteLine(outString);
}
else
{
Console.WriteLine(string.Format("{0} {1} {2} {3} 无论如何都无法计算得出 24rn", new object[] { v1, v2, v3, v4 }));
}

Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}

private static Random random = new Random(Environment.TickCount);
private static int TryParse(string value)
{
int result = 0;

if (value.Length > 0)
int.TryParse(value, out result);

if (result <= 0)
result = random.Next(1, 24); //throw new Exception("输入数字必须大于0,发现输入值[" + value + "].");

return result;
}
}
}

=============================================================================================

using System;
using System.Collections.Generic;
using System.Text;

namespace Calculate24
{
public class Calculate
{
public static string Run(int v1, int v2, int v3, int v4)
{
ValueList listLeft = new ValueList();
ValueList listRight = new ValueList();
ValueList listResult = new ValueList();

BuildValueList(listLeft, v1, v2);
BuildValueList(listRight, v3, v4);

foreach (Value vl in listLeft)
{
foreach (Value vr in listRight)
{
BuildValueList(listResult, vl, vr);
}
}

if (v2 != v3)
{
BuildValueList(listLeft, v1, v3);
BuildValueList(listRight, v2, v4);
}
foreach (Value vl in listLeft)
{
foreach (Value vr in listRight)
{
BuildValueList(listResult, vl, vr);
}
}

if (v2 != v4)
{
BuildValueList(listLeft, v1, v4);
BuildValueList(listRight, v2, v3);
}
foreach (Value vl in listLeft)
{
foreach (Value vr in listRight)
{
BuildValueList(listResult, vl, vr);
}
}

BuildValueList(listLeft, listRight, listResult, v1, v2, v3, v4);
BuildValueList(listLeft, listRight, listResult, v1, v3, v2, v4);
BuildValueList(listLeft, listRight, listResult, v1, v3, v4, v2);
BuildValueList(listLeft, listRight, listResult, v1, v2, v4, v3);
BuildValueList(listLeft, listRight, listResult, v1, v4, v2, v3);
BuildValueList(listLeft, listRight, listResult, v1, v4, v3, v2);

BuildValueList(listLeft, listRight, listResult, v2, v3, v1, v4);
BuildValueList(listLeft, listRight, listResult, v2, v3, v4, v1);
BuildValueList(listLeft, listRight, listResult, v2, v4, v1, v3);
BuildValueList(listLeft, listRight, listResult, v2, v4, v3, v1);

BuildValueList(listLeft, listRight, listResult, v3, v4, v1, v2);
BuildValueList(listLeft, listRight, listResult, v3, v4, v2, v1);

return listResult.ToString();
}

private static void BuildValueList(ValueList listLeft, ValueList listRight, ValueList listResult,
double v1, double v2, double v3, double v4)
{
BuildValueList(listLeft, v1, v2);
listRight.Clear();
foreach (Value vl in listLeft)
{
BuildValueList(listRight, vl, v3);
}
foreach (Value vl in listRight)
{
BuildValueList(listResult, vl, v4);
}
}

private static void BuildValueList(ValueList list, double v1, double v2)
{
list.Clear();
list.AddValue(new Value(v1, v2, '+'));
list.AddValue(new Value(v1, v2, '*'));
if (v1 >= v2)
{
list.AddValue(new Value(v1, v2, '-'));
list.AddValue(new Value(v1, v2, '/'));
}
else
{
list.AddValue(new Value(v2, v1, '-'));
list.AddValue(new Value(v2, v1, '/'));
}
if (v1 != v2)
{
if (v1 >= v2)
{
list.AddValue(new Value(v2, v1, '-'));
list.AddValue(new Value(v2, v1, '/'));
}
else
{
list.AddValue(new Value(v1, v2, '-'));
list.AddValue(new Value(v1, v2, '/'));
}
}
}

private static void BuildValueList(ValueList list, Value v1, Value v2)
{
list.AddValue(new Value(v1, v2, '+'));
list.AddValue(new Value(v1, v2, '*'));
if (v1.value >= v2.value)
{
list.AddValue(new Value(v1, v2, '-'));
list.AddValue(new Value(v1, v2, '/'));
}
else
{
list.AddValue(new Value(v2, v1, '-'));
list.AddValue(new Value(v2, v1, '/'));
}
if (v1.value != v2.value)
{
if (v1.value >= v2.value)
{
list.AddValue(new Value(v2, v1, '-'));
list.AddValue(new Value(v2, v1, '/'));
}
else
{
list.AddValue(new Value(v1, v2, '-'));
list.AddValue(new Value(v1, v2, '/'));
}
}
}

private static void BuildValueList(ValueList list, Value v1, double v2)
{
list.AddValue(new Value(v1, v2, '+'));
list.AddValue(new Value(v1, v2, '*'));
if (v1.value >= v2)
{
list.AddValue(new Value(v1, v2, '-'));
list.AddValue(new Value(v1, v2, '/'));
}
else
{
list.AddValue(new Value(v2, v1, '-'));
list.AddValue(new Value(v2, v1, '/'));
}
if (v1.value != v2)
{
if (v1.value >= v2)
{
list.AddValue(new Value(v2, v1, '-'));
list.AddValue(new Value(v2, v1, '/'));
}
else
{
list.AddValue(new Value(v1, v2, '-'));
list.AddValue(new Value(v1, v2, '/'));
}
}
}
}
}

=============================================================================================

using System;
using System.Collections.Generic;
using System.Text;

namespace Calculate24
{
public class Value
{

private double v1;
private double v2;
private char op;

public double value;

public Value vv1 = null;
public Value vv2 = null;

public Value(double V1, double V2, char OP)
{
v1 = V1;
v2 = V2;
op = OP;
CalculateValue();
}

public Value(Value V1, Value V2, char OP)
{
v1 = V1.value;
vv1 = V1;
v2 = V2.value;
vv2 = V2;
op = OP;
CalculateValue();
}

public Value(Value V1, double V2, char OP)
{
v1 = V1.value;
vv1 = V1;
v2 = V2;
op = OP;
CalculateValue();
}

public Value(double V1, Value V2, char OP)
{
v1 = V1;
v2 = V2.value;
vv2 = V2;
op = OP;
CalculateValue();
}

private void CalculateValue()
{
value = 0;

switch (op)
{
case '+':
value = v1 + v2;
break;
case '-':
value = v1 - v2;
break;
case '*':
value = v1 * v2;
break;
case '/':
if (v2 != 0)
value = v1 / v2;
else
value = double.MinValue;
break;
}
CalculateHashCode();
}

public override string ToString()
{
string s1;
string s2;
if (vv1 != null)
{
s1 = vv1.ToString();
if ("*/".IndexOf(op) >= 0 && "+-".IndexOf(vv1.op) >= 0)
s1 = "(" + s1 + ")";
}
else
s1 = v1.ToString();
if (vv2 != null)
{
s2 = vv2.ToString();
if (("*/".IndexOf(op) >= 0 && "+-".IndexOf(vv2.op) >= 0) || (op == '-' && "+-".IndexOf(vv2.op) >= 0) || (op == '/' && "*/".IndexOf(vv2.op) >= 0))
s2 = "(" + s2 + ")";
}
else
s2 = v2.ToString();
return String.Format("{0} {1} {2}", s1, op, s2);
}

public override int GetHashCode()
{
return hashCode;
}

private int hashCode = 0;

private void CalculateHashCode()
{
hashCode = value.GetHashCode();

byte[] buffer = Encoding.UTF8.GetBytes(ToString());

foreach (byte b in buffer)
{
hashCode += b;
}

hashCode += buffer.Length * 7;
}
}
}

=============================================================================================

using System;
using System.Collections.Generic;
using System.Text;

namespace Calculate24
{
public class ValueList : List
{
public void AddValue(Value item)
{
if (item.value != double.MinValue)
{
bool isResult = ((item.vv1 != null && item.vv2 != null) || (item.vv1 != null && (item.vv1.vv1 != null ||
item.vv1.vv2 != null)) || (item.vv2 != null && (item.vv2.vv1 != null || item.vv2.vv2 != null)));
if (isResult && Math.Abs(item.value - 24) > 0.00001)
{
//Console.WriteLine("DEBUG: " + item.ToString());
return;
}
int hash = item.GetHashCode();
foreach (Value value in this)
{
if (hash == value.GetHashCode())
return;
}
Add(item);
}
}

public override string ToString()
{
StringBuilder sb = new StringBuilder();
foreach (Value item in this)
{
sb.AppendLine(item.ToString() + " = 24");
}
return sb.ToString();
}
}
}

=============================================================================================
Appendix:

以下是一些答案比较唯一的题目,你可以试试:

1 1 3 4
1 3 4 6
1 3 9 10
1 3 13 16
1 4 7 9
1 5 5 5
1 5 7 9
1 5 8 13
1 5 9 9
1 5 11 16
1 6 7 9
1 7 7 9
1 7 7 12
1 7 7 17
1 9 11 11
1 9 11 13
2 2 5 8
2 2 11 11
2 3 10 10
2 4 7 7
2 4 10 10
2 5 5 10
2 5 6 9
2 5 7 9
2 16 18 19
3 3 3 3
3 3 7 7
3 3 8 8
3 3 8 201
3 3 8 208
3 3 23 207
3 5 6 77
4 4 7 7
4 4 10 10
4 5 6 9
4 16 18 19
5 5 18 77
5 10 10 13
5 10 10 17
6 6 8 8
7 8 9 10
7 8 9 12
7 8 10 10
7 8 10 11
9 9 9 12
9 11 12 13
11 13 17 19

posted @ 2007-05-09 13:29  Yoshow  阅读(2068)  评论(0编辑  收藏  举报