确定行-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 
+1

我认为你需要跟踪*账单*,而不仅仅是总数。 – Pointy

你需要算你有每个账:如果有人给你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,bc,其中一个用于跟踪每个账单类型。

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'