问题
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.
回答1:
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).
回答2:
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.
来源:https://stackoverflow.com/questions/1582054/handling-temporary-calculation-in-linq