C# 有人能滥用LINQ解决这个金钱难题吗?

C# 有人能滥用LINQ解决这个金钱难题吗?,c#,linq,math,C#,Linq,Math,为了好玩,我想看到有人使用和滥用LINQ来解决这个资金问题。 我真的不知道你会怎么做-我想填充一些集合,然后从中选择 如果给出硬币总数,并给出所有硬币加在一起的总金额: 显示所有可能的硬币组合。硬币是四分之一(.25)、一角硬币(.10)、五分镍币(.05)和便士(.01) 包括选项,以便一种硬币可以为零,或者每种硬币必须至少有一个 示例问题:如果我有19枚硬币,这些硬币加起来是1.56美元,那么每种类型的硬币必须至少有1枚 答案是: 1个25美分,9个一角硬币,8个五分镍币,1便士 2个25美

为了好玩,我想看到有人使用和滥用LINQ来解决这个资金问题。 我真的不知道你会怎么做-我想填充一些集合,然后从中选择

如果给出硬币总数,并给出所有硬币加在一起的总金额: 显示所有可能的硬币组合。硬币是四分之一(.25)、一角硬币(.10)、五分镍币(.05)和便士(.01)

包括选项,以便一种硬币可以为零,或者每种硬币必须至少有一个

示例问题:如果我有19枚硬币,这些硬币加起来是1.56美元,那么每种类型的硬币必须至少有1枚

答案是:

1个25美分,9个一角硬币,8个五分镍币,1便士

2个25美分,5个10美分,11个5美分,1便士

2个25美分,9个一角硬币,2个五分镍币,6便士

3个25美分,1个10美分,14个5美分,1便士

3个25美分,5个10美分,5个5美分,6个便士

4个25美分,1个10美分,8个5美分,6个便士

5个25美分,1个10美分,2个5美分,11便士

如果我们允许一个硬币为零,我们可以得到一个额外的 0个25美分,13个10美分,5个5美分,1便士

下面是一些使用蛮力方法解决问题的示例C#代码。 不要费心改进示例,让我们看看使用Linq的解决方案。 //如果可能,尽量不要使用任何常规的c#循环代码

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));
    }
private void solvecoin问题(整数totalNumberOfCoins,双倍totalAmount,整数minimumNumberOfEachCoin)
{
int foundCount=0;
长次数=0;
Console.WriteLine(String.Format(“解决硬币问题:TotalNumberOfCoins={0}TotalAmount={1}MinimumNumberOfEachCoin{2}”,TotalNumberOfCoins,TotalAmount,MinimumNumberOfEachCoin));
对于(int totalQuarters=每个硬币的最小数量;totalQuarters
未经测试,但:

        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
...

使用LINQ来解决这个问题很难被滥用!:-)顺便说一句,代码找到5个(而不是7个)答案的原因是舍入错误。切换到十进制(0.05米等),您可能会感到惊讶!关于“浮点BS”-这不是BS;这就是浮点运算的原理。经验法则:如果你在同一句话中看到“float”(或“double”)和“money”,那可能是错的。这是一个该死的快速答案。您返回的集合中确实有所有答案,但它似乎也返回了不正确的结果。LINQ查询发现了35个结果,其中只有5个(和我的一样)符合19个计数的标准,总共$1.56.+1暴力,如果它不起作用,你没有使用足够的。35?我从我发布的查询中得到了7个,它们看起来都很好。另外两个是“1个25美分、9个一角硬币、8个五分镍币和1个一分镍币”,还有“5个25美分、1个一角硬币、2个五分镍币和11个一分镍币”。你的代码运行得很好。这是发现7。事实上,它指出了暴力方法中的一个问题。蛮力方法中的两项被省略,因为它检查总计的行正在执行一些浮点运算,并且计算结果为1.59999,而不是1.59。
        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 };