开发者

Handling temporary calculation in Linq

When solving an interview question

Question A six digit number need to be found in such a开发者_开发百科 manner when it is multiplied by an integer between 2 and 9 gives the original six digit number when its digits are reversed.

Example:

Suppose I multiply 219978 * 4 i get 879912 ,when reverse 879912 I will get 219978 back.

I solved it using

for (long l = 100000; l < 999999; l++)
{
 var num = l.ToString();

for (int i = 3; i < 9; i++)
{
  var mul = l * i;
  string str = mul.ToString();
  char[] splitDigits = str.ToCharArray();
  string reversedDigit =
  new  string(splitDigits.Reverse().ToArray());

  if (reversedDigit.CompareTo(num) == 0)
    {
      Console.WriteLine("{0} * {1}= {2},
       when multiplied {3} ", num, i, mul,reversedDigit);

    }

 }
}

The original task was to solve it using linq. I have bit confusion in handling temp calculations for example

when i use

   var = from l in Enumerable.Range(100000,999999)
         from i in Enumerable.Range(3,9)

What is the way to handle temporary calculations like var num = l.ToString(),etc in linq.It confused me a lot to finish it in Linq.Help is appreciated.


You want let...

    // NOTE: buggy; see below
    var qry =  from l in Enumerable.Range(100000, 999999)
               from i in Enumerable.Range(3, 9)
               let s = l.ToString()
               let t = (l * i).ToString()
               where s.Reverse().SequenceEqual(t)
               select new { l, i };

    var a = qry.First();
    Console.WriteLine("an answer...");
    Console.WriteLine("{0} x {1} = {2}", a.l, a.i, a.l * a.i);

    Console.WriteLine("all answers...");
    foreach (var row in qry)
    {
        Console.WriteLine("{0} x {1} = {2}", row.l, row.i, row.l * row.i);
    }

with first answer (note the inclusion of 9 is taken from your original version of the code, but it may be desirable to use Range(3,8) instead):

109989 x 9 = 989901

Optimised version (and correct range):

    var qry =  from l in Enumerable.Range(100000, 999999 - 100000)
               let s = l.ToString()
               let sReversed = new string(s.Reverse().ToArray())
               let wanted = int.Parse(sReversed)
               from i in Enumerable.Range(3, 8 - 3) 
               where l * i == wanted
               select new { l, i };

This reduces the number of strings created, uses integer equality, and correctly uses the range (the second parameter to Range is the count, not the end).


Here's another solution that matches the problem statement with a few helper methods for clarity (which could be moved into the original linq query):

    private static IEnumerable<int> SixDigitNumbers = Enumerable.Range(100000, (999999 - 100000));
    private static IEnumerable<int> Multipliers = Enumerable.Range(2, 8);

    static void Main(string[] args)
    {

        var Solutions = from OriginalNumber in SixDigitNumbers
                              from Multiplier in Multipliers
                              let MultipliedNumber = (OriginalNumber * Multiplier)
                              where MultipliedNumber < 999999 && ResultIsNumericPalindrome(OriginalNumber, Multiplier)
                              select new { MultipliedNumber, OriginalNumber, Multiplier };


        var AllSolutions = Solutions.ToList();

    }

    private static string Reverse(string Source)
    {
        return new String(Source.Reverse().ToArray());
    }

    private static bool ResultIsNumericPalindrome(int Original, int Multiplier)
    {
        return (Original.ToString() == Reverse((Original * Multiplier).ToString()));
    }

Here are ALL of the solutions:

{ MultipliedNumber = 989901, OriginalNumber = 109989, Multiplier = 9 }
{ MultipliedNumber = 879912, OriginalNumber = 219978, Multiplier = 4 }

Be careful with Enumerable.Range - I see one person responding to this question made the mistake of excluding two numbers requested in the problem statement.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜