# Daily Challenge #144 - Box Office Clerk

You work as a clerk at a cinema box office and a new movie has been released. There are a lot of people standing in a line waiting to buy a ticket with either 25, 50, or 100 dollar bill. Each ticket for the new movie costs 25 dollars.

If you start with no money in the register, can you sell a ticket to every person in line and give change? You must attend to everyone in order, it would be unfair to sell tickets out of order.

Return YES, if you can sell a ticket to every person and give change.
Otherwise, return NO.

Examples
tickets([25, 25, 50]) => YES
tickets([25, 100]) => NO You will not have enough money to give change to 100 dollars
tickets([25, 25, 50, 50, 100]) => NO You will not have the right bills to give 75 dollars of change (you can't make two bills of 25 from one of 50)

Tests
tickets([25, 25, 50, 50])
tickets([25, 50, 25, 100])

Good luck!

This challenge comes from AlexIsHappy on CodeWars. Thank you to CodeWars, who has licensed redistribution of this challenge under the 2-Clause BSD License!

Want to propose a challenge idea for a future post? Email yo+challenge@dev.to with your suggestions!

### Discussion Using JavaScript:

const changes = {
25: 0,
50: 0
};

const procedure = cash => {
switch (cash) {
case 25:
changes++;
return true;
case 50:
if (changes > 0) {
changes++;
changes--;
return true;
} else {
return false;
}
case 100:
if (changes > 0 && changes > 0) {
changes--;
changes--;
return true;
} else if (changes > 2) {
changes -= 3;
return true;
} else {
return false;
}
}
};

const tickets = queue => queue.every(procedure) ? 'YES' : 'NO';

console.log(tickets([25, 25, 50, 50, 100]));    // NO
console.log(tickets([25, 25, 50, 50]));         // YES
console.log(tickets([25, 50, 25, 100]));        // YES


## Scala

object BoxOffice {

type Register = Map[Int, Int]

@tailrec
def tickets (xs: Seq[Int], register: Register = Map()): Answer =
xs match {
case Nil => Yes
case x :: rest =>
x match {
case 25  => tickets(rest, register add 25)
case 50  =>
if (register.hasItem(25)) tickets(rest, register remove 25 add 50)
else No
case 100 =>
if (register.hasItem(50) && register.hasItem(25))
tickets(rest, register remove 50 remove 25 add 100)
else if (register.hasItem(25, 3))
else No
case x   => throw new MatchError(s"Can't handle currency $x") } } implicit class ExtRegister(r: Register) { def hasItem (key: Int, amount: Int = 1): Boolean = (r get key) match { case None => false case Some(value) => value >= amount } def add (item: Int, amount: Int = 1): Register = { val prev = r.getOrElse(item, 0) r.updated(item, prev + amount) } def remove(item: Int, amount: Int = 1): Register = { val prev = r.getOrElse(item, 0) r.updated(item, prev - amount) } } }  And the tests: class BoxOfficeTest extends FunSuite { test("tickets") { assert(tickets(List(25, 25, 50)) == Yes) assert(tickets(List(25, 100)) == No) assert(tickets(List(25, 25, 50, 50, 100)) == No) assert(tickets(List(25, 25, 50, 50)) == Yes) assert(tickets(List(25, 50, 25, 100)) == Yes) } }  Rust: fn tickets(bills: &[usize]) -> Result<bool, String> { let mut change_25 = 0usize; let mut change_50 = 0usize; for bill in bills { match bill { 25 => { change_25 += 1; } 50 => { if 1 <= change_25 { change_25 -= 1; change_50 += 1; } else { return Ok(false); } } 100 => { if 1 <= change_25 && 1 <= change_50 { change_25 -= 1; change_50 -= 1; } else if 3 <= change_25 { change_25 -= 3; } else { return Ok(false); } } _ => { return Err(format!("Expected a 25, 50 or 100 bill - got {}", bill)); } } } Ok(true) } fn main() { assert!(tickets(&[25, 25, 50]) == Ok(true)); assert!(tickets(&[25, 100]) == Ok(false)); assert!(tickets(&[25, 25, 50, 50, 100]) == Ok(false)); assert!(tickets(&[25, 25, 50, 50]) == Ok(true)); assert!(tickets(&[25, 50, 25, 100]) == Ok(true)); }  Another JS approach const tickets = bills => { let status = "YES"; const register = bills.reduce( (acc, val) => { acc[val] += 1; return acc; }, { 25: 0, 50: 0, 100: 0 } ); const removeFromRegister = bills => bills.forEach(bill => (register[bill] -= 1)); bills.forEach(bill => { if (bill === 100) removeFromRegister([50, 25]); if (bill === 50) removeFromRegister(); }); Object.values(register).forEach(item => { if (item < 0) status = "NO"; }); return status; }; console.log(tickets([25, 25, 50, 50, 100])); //NO  CondeSandbox Python solution 🐍 from typing import List TICKET_VALUE = 25 def tickets(values: List[int]) -> str: register = 0 for amount in values: change = amount - TICKET_VALUE if register < change: return "NO" register += TICKET_VALUE return "YES"  using Ruby: def tickets(queue) tillbox = [] can_process = true change = { 25 => [], 50 => , 100 => [25,50] } queue.each do |bill| # if tillbox has the change required if (tillbox & change[bill] == change[bill]) tillbox << bill change[bill].each { |b| tillbox.delete_at(tillbox.index(b)) } else can_process = false break end end can_process end puts tickets([25, 25, 50, 50]) #true puts tickets([25, 50, 25, 100]) #false  Haskell: import Control.Monad (foldM) import Data.Maybe (isJust) data CashBox = CashBox { v25 :: Int, v50 :: Int } emptyBox :: CashBox emptyBox = CashBox 0 0 add25s :: Int -> CashBox -> CashBox add25s n (CashBox x y) = CashBox (x + n) y add25 :: CashBox -> CashBox add25 = add25s 1 take25s :: Int -> CashBox -> CashBox take25s n = add25s (-n) take25 :: CashBox -> CashBox take25 = take25s 1 add50s :: Int -> CashBox -> CashBox add50s n (CashBox x y) = CashBox x (y + 1) add50 :: CashBox -> CashBox add50 = add50s 1 take50s :: Int -> CashBox -> CashBox take50s n = add50s (-n) take50 :: CashBox -> CashBox take50 = take50s 1 makeChange :: Int -> CashBox -> Maybe CashBox makeChange 25 c = Just$ add25 c
makeChange 50  c = if v25 c > 0
then Just $add50$ take25 c
else Nothing
makeChange 100 c = case v50 c of
0 -> if v25 c > 2 then Just (take25s 3 c) else Nothing
_ -> if v25 c > 0 then Just (take25 (take50 c)) else Nothing
makeChange _   _ = Nothing

tickets :: [Int] -> Bool
tickets = isJust . foldM (flip makeChange) emptyBox


I think all my utility add and take kinda obscure the code a bit. Oh well. Also I'm flipping makeChange because I realized after that foldM applies the arguments in the other order, and I was too lazy to rewrite :P

Typescript:

const tickets = (bills: number[]) => {
return bills.reduce(
(prev, curr) => {
if (curr == 25) return [[prev + 1, prev], prev];
if (curr == 50 && prev === 0) return [prev, 'NO'];
if (curr == 50) return [[prev - 1, prev + 1], prev];
if (prev >= 1 && prev >= 1) return [[prev - 1, prev - 1], prev];
if (prev >= 3) return [[prev - 3, prev], prev];
return [prev, 'NO'];
},
<[[number, number], string]>[[0, 0], 'YES']
);
}

const testCases = [
[25, 25, 50],
[25, 100],
[25, 25, 50, 50, 100],
[25, 25, 50, 50],
[25, 50, 25, 100]
];
for (const testCase of testCases) {
console.log(testCase, '=>', tickets(testCase))
}  