2009-10-18 13 views
1

當attemptiing解決以下分配:LINQ的Arithemetic算組合

使用算術運算符(+, - ,*,/)重新排列4個擊掌爲等於數目爲1〜10

實施例:5/5 + 5-5 = 1,10/10 + 10/10 = 2

我想在C#中不使用LINQ(我不知道如何進一步進行)

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.Expecting您有所幫助。

+0

因此,基本上,你是通過所有可能的排列迭代和挑出那些給出正確答案的那些代碼並構建代表算術的字符串?小心分享您如何使用LINQ做到這一點? – 2009-10-18 09:38:10

+0

只是出於好奇:有沒有人設法生成3..8?我使用PowerShell進行的小測試只產生了1,2,9和10的結果。 – Joey 2009-10-18 09:50:45

+0

是否允許使用括號? (5 * 5 + 5)/ 5 == 6,(5 + 5 + 5)/ 5 == 3 – andyp 2009-10-18 10:08:41

回答

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 

隨着(編輯:哎呀 - 「無格」 的東西是多餘的):

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); 
    } 
+0

@Marc給出「8」的解決方案:您的概念是要走的路,儘管我很安靜某些操作被省略:「((5 + 5)/ 5)* 5 = 10」,「((5/5)+5)-5 = 1」等等。 – 2009-10-18 10:24:28

+0

這不包括:9 =(5 + 5) - (5/5);和2 =(5/5)+(5/5)。 – 2009-10-18 10:24:39

+0

@Alex:(5 + 5) - (5/5)正在使用優先規則。馬克已經指定他的算法是從左到右,沒有優先權。 – 2009-10-18 10:30:32

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適合在這裏1和10 19之間而獨特的那些非unqiue操作(左到右只操作):

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

補充:

我與馬克的答案匹配後實現的,最初的循環沒有覆蓋所有的排列,我的答案艾因不會是對的。但既然我已經花了很長時間,我會讓它留下。 :P

+0

我很感激你的努力。感謝很多朋友 – user190560 2009-10-18 10:20:33

+0

@linqfying:沒問題,帶上Marc的一個,稍微調整一下,你應該明白了。但是如果你想完全避免使用LINQ,你必須稍微調整一下。 – 2009-10-18 10:26:17

+0

是沒有Linq我工作了。一旦完成,我會發布它。現在我正在處理另一個有趣的問題。謝謝你的回覆 :) – user190560 2009-10-18 10:29:35

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); 
     } 
     } 
    } 
    } 
} 
+0

@Rob:我跑了你的代碼,21個獨特的結果。看起來很有前途!儘管仍然缺乏優先規則。無論如何,幹得好。 – 2009-10-18 10:52:06

+0

哇,那肯定會擊敗我在這裏的大小:-) ... '$ ops =「+」,「 - 」,「*」,「/」; 1..10 |%{$ res = $ _ ; $ OPS |%{$ 01 = $ _; $ OPS |%{$ O2 = $ _; $ OPS |%{$ O3 = $ _; 「((5 $ o1 5)$ o2 5)$ o3 5」}}} |?{(iex $ _)-eq $ res} |%{「$ _ = $ res」}}' – Joey 2009-10-18 11:32:20

2

Marc的解決方案中唯一缺失的情況是具有如下操作優先級的情況:5/5 + 5/5。我將它們添加到工會中,這裏是正確的查詢。
馬克,如果您更新與下面的代碼你的回答(如果你認爲這是正確的),我會刪除這個答案:

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這個問題可能發生。

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)/(10/10))= 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

+0

感謝您的努力 – user190560 2009-10-18 15:00:23