Может ли кто-то злоупотреблять LINQ и решать эту проблему?
Для удовольствия, я хотел бы, чтобы кто-то использовал и злоупотреблял LINQ для решения этой проблемы с деньгами.
Я действительно понятия не имею, как вы это сделаете - я предполагаю, что вы заполняете какой-то набор, а затем выбираете его.
Если дано общее количество монет и общее количество всех монет добавлено вместе:
Покажите все возможные комбинации монет. Монеты - кварталы (0,25), Dimes (.10) Никели (0,05) и Пенни (0,01)
Включите эту опцию, чтобы было нулевое число монеты или должно быть не менее 1 из них.
Проблема с образцом: если у меня есть 19 монет, и монеты составляют до $1,56, и там должно быть не менее 1 каждого типа монет.
Ответ будет следующим:
1 квартал, 9 копейки, 8 никелей, 1 пенни
2 квартала, 5 Dimes, 11 Nickels, 1 Pennies
2 квартала, 9 монет, 2 никеля, 6 пенни
3 квартала, 1 день, 14 никелей, 1 пенни
3 квартала, 5 Dimes, 5 Nickels, 6 Pennyies
4 квартала, 1 день, 8 никелей, 6 пенни
5 кварталов, 1 Dimes, 2 Nickels, 11 Pennyies
И если мы допустили нуль для coint, мы позволили получить дополнительный
0 кварталов, 13 Dimes, 5 Nickels, 1 Pennies
Вот пример кода С#, использующего метод грубой силы для решения проблемы.
Не беспокойтесь о том, чтобы улучшить выборку, просто взгляните на решение, используя Linq.
// По возможности старайтесь не использовать любой циклический код regualar С#.
private void SolveCoinProblem(int totalNumberOfCoins, double totalAmount, int minimumNumberOfEachCoin)
{
int foundCount = 0;
long numberOfTries = 0;
Console.WriteLine(String.Format("Solving Coin Problem:TotalNumberOfCoins={0}TotalAmount={1}MinimumNumberOfEachCoin{2}", totalNumberOfCoins, totalAmount, minimumNumberOfEachCoin));
for (int totalQuarters = minimumNumberOfEachCoin; totalQuarters < totalNumberOfCoins; totalQuarters++)
{
for (int totalDimes = minimumNumberOfEachCoin; totalDimes < totalNumberOfCoins; totalDimes++)
{
for (int totalNickels = minimumNumberOfEachCoin; totalNickels < totalNumberOfCoins; totalNickels++)
{
for (int totalPennies = minimumNumberOfEachCoin; totalPennies < totalNumberOfCoins; totalPennies++)
{
numberOfTries++;
if (totalQuarters + totalDimes + totalNickels + totalPennies == totalNumberOfCoins)
{
if (Math.Round((totalQuarters * .25) + (totalDimes * .10) + (totalNickels * .05) + (totalPennies * .01),2) == totalAmount)
{
Console.WriteLine(String.Format("{0} Quarters, {1} Dimes, {2} Nickels, {3} Pennies", totalQuarters, totalDimes, totalNickels, totalPennies));
foundCount++;
}
}
}
}
}
}
Console.WriteLine(String.Format("{0} Combinations Found. We tried {1} combinations.", foundCount, numberOfTries));
}
Ответы
Ответ 1
Отключено, но:
int minQuarters = 1, minDimes = 1,
minNickels = 1, minPennies = 1,
maxQuarters = 19, maxDimes = 19,
maxNickels = 19, maxPennies = 19,
coinCount = 19, total = 156;
var qry = from q in Enumerable.Range(minQuarters, maxQuarters)
from d in Enumerable.Range(minDimes, maxDimes)
from n in Enumerable.Range(minNickels, maxNickels)
from p in Enumerable.Range(minPennies, maxPennies)
where q + d + n + p == coinCount
where q * 25 + d * 10 + n * 5 + p == total
select new {q,d,n,p};
foreach (var row in qry)
{
Console.WriteLine("{0} quarter(s), {1} dime(s), {2} nickel(s) and {3} pennies",
row.q, row.d, row.n, row.p);
}
Собственно, для розничных целей - возможно, лучший вопрос: "Каковы наименьшие монеты, которые я могу выдать"? Заменить на:
...
from p in Enumerable.Range(minPennies, maxPennies)
where q + d + n + p <= coinCount
where q * 25 + d * 10 + n * 5 + p == total
orderby q + d + n + p
...
и используйте либо First()
, либо Take(...)
;-p
Возможно, вы также можете уменьшить количество проверенных случаев, вычитая (например) q
в тесте maxDimes
(и так далее...) - что-то вроде (упрощенного):
int minCount = 1,
coinCount = 19, total = 156;
var qry = from q in Enumerable.Range(minCount, coinCount - (3 * minCount))
where q * 25 <= total
from d in Enumerable.Range(minCount, coinCount - (q + (2 * minCount)))
where q * 25 + d * 10 <= total
from n in Enumerable.Range(minCount, coinCount - (q + d + minCount))
where q * 25 + d * 10 + n * 5 <= total
from p in Enumerable.Range(minCount, coinCount - (q + d + n))
where q + d + n + p == coinCount
where q * 25 + d * 10 + n * 5 + p == total
select new { q, d, n, p };