C# C无递归计数项
我需要解决一个测试问题,当X苹果作为起始数量,Y苹果每次吃,每次吃苹果加1苹果时,我需要计算总共可以吃多少个苹果 我当前的解决方案使用递归函数,因此,如果Y小于X,或者给定的X太大,则会导致无限循环C# C无递归计数项,c#,recursion,C#,Recursion,我需要解决一个测试问题,当X苹果作为起始数量,Y苹果每次吃,每次吃苹果加1苹果时,我需要计算总共可以吃多少个苹果 我当前的解决方案使用递归函数,因此,如果Y小于X,或者给定的X太大,则会导致无限循环 public class Apples { // Counts iterations. If we eat less than we add new every, it'll loop infinetely! private static int _recursions;
public class Apples
{
// Counts iterations. If we eat less than we add new every, it'll loop infinetely!
private static int _recursions;
private static int _applesRemaining;
private static int _applesEaten;
public static int CountApples(int startingAmount, int newEvery)
{
if (newEvery > startingAmount) newEvery = startingAmount;
Console.WriteLine("startingAmount: " + startingAmount + ", newEvery: " + newEvery);
_applesRemaining = startingAmount;
/* Eat 'newEvery' amount */
_applesRemaining -= newEvery;
_applesEaten += newEvery;
Console.WriteLine("Eat: " + newEvery + ", remaining: " + _applesRemaining);
/* Get one additional candy */
_applesRemaining += 1;
Console.WriteLine("Added 1.");
if (_applesRemaining > 1 && _recursions++ < 1000)
{
CountApples(_applesRemaining, newEvery);
}
else
{
if (_recursions > 1000) Console.WriteLine("ABORTED!");
/* Eat the one we've just added last. */
_applesEaten += 1;
}
return _applesEaten;
}
public static void Main(string[] args)
{
Console.WriteLine(CountApples(10, 2) + "\n");
}
}
我手头没有C工具链,所以下面的例子是在Python社区中编辑制作的例子C!魔法
正如评论中所说,这是一个迭代问题,而不是递归问题
var apples = 100;
var eaten = 0;
var eatPerRound = 5;
var gainPerRound = 1;
while(apples > 0)
{
apples -= eatPerRound;
eaten += eatPerRound;
apples += gainPerRound;
Console.WriteLine($"Round {round}: {eaten} apples eaten, {apples} left");
}
以下是我如何理解您的问题的一个运行示例:
using System.IO;
using System;
class Program
{
static void Main()
{
Console.WriteLine(GetNumberOfApplesEaten(100,5));
}
public static int GetNumberOfApplesEaten(int X, int Y)
{
int result = 0;
// while we can eat 'Y' apples
while(X >= Y)
{
// we eat & count those apples
result += Y;
X -= Y;
// we add an extra apple
X++;
}
// we eat what's left
result += X;
return result;
}
}
编辑
我将X>Y更改为X>=Y,使其与您的规格匹配
检查javascript等效项:
函数getNumberOfAppleSatenx,Y{
var结果=0;
//而我们可以吃“Y”苹果
whileX>=Y{
//我们吃并数那些苹果
结果+=Y;
X-=Y;
//我们多加了一个苹果
X++;
}
//我们吃剩下的
结果+=X;
返回结果;
}
logGetNumberOfAppleSaten3,2这个问题的递归似乎有些过分,所以我建议使用另一种数学方法 让我们从一个事实开始,我们总是吃至少X个苹果。真正的问题是,在所有的东西都被吃掉后,总共会添加多少苹果 假设ni是我吃了之后剩下的苹果数。然后:
n0 = X
n1 = X - Y + 1
n2 = X - 2Y + 2
...
ni = X - i(Y - 1)
求解ni=0将得到i——吃所有食物所需的进食次数:
ni = 0 = X - i(Y - 1) => i = X / (Y - 1)
现在我们知道我们要吃多少次了,所以要吃的苹果总数是原来的X加上Y苹果被吃的次数,因为每次我们多吃一个苹果时:
tot = X + roundDown(i) = X * roundDown(X / (Y - 1))
我们对结果进行四舍五入,因为设置ni=0会捕获部分数量的食物,然后会生成部分苹果
例如:
X = 7, Y = 3 => tot = 7 + roundDown(7 / (3 - 1)) = 7 + roundDown(3.5) = 10
starting with 7:
0 eaten, 7 remain
3 eaten, 1 gained, 5 remain
3 eaten, 1 gained, 3 remain
3 eaten, 1 gained, 1 remains
1 eaten, nothing gained, nothing remains
--
10 eaten in total
如果只想计算吃的苹果数而不跟踪进度,则不需要递归和循环。您只需使用线性O1代码计算结果:
int result = apples + apples / (eatenPerRound - 1);
if ((apples % (eatenPerRound - 1)) <= 1) {
result--;
}
Console.WriteLine($"Total number of {result} apples eaten.");
不确定你的答案是否有限制,但通过一些数学,你可以想出以下方法:
public int CheatEatenApples(int startingApples, int newEvery)
{
var firstGuess = (double)startingApples*newEvery/(newEvery-1);
if (firstGuess%1==0) // Checks if firstGuess is a whole number
{
return (int)firstGuess-1;
}
else
{
return (int)firstGuess;
}
}
第一个猜测是根据我们不断得到新苹果这一事实计算出来的,因此每吃一个苹果,其中一个是免费的!当然,如果第一个猜测是一个整数,那么这实际上就失败了。这就需要免费的苹果才能让我们吃。让我们来看一个例子
如果我们有3个苹果,我们每两个就有一个新苹果,那么我们的第一个猜测是6个苹果。然而,这是三个免费的苹果,我们只有在吃了6个苹果后才能得到第三个,这依赖于三个免费的苹果!所以在这种情况下,我们需要去掉一个。剩下的时间里,我们可以四舍五入删除表示我们离免费苹果有多近的分数部分
这正好说明你在学校学的数学可以在现实世界中使用。以上是一些简单的计算,可能比大多数迭代/递归计算方法要快
附加说明:在一条现已删除的评论中指出,在firstGuess计算中使用整数算法可以更好地实现这一点。这将节省返回值转换回int的时间。它之所以像现在这样写,部分原因是因为我在写它的时候是这样想的,部分原因是当我在迭代寻找正确答案的时候,我在调试时看到了小数部分,以确认只有当firstGuess是完整的,我才需要做一些特别的事情
如果您改为整数数学,那么If条件将需要更改,因为它不再按原样工作,您将得到Sefe的答案
最后说明:
如果您确实希望使用迭代技术,则以下方法与规范相匹配:
public int CalculateEatenApples(int startingApples, int newEvery)
{
int applesEaten = 0;
int apples = startingApples;
while (apples>0)
{
applesEaten++;
apples--;
if (applesEaten%newEvery==0)
{
apples++;
}
}
return applesEaten;
}
这很简单。当你有苹果时,它会增加你吃过的苹果数量,减少你剩下的苹果数量。然后,如果你吃的是newEvery的倍数,那么它会额外增加一个。Y苹果每次都在吃。你能解释一下吗?知道苹果正在吃真有趣。你是说吃了吗?这听起来像是简化成了一个线性方程,但不管怎样都不需要使用递归。@david,那是个打字错误。更正。当一开始有3个苹果,每次吃5个苹果时会发生什么?看到你的更新后,我想澄清一下:Y苹果不是每次都吃。苹果一次吃一个,每次你达到Y的倍数,你就多加一个苹果。这在其规范中是绝对明确的。是一个我经常使用的在线C编译器,但它的功能并不完善。给定X是3,Y是2,结果应该是5,eat 2,add 1,eat 2,add 1,eat 1,但这段代码返回6。@Bad
只要你有3个,你就去吃,现在你有4个,你吃2个,剩下2个,你去吃,剩下3个,你吃2个,剩下1个,你去吃2个,剩下0个。总数是6。@Baddingtoncat添加额外苹果的顺序很重要。@MineR好的,但这不是我之前评论中的测试题给出的示例。我对此相当怀疑approach@Rafalon怀疑结果是否正确回答了问题?问题是你最多能吃多少苹果?。这个问题已经回答了。请注意,这并没有给出他要求的3次首发,每轮2次进食的结果。。。应该给5分,但给6分。如果你能改变它使其发挥作用,它应该得到最快的投票@Sefe MineR的评论正是我对这一方法持怀疑态度的原因。我不知道您可以使用双%1进行检查。很好。@MineR:我不是100%确定最好的检查方法,所以在@PaulF:我想你可能是对的。上面的方法是结合我脑海中的想法编写的,因为在迭代和测试时,我看到的是小数部分。我现在就不做了。部分原因是,更改为整数算术将意味着更改if条件,而我必须将其更改为的内容将使其与Sefe的答案基本相同至少现在有两个稍有不同的版本可供选择:我后来确实看到了if语句中的细微差别&删除了我的评论。@PaulF:我认为这绝对是一个很好的评论,值得保留,因为现在你已经删除了它,我将在我的答案中添加一条注释这对我有用,非常感谢!我在Y为1的情况下添加了一个检查,这将导致一个无限循环。@Baddingtoncat是的,您肯定应该检查X>0和Y>1
public int CheatEatenApples(int startingApples, int newEvery)
{
var firstGuess = (double)startingApples*newEvery/(newEvery-1);
if (firstGuess%1==0) // Checks if firstGuess is a whole number
{
return (int)firstGuess-1;
}
else
{
return (int)firstGuess;
}
}
public int CalculateEatenApples(int startingApples, int newEvery)
{
int applesEaten = 0;
int apples = startingApples;
while (apples>0)
{
applesEaten++;
apples--;
if (applesEaten%newEvery==0)
{
apples++;
}
}
return applesEaten;
}