确定行-1测试用例中是否有足够的票据更改
对于CodeWars上的此Kata Level 6问题,中有9个测试通过。奇怪的事情:CodeWars不会告诉我哪个测试用例失败。确定行-1测试用例中是否有足够的票据更改
这是我的代码。也许有人在这里可以帮忙?非常感谢。
function tickets(peopleInLine) {
var totalChange = 0;
for (var i = 0; i < peopleInLine.length; i++) {
if (peopleInLine[i] === 25) totalChange += 25;
if (peopleInLine[i] > 25) {
var change = peopleInLine[i] - 25;
if (totalChange < change) return "NO";
if (totalChange >= change) totalChange -= change;
}
}
return "YES";
}
这里是问题:
新的 “复仇者” 电影刚刚被释放!电影票房有很多人站在一条巨大的线上。他们每个人都有一张100美元,50美元或25美元的账单。 “复仇者”票价25美元。
Vasya目前是一名职员。他想把票卖给这条线上的每一个人。
Can Vasya可以向每个人出售一张门票,如果他最初没有钱,并且按照人们遵循的顺序严格销售门票,那么可以给予更改?
返回是,如果Vasya可以卖票给每个人并给予改变。否则返回否。
例子:
tickets([25, 25, 50]) // => YES
tickets([25, 100]) // => NO. Vasya will not have enough money to give change to 100 dollars
你需要算你有每个账:如果有人给你100,你不能给他带回75只用一个100法案。 tickets([25,25,25, 100,100])
应该返回"NO"
这里有一个天真的解决方案,
function tickets(peopleInLine) {
//var totalChange = 0; not needed
var total25bill = 0;
var total50bill = 0;
var total100bill = 0;
for (var i = 0; i < peopleInLine.length; i++) {
//totalChange += peopleInLine[i]
if (peopleInLine[i] === 25) {
total25bill += 1;
} else if (peopleInLine[i] === 50) {
if (total25bill >= 1) {
total25bill =-1; //gives back 1 25$ bill
total50bill += 1;
} else {
return "NO";
}
} else if (peopleInLine[i] === 100) {
if ((total50bill >= 1) && (total25bill >= 1)){
total25bill =-1; //gives back 1 25$ bill
total50bill =-1; //gives back 1 50$ bill
total100bill += 1;
} else if (total25bill >= 3){
total25bill =-3; //gives back 3 25$ bill
total100bill += 1;
} else {
return "NO";
}
}
}
return "YES";
}
WALLE点你,你将不得不跟踪每个法案。下面是一个递归定义,其中有3个状态变量,分别为a
,b
和c
,其中一个用于跟踪每个账单类型。
function isEmpty(xs) { return xs.length === 0; }
function first(xs) { return xs[0]; }
function rest(xs) { return xs.slice(1); }
function tickets(xs) {
function loop(a,b,c,xs) {
// validate drawer, a=$25, b=$50, c=$100
if (a < 0 || b < 0 || c < 0)
return "NO";
// if the drawer is valid and the line of people is empty...
else if (isEmpty(xs))
return "YES";
// otherwise, process the next person in line
else
switch (first(xs)) {
case 25:
return loop(a+1, b, c, rest(xs)); // give back $0
case 50:
return loop(a-1, b+1, c, rest(xs)); // give back $25
case 100:
return b > 0 // if drawer has a $50..
? loop(a-1, b-1, c+1, rest(xs)) // give back $25 + $50
: loop(a-3, b, c+1, rest(xs)) // give back 3 * $25
;
}
}
// start the loop with 0 of each bill in the drawer
return loop(0,0,0,xs);
}
我喜欢这个函数,因为没有逻辑重复,并且循环中每个分支只有一个合理的返回值。
我也喜欢案例分析看起来像每个账单类型的交易。
// in the case of someone paying with a $50
// give 1 a
// gain 1 b
// c stays the same
return loop(a-1, b+1, c, rest(xs))
这些状态变化使得很容易推断出程序的行为。
最简单的情况下,1人以$ 25
tickets([25])
=> 'YES'
1人用$ 50。有没有变化给他:(
tickets([50])
//=> 'NO'
1人用$ 100。也因为这个人
tickets([100])
//=> 'NO'
2人没有变化,先用$ 25。50美元的第二人得到25美元的变化
tickets([25,50])
//=> 'YES'
3人。首先是25美元。第二个人获得第一个人的25美元的变化。我们不能为抽屉里只有50美元的第三人做出改变。
tickets([25,50,100])
//=> 'NO'
相同的情况之上,但有一个额外的$ 25我们处理$ 100的法案之前。这一次我们有足够的改变。
tickets([25,50,25,100])
//=> 'YES'
它也可以工作,如果3美元25美元来到100美元的账单之前,因为3美元25美元(75美元)是100美元的有效变化。
tickets([25,25,25,100])
//=> 'YES'
我认为你需要跟踪*账单*,而不仅仅是总数。 – Pointy