Skip to content

Instantly share code, notes, and snippets.

@ioncreature
Last active January 18, 2022 15:18
Show Gist options
  • Save ioncreature/1ce42cc458bc5fde133a3e93cef3821e to your computer and use it in GitHub Desktop.
Save ioncreature/1ce42cc458bc5fde133a3e93cef3821e to your computer and use it in GitHub Desktop.
Printify interview
import * as assert from 'assert';
const coins = [1, 2, 5, 10, 20, 50, 100, 200].reverse();
type Coins = Map<number, number>;
interface Product {
name: string;
price: number;
}
class Machine {
constructor(private readonly products: Product[]) {
}
buy(productName: string, coins: Coins): { coins: Coins, product: Product } {
const product = this.getProduct(productName);
const amount = this.countCoins(coins);
if (amount < product.price) {
throw new Error('Not enough money');
}
return {
product,
coins: Machine.getChange(amount - product.price)
};
}
private getProduct(name: string) {
const product = this.products.find((p) => p.name == name);
if (!product) {
throw new Error('No such product');
}
return product;
}
private countCoins(coins: Coins): number {
let amount = 0;
coins.forEach((count, coinPrice) => {
amount += count * coinPrice;
})
return amount;
}
static getChange(amount: number): Coins {
const change = new Map();
for (let i = 0; i < coins.length; i++) {
const q = Math.floor(amount / coins[i]);
if (q >= 1) {
change.set(coins[i], q);
amount -= coins[i] * q;
}
if (!amount) {
break;
}
}
return change;
}
}
// Unit tests
assert.deepEqual(Machine.getChange(500), new Map([[200, 2], [100, 1]]));
assert.deepEqual(Machine.getChange(105), new Map([[100, 1], [5, 1]]));
assert.deepEqual(Machine.getChange(0), new Map());
console.log('\n\nUNIT TESTS PASSED\n\n')
// Integrations
const machine = new Machine([
{name: 'Knachapury', price: 233},
{name: 'B', price: 126},
{name: 'C', price: 95},
]);
// it should throw on unknown product
assert.throws(
() => {
machine.buy('Cola', new Map([[200, 1]]));
},
{
name: 'Error',
message: 'No such product'
}
);
// it should throw if user inserts not enough money
assert.throws(
() => {
machine.buy('Knachapury', new Map([[200, 1]]));
},
{
name: 'Error',
message: 'Not enough money'
}
);
// it should return product and change
assert.deepEqual(machine.buy('Knachapury', new Map([[200, 2]])), {
product: {name: 'Knachapury', price: 233},
coins: new Map([[100, 1], [50, 1], [10, 1], [5, 1], [2, 1]])
});
console.log('\n\nINTEGRATION TESTS PASSED\n\n')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment