在尝试解决以下任务时:
使用算术运算符(+, - ,*,/)重新排列四个五等于数字1到10。 的
实施例:5/5 + 5-5 = 1,5 / 5 + 5/5 = 2 的
我在没有使用Linq的情况下尝试使用C#(我不知道如何继续进行)
public void GetDetails()
{
char[] sym = new char[] { '+', '-', '/', '*' };
int[] AOf5 = new int[] { 5, 5, 5, 5 };
for (int i = 0; i <4; i++)
{
for (int j = 0; j <4; j++)
{
for (int k = 0; k <4; k++)
{
for (int l = 0; l < 4; l++)
{
int result1 = AOf5[0] + sym[i] + AOf5[1] + sym[j] +
AOf5[2] + sym[k] + AOf5[3];
int result2 = AOf5[0] + sym[i] + AOf5[1] + sym[j] +
AOf5[2] + sym[l] + AOf5[3];
int result3 = AOf5[0] + sym[i] + AOf5[1] +
sym[k] + AOf5[2] + sym[l] + AOf5[3];
....
....
}
}
}
}
}
如果没有linq并使用linq,我无法完成它。期待你的帮助。
答案 0 :(得分:4)
从左到右(没有优先权)应用,我可以得到:
1: ((5+5)-5)/5
2:
3: ((5+5)+5)/5
4: ((5*5)-5)/5
5: ((5-5)*5)+5
6: ((5*5)+5)/5
7: ((5+5)/5)+5
8:
9:
10: ((5+5)+5)-5
使用(编辑:oops - 不需要“没有div”的东西):
var operators = new[] {
new { Name = "+", Func = (Func<decimal,decimal,decimal>)((x,y)=>x+y) },
new { Name = "-", Func = (Func<decimal,decimal,decimal>)((x,y)=>x-y) },
new { Name = "/", Func = (Func<decimal,decimal,decimal>)((x,y)=>x/y) },
new { Name = "*", Func = (Func<decimal,decimal,decimal>)((x,y)=>x*y) }
};
var options = from i in Enumerable.Range(1, 10)
select new {i, op=(
from op1 in operators
let v1 = op1.Func(5,5)
from op2 in operators
let v2 = op2.Func(v1, 5)
from op3 in operators
let v3 = op3.Func(v2,5)
where v3 == i
select "((5" + op1.Name + "5)" + op2.Name + "5)"
+ op3.Name + "5").FirstOrDefault()};
foreach (var opt in options)
{
Console.WriteLine(opt.i + ": " + opt.op);
}
答案 1 :(得分:2)
我是以原始方式做到的,我不确定答案是否正确。但是在电子表格中更容易完成。基本上我修改了linqfying的代码来生成代码。
就是这样:
public static void GetDetails()
{
int ctr = 0;
char[] sym = new char[] { '+', '-', '/', '*' };
string num = "5";
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
for (int k = 0; k < 4; k++)
{
for (int l = 0; l < 4; l++)
{
ctr++;
string str = num + sym[i] + num + sym[j] + num + sym[k] + num;
Console.WriteLine("res = " + str + "; ");
Console.WriteLine("if(res>=1 && res<=10)");
Console.WriteLine("Console.WriteLine(\"" + str + "\");");
}
}
}
}
//Console.WriteLine("Total:" + ctr.ToString());
}
它生成256组操作,我将其输出到文本文件,复制并粘贴到新方法中:
public static void runit()
{
float res = 0;
res = 5+5+5+5;
if (res >= 1 && res <= 10)
Console.WriteLine("5+5+5+5");
res = 5+5+5+5;
if (res >= 1 && res <= 10)
Console.WriteLine("5+5+5+5");
res = 5+5+5+5;
if (res >= 1 && res <= 10)
Console.WriteLine("5+5+5+5");
//......
//......
//......
//......
res = 5*5*5*5;
if (res >= 1 && res <= 10)
Console.WriteLine("5*5*5*5");
}
再次运行它,我得到76个非unqiue操作,适合1到10之间。 这里有19个独特的(仅从左到右操作):
5*5/5/5
5*5/5+5
5/5*5/5
5/5*5+5
5/5/5+5
5/5+5/5
5/5+5-5
5/5-5+5
5+5*5/5
5+5/5*5
5+5/5/5
5+5/5-5
5+5+5-5
5+5-5/5
5+5-5+5
5-5/5/5
5-5/5+5
5-5+5/5
5-5+5+5
我确信有人可以提出更有创意的事情:P
添加:
我在与Marc的答案匹配后意识到,初始循环并没有涵盖所有的排列,我的答案是不对的。但既然我已经花了很长时间,我会让它留下来。 :P
答案 2 :(得分:2)
Marc解决方案中唯一缺失的案例是具有操作优先级的案例,例如:5/5 + 5/5。我将它们添加到一个联合中,这是正确的查询 Marc,如果您使用下面的代码更新您的答案(如果您认为这是正确的),我将删除此答案:
var operators = new[] {
new { Name = "+", Func = (Func<decimal,decimal,decimal>)((x,y)=>x+y) },
new { Name = "-", Func = (Func<decimal,decimal,decimal>)((x,y)=>x-y) },
new { Name = "/", Func = (Func<decimal,decimal,decimal>)((x,y)=>x/y) },
new { Name = "*", Func = (Func<decimal,decimal,decimal>)((x,y)=>x*y) }
};
var options = from i in Enumerable.Range(1, 10)
select new
{
i,
op = (
from op1 in operators
let v1 = op1.Func(5, 5)
from op2 in operators
let v2 = op2.Func(v1, 5)
from op3 in operators
let v3 = op3.Func(v2, 5)
where v3 == i
select "((5" + op1.Name + "5)" + op2.Name + "5)"
+ op3.Name + "5")
.Union(
//calculate 2 operations (the left and the right one),
//then operate them together.
from op1 in operators
let v1 = op1.Func(5, 5)
from op2 in operators
let v2 = op2.Func(5, 5)
from op3 in operators
let v3 = (op3.Name == "/" && v2 == 0) ? null : (int?)op3.Func(v1, v2)
where v3 == i
select "(5" + op1.Name + "5)" + op2.Name + "(5"
+ op3.Name + "5)"
).FirstOrDefault()
};
foreach (var opt in options)
{
Console.WriteLine(opt.i + ": " + opt.op);
}
修改强>:
关于let v3 = (op3.Name == "/" && v2 == 0) ? null : (int?)op3.Func(v1, v2)
的几句话:这是一种非常有效的方法,可以避免除以0(这可能会发生,因为你可以除以(5-5)
)。
我很确定你可以用更好的方式过滤它,但是我把它留给enphasize这个问题可以发生。
答案 3 :(得分:1)
假设您不想使用LINQ,这是一种实现方法。这说它是非常不优化的,我建议使用更短的LINQ实现。 (见:Marc Gravell's post。)
using System;
using System.Collections.Generic;
namespace MathIterator
{
class Program
{
static readonly int[] _inputs = new int[] { 5, 5, 5, 5 };
static readonly char[] _operations = new char[] { '+', '-', '*', '/' };
static Dictionary<int, List<string>> _calculations = new Dictionary<int, List<string>>();
static void Main(string[] args)
{
StartPermutation();
PrintResults();
}
static void StartPermutation()
{
if (_inputs.Length > 0)
Permute(1 /*index*/, _inputs[0], _inputs[0].ToString());
}
static void Permute(int index, int result, string computation)
{
if (index == _inputs.Length)
{
if (!_calculations.ContainsKey(result))
{
_calculations[result] = new List<string>();
}
_calculations[result].Add(computation);
}
else
{
foreach (char operation in _operations)
{
string nextComputation = String.Format("({0} {1} {2})",computation, operation, _inputs[index]);
int nextResult = result;
switch (operation)
{
case '+':
nextResult += _inputs[index];
break;
case '-':
nextResult -= _inputs[index];
break;
case '*':
nextResult *= _inputs[index];
break;
case '/':
nextResult /= _inputs[index];
break;
}
Permute(
index + 1,
nextResult,
nextComputation);
}
}
}
static void PrintResults()
{
for (int i = 1; i <= 10; ++i)
{
if (_calculations.ContainsKey(i))
{
Console.WriteLine("Found {0} entries for key {1}", _calculations[i].Count, i);
foreach (string calculation in _calculations[i])
{
Console.WriteLine(i + " = " + calculation);
}
}
else
{
Console.WriteLine("No entry for key: " + i);
}
}
}
}
}
这是另一种实现。这个遵循优先顺序。同样,我不建议像这样解决它。甚至更多 - 所以现在给予广泛的破解(以区别于减号),但它似乎确实有效。
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace MathIterator
{
class Program
{
static readonly int[] _inputs = new[] { 5, 5, 5, 5 };
//HUGE hack, the '–' is a wide dash NOT a hyphen.
static readonly char[][] _operationLevels = new[] { new[] { '*', '/' }, new[] { '+', '–' } };
static List<string> _calculations = new List<string>();
static Dictionary<int, List<string>> _results = new Dictionary<int, List<string>>();
static void Main(string[] args)
{
StartPermutation();
StartEvaluateCalculations();
PrintResults();
}
static void StartPermutation()
{
if (_inputs.Length > 0)
Permute(1 /*index*/, _inputs[0].ToString());
}
static void Permute(int index, string computation)
{
if (index == _inputs.Length)
{
_calculations.Add(computation);
}
else
{
foreach (char[] operationLevel in _operationLevels)
{
foreach (char operation in operationLevel)
{
string nextComputation = String.Format("{0} {1} {2}", computation, operation, _inputs[index]);
Permute(
index + 1,
nextComputation);
}
}
}
}
static void StartEvaluateCalculations()
{
foreach (string calculation in _calculations)
{
int? result = EvaluateCalculation(calculation);
if (result != null)
{
int intResult = (int) result;
if (!_results.ContainsKey(intResult))
{
_results[intResult] = new List<string>();
}
_results[intResult].Add(calculation);
}
}
}
static int? EvaluateCalculation(string calculation)
{
foreach (char[] operationLevel in _operationLevels)
{
string[] results = calculation.Split(operationLevel, 2);
if (results.Length == 2)
{
int hitIndex = results[0].Length;
Regex firstDigit = new Regex(@"^ -?\d+");
Regex lastDigit = new Regex(@"-?\d+ $");
string firstMatch = lastDigit.Match(results[0]).Value;
int arg1 = int.Parse(firstMatch);
string lastMatch = firstDigit.Match(results[1]).Value;
int arg2 = int.Parse(lastMatch);
int result = 0;
switch (calculation[hitIndex])
{
case '+':
result = arg1 + arg2;
break;
//HUGE hack, the '–' is a wide dash NOT a hyphen.
case '–':
result = arg1 - arg2;
break;
case '*':
result = arg1 * arg2;
break;
case '/':
if ((arg2 != 0) && ((arg1 % arg2) == 0))
{
result = arg1 / arg2;
break;
}
else
{
return null;
}
}
string prePiece = calculation.Remove(hitIndex - 1 - arg1.ToString().Length);
string postPiece = calculation.Substring(hitIndex + 1 + lastMatch.ToLower().Length);
string nextCalculation = prePiece + result + postPiece;
return EvaluateCalculation(nextCalculation);
}
}
return int.Parse(calculation);
}
static void PrintResults()
{
for (int i = 1; i <= 10; ++i)
{
if (_results.ContainsKey(i))
{
Console.WriteLine("Found {0} entries for key {1}", _results[i].Count, i);
foreach (string calculation in _results[i])
{
Console.WriteLine(i + " = " + calculation);
}
}
else
{
Console.WriteLine("No entry for key: " + i);
}
}
}
}
}
答案 4 :(得分:1)
这是一个完全基于LINQ(方法语法)和后期评估的解决方案,它可以处理所有排列(不仅仅是从左到右):
static void Main()
{
var solution = PermuteLength(4)
.Where(p => Decimal.Floor(p.Value) == p.Value)
.Where(p => p.Value <= 10 && p.Value >= 0)
.OrderBy(p => p.Value);
foreach (var p in solution)
{
Console.WriteLine(p.Formula + " = " + p.Value);
}
}
public static Operator[] Operators = new[]
{
new Operator {Format = "({0} + {1})", Function = (x, y) => x + y},
new Operator {Format = "({0} - {1})", Function = (x, y) => x - y},
new Operator {Format = "({1} - {0})", Function = (x, y) => y - x},
new Operator {Format = "({0} * {1})", Function = (x, y) => x * y},
new Operator {Format = "({0} / {1})", Function = (x, y) => y == 0 ? 0 : x / y},
new Operator {Format = "({1} / {0})", Function = (x, y) => x == 0 ? 0 : y / x},
};
public static IEnumerable<Permutation> BasePermutation = new[] { new Permutation {Formula = "5", Value = 5m} };
private static IEnumerable<Permutation> PermuteLength(int length)
{
if (length <= 1)
return BasePermutation;
var result = Enumerable.Empty<Permutation>();
for (int i = 1; i <= length / 2; i++)
result = result.Concat(Permute(PermuteLength(i), PermuteLength(length - i)));
return result;
}
private static IEnumerable<Permutation> Permute(IEnumerable<Permutation> left, IEnumerable<Permutation> right)
{
IEnumerable<IEnumerable<IEnumerable<Permutation>>> product = left.Select(l => right.Select(r => ApplyOperators(l, r)));
var aggregate =
product.Aggregate(Enumerable.Empty<IEnumerable<Permutation>>(), (result, item) => result.Concat(item)).
Aggregate(Enumerable.Empty<Permutation>(), (result, item) => result.Concat(item));
return aggregate;
}
private static IEnumerable<Permutation> ApplyOperators(Permutation left, Permutation right)
{
return Operators.Select(o => new Permutation
{
Formula = string.Format(o.Format, left.Formula, right.Formula),
Value = o.Function(left.Value, right.Value)
});
}
public struct Permutation
{
public string Formula;
public decimal Value;
}
public struct Operator
{
public string Format;
public Func<decimal, decimal, decimal> Function;
}
已知问题: 有些解决方案是重复的 不能很好地处理除零,所以一些错误的答案(我假设任何除以零= 0)
编辑: 结果的一部分:
((5/5)/(5/5))= 1
((5/5)+(5/5))= 2
((5 +(5 + 5))/ 5)= 3
(5 - ((5 + 5)/ 5))= 3
<(>((5 * 5) - 5)/ 5)= 4(5 +(5 *(5 - 5)))= 5
(5 - (5 *(5 - 5)))= 5
(5 +((5-5)/ 5))= 5
(5 - ((5 - 5)/ 5))= 5