C# 货币排列
只是为了让大家知道,这是我第一次寻求有关堆栈溢出的帮助。我通常会搜索网站并找到满意的答案,或者在 MSDN 或其他网站上进一步挖掘。但这一次我被严重卡住了。
我收到招聘人员发来的一个编程问题,我必须完成该问题才能提交给客户,看看他们是否愿意邀请我。挑战如下:对于任何给定的值,确定该值可以用 100 美元面额表示的方式数, $50, $20, $10, $5, $1, .25, .10, .05, .01
我从未学过三角学或微积分,也从未在我的学习中遇到过如此复杂的数学问题 。 14 年编程经验。他们希望用 C# 找到答案,因为它是 Microsoft .NET 商店。
招聘人员给了我他提交的另一位候选人的代码。这个人一定是一位出色的数学家,因为她真正编写了整个算法以达到预期的结果。我把它插入到网页中,它确实满足了要求。问题是我什至无法弄清楚并以允许我编写自己的实现的方式理解它。
我真的非常想要这份工作,因为它是在纽约的一家初创公司,听起来很棒。我能够回答第二个问题,因为它是一个架构/设计问题,但这个问题让我感到困惑。
顺便说一句,我在维基百科上查找了硬币找零问题和背包型问题,这远远超出了我的数学技能。我什至无法阅读答案,因为我不懂微积分。所以我在这方面需要一些认真的帮助。
这是她的代码,顺便说一句,它确实有效:
protected void Page_Load(object sender, EventArgs e)
{
var numberToSplit = new List<int>() {123};
foreach (int a in numberToSplit)
{
Response.Write(a + " can be split in ");
foreach (List<double> splits in GetDenominations(a).Values)
{
foreach (double b in splits)
{
Response.Write(b + ",");
}
//next split
Response.Write("<br/>");
}
Response.Write("<br/>");
}
}
public Dictionary<double, List<double>> GetDenominations(int value)
{
var denominations = new List<double> {100, 50, 20,10,5,1,0.25,0.10,0.05,0.01};
var AllPossibleSplits = new Dictionary<double, List<double>>();
var hightestdenomination = 100.0;
while (hightestdenomination != 0)
{
var remainingDenominations =
denominations.Where(a => (a <= value && !AllPossibleSplits.Keys.Contains(a)));
if (remainingDenominations.Count() > 0)
hightestdenomination = remainingDenominations.Max();
else
hightestdenomination = 0;
var splits = new List<double>();
if (hightestdenomination != 0)
{
int valueToSplit = value;
while (valueToSplit > 0)
{
foreach (double denomination in remainingDenominations.Where(a => a <= valueToSplit))
{
int absoluteValue = (int) (valueToSplit/denomination);
valueToSplit = valueToSplit - (int) (absoluteValue*denomination);
int absoluteValueSplit = 0;
while (absoluteValueSplit < absoluteValue)
{
splits.Add(denomination);
absoluteValueSplit++;
}
}
}
}
AllPossibleSplits[hightestdenomination] = splits;
}
return AllPossibleSplits;
}
Just to let everyone know, this is the first time I've ever asked for help on stack overflow. I usually search the site and find a satisfactory answer or dig further on MSDN or other sites. But this time I am seriously stuck.
I received a programming problem from a recruiter that I must complete to submit to the client to see if they want to call me in. Here is the challenge: For any given value determine the number of ways said value can be represented by denominations $100, $50, $20, $10, $5, $1, .25, .10, .05, .01
I have never taken trigonometry or calculus nor have I ever encountered something this mathematically complex in my 14 years of programming. They want the answer in C# as it is a Microsoft .NET shop.
The recruiter gave me another candidate's code which he submitted. This person must be a brilliant mathemetician as she truly wrote the entire algorithim to achieve the desired result. I plugged it into a webpage and it does in fact satisfy the requirements. The problem is that I can't even figure it out and understand it in a way that would allow me to write my own implementation.
I really badly want this job as it is at a startup in NYC that sounds great. I was able to answer the second problem as it was an architecture/design question but this one is confounding me.
BTW I looked up the coin change problem and knapsack type problems on Wikipedia and it is well beyond my mathematical skills. I can't even read the answers as I don't understand calculus. So I need some serious help on this one.
Here is her code which does work BTW:
protected void Page_Load(object sender, EventArgs e)
{
var numberToSplit = new List<int>() {123};
foreach (int a in numberToSplit)
{
Response.Write(a + " can be split in ");
foreach (List<double> splits in GetDenominations(a).Values)
{
foreach (double b in splits)
{
Response.Write(b + ",");
}
//next split
Response.Write("<br/>");
}
Response.Write("<br/>");
}
}
public Dictionary<double, List<double>> GetDenominations(int value)
{
var denominations = new List<double> {100, 50, 20,10,5,1,0.25,0.10,0.05,0.01};
var AllPossibleSplits = new Dictionary<double, List<double>>();
var hightestdenomination = 100.0;
while (hightestdenomination != 0)
{
var remainingDenominations =
denominations.Where(a => (a <= value && !AllPossibleSplits.Keys.Contains(a)));
if (remainingDenominations.Count() > 0)
hightestdenomination = remainingDenominations.Max();
else
hightestdenomination = 0;
var splits = new List<double>();
if (hightestdenomination != 0)
{
int valueToSplit = value;
while (valueToSplit > 0)
{
foreach (double denomination in remainingDenominations.Where(a => a <= valueToSplit))
{
int absoluteValue = (int) (valueToSplit/denomination);
valueToSplit = valueToSplit - (int) (absoluteValue*denomination);
int absoluteValueSplit = 0;
while (absoluteValueSplit < absoluteValue)
{
splits.Add(denomination);
absoluteValueSplit++;
}
}
}
}
AllPossibleSplits[hightestdenomination] = splits;
}
return AllPossibleSplits;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您可以将其视为树遍历问题:
在这里,您将遍历树并检查以下内容。
下面是一个示例:您想要获得 25 美元、5 美元、10 美元和 20 美元钞票的所有可能排列。蓝色表示成本
25
,红色表示成本> 25
绿色表示cost = 25
图像免责声明:也许其中有一些错误,但你明白了
另外,如果你这样做,它会给出像 5,5,5,10 <> 这样的排列。 10,5,5,10 因此,请保留您已有的解决方案的列表,这样您就不会得到这些倍数。此外,这棵树有一个有点大(有争议的)分支因子(10),所以如果你得到很大的数字,就有很多可能的选择。不要先创建整棵树然后遍历它。它可以加起来(我无法想象有多少种可能性可以赚到 1,000,000 美元)。
You can look at it as a tree traversal problem:
Here you progress trough the tree and check for the following things.
Here is an example: You want to get all possible permutations of $25, with 5, 10 and 20 dollar bills. Blue means that the
cost < 25
, red meanscost > 25
and green meanscost = 25
IMAGE DISCLAIMER: Perhaps some errors in it, but well you get the idea
Also, if you do it like this, it will give permutations like 5,5,5,10 <> 10,5,5,10 so keep a list of the solutions you already have, so you don't get these multiples. Also this tree has a somewhat large (disputable) branching factor (10), so if you're getting big numbers there are a LOT of possible options. Don't go creating the whole tree first and traversing through it. It can add up (I can't imagine how many possibilities there are to make like $1.000.000).
出色地,
发布的算法仅让您了解所有可能的排列,尝试使用值 1 它给出的答案如下:
。
。
。
但这只是整个答案的一瞥,缺少答案,例如
0,25 , 0,25 , 0,1 , 0,1 , 0,1 , 0,1 , 0,1
仅举一例。
实现自己的算法是一个好方法。
我是一名计算科学的实习生,我可以在我的脑海中想到一种算法,虽然不那么复杂,但很有效。
在我之前发帖的人给出了一个很好的提示:
从最大可能的分裂到最小的可能分裂,计算出现的最大数量,然后以较小的数量继续,直到最终剩余 0 次。
要获得所有可能的解决方案,需要做更多的工作,但是您提供的解决方案给出了不同最大数量的解决方案。
Well,
The posted algorithm only gives you a glance at all possible permutations, tried it with value 1 it gives answers like:
.
.
.
But thats only a glance at the whole answer there is missing answers like
0,25 , 0,25 , 0,1 , 0,1 , 0,1 , 0,1 , 0,1
to just mention one.
Implementing your own algorithm is a good way to do.
I am a trainee at computational sciences and i can think of a algorithm for that at the top of my head, not as sophisticated, but working.
The guy that posted right before me gave a nice hint:
go from largest to smallest possible split, calculate the maximum amount of occurences and go on with smaller amounts till you end up with 0 rest over.
To get all possible solutions it is a bit more work, but the solution that you provided gives a solution for different maximum amount.
您可能想看看贪婪算法。
You might want to take a look at a Greedy Algorithm.
虽然我觉得这是一次工作面试,你应该能够编写这段代码,但我更愿意推动你朝着正确的方向前进。
这是一个需要简单数学的经典编程任务,我将在下面进行解释。
想象一下每个教派都有 1 个,在现实生活中你会如何区分它们。
首先,您将每种面值堆成一堆,在本例中对应于一个变量,即 var HundredDollarNotes、var五十美元Notes,或者具有该效果属性的对象。
而您的金额不等于零。
减去 100 美元的金额,并将 1 加入到 HundredDollarNotes 变量中,重复此操作,直到无法减去 100 美元。
继续减少金额,直到没有剩余金额为止。
简而言之,就是贪婪算法。
Although I feel as it is an interview for a job you should be able to write this code I am more willing to give you a push in the right direction.
This is a classic programming task requiring simple math and I will explain below.
Think about having 1 of each of the denominations, how would you separate them in real life.
Well first you would make a pile of each denomination which in this case corresponds to a variable i.e var hundredDollarNotes, var fiftyDollarNotes, or alternatively an object with properties to that effect.
while your amount is not equal to zero.
take 100 dollars off amount and add one to hundredDollarNotes variable, repeat until cannot take 100 dollars off.
Continue with lower amounts till you have no amount left.
And there you have it a Greedy Algorithm in a nut shell.
不要让问题变得更困难。
假设您有 51 个硬币。使用您拥有的最大账单 (50) 51-50=1
然后使用你拥有的最大的硬币 (1) 1-1=1
就这样。
该代码只是遍历整个价值列表并使用可能的最大钞票/面额,并对剩下的任何内容执行相同的操作,直到什么都没有剩下。
Dont make the problem harder then it is.
Lets say you have 51 coins. Use the biggest bill you have (50) 51-50=1
Then use the biggest coin you have (1) 1-1=1
And there you are.
The code simply walks through the entire list of value and uses the biggest bill/denomination possible and does the same for whatever is left till nothing is left.