Skip to content

Instantly share code, notes, and snippets.

@szemate
Last active October 16, 2022 17:28
Show Gist options
  • Save szemate/4c000f68e995eeb4bfbb8a10d05a7b57 to your computer and use it in GitHub Desktop.
Save szemate/4c000f68e995eeb4bfbb8a10d05a7b57 to your computer and use it in GitHub Desktop.
Pizza Generator exercise solution
// https://gist.github.com/szemate/537792a6cf39008d51192fc8a3034d9a
const toppings = [
'ham',
'salami',
'mushroom',
'spinach',
'artichoke',
];
const basePrice = 8;
const toppingPrices: Record<string, number> = {
ham: 2,
salami: 3,
mushroom: 1,
spinach: 1,
artichoke: 2,
}
// Exercise 1
function generate3ToppingsWithoutDuplication(): string {
const pizzas: string[][] = [];
for (let i = 0; i < toppings.length - 2; i++) {
for (let j = i + 1; j < toppings.length - 1; j++) {
for (let k = j + 1; k < toppings.length; k++) {
pizzas.push([toppings[i], toppings[j], toppings[k]]);
}
}
}
const pizzaPrices = pizzas.map(calculatePrice);
return pizzas
.map(sortToppings)
.map(joinToppings)
.map((pizzaName, i) => appendPrice(pizzaName, pizzaPrices[i]))
.sort()
.join('\n');
}
// Exercise 2
function generate3ToppingsWithDuplication(): string {
const pizzas: string[][] = [];
for (let i = 0; i < toppings.length; i++) {
for (let j = 0; j < toppings.length; j++) {
for (let k = 0; k < toppings.length; k++) {
const pizzaCandidate = [toppings[i], toppings[j], toppings[k]];
if (!pizzas.find((pizza) => haveSameToppings(pizza, pizzaCandidate))) {
pizzas.push(pizzaCandidate);
}
}
}
}
const pizzaPrices = pizzas.map(calculatePrice);
return pizzas
.map(sortToppings)
.map(combineToppings)
.map(joinToppings)
.map((pizzaName, i) => appendPrice(pizzaName, pizzaPrices[i]))
.sort()
.join('\n');
}
// Exercise 3
function generateEveryPizzaWithoutDuplication(): string {
const pizzas = backtrackGenerate();
const pizzaPrices = pizzas.map(calculatePrice);
return pizzas
.map(sortToppings)
.map(joinToppings)
.map((pizzaName, i) => appendPrice(pizzaName, pizzaPrices[i]))
.sort()
.join('\n');
}
// --- Helpers ---
function backtrackGenerate(
toppingsLeft: string[] = toppings,
pizza: string[] = []
): string[][] {
let pizzas: string[][] = [];
if (pizza.length > 0) {
pizzas.push([...pizza]); // shallow copy
}
const toppingsCopy = [...toppingsLeft]; // shallow copy
while (toppingsCopy.length > 0) {
pizza.push(toppingsCopy.pop() as string);
pizzas = [...pizzas, ...backtrackGenerate(toppingsCopy, pizza)];
pizza.pop();
}
return pizzas;
}
function haveSameToppings(pizza1: string[], pizza2: string[]): boolean {
return pizza1.sort().join('') === pizza2.sort().join('');
}
function calculatePrice(pizza: string[]): number {
return pizza.reduce(
(total, topping) => total + toppingPrices[topping],
basePrice
);
}
function sortToppings(pizza: string[]): string[] {
return pizza.sort();
}
function joinToppings(pizza: string[]): string {
const last = pizza[pizza.length - 1];
const rest = pizza.slice(0, -1);
return rest.join(', ') + ((rest.length > 0) ? ' and ' : '') + last;
}
function combineToppings(pizza: string[]): string[] {
return pizza.reduce((combinedToppings: string[], topping, i) => {
if (i >= 2 && pizza[i - 2] === topping) {
combinedToppings[combinedToppings.length - 1] = `triple ${topping}`;
} else if (i >= 1 && pizza[i - 1] === topping) {
combinedToppings[combinedToppings.length - 1] = `double ${topping}`;
} else {
combinedToppings.push(topping);
}
return combinedToppings;
}, []);
}
function appendPrice(pizzaName: string, price: number): string {
return `${pizzaName} - €${price}`;
}
console.log(generate3ToppingsWithoutDuplication());
console.log('---');
console.log(generate3ToppingsWithDuplication());
console.log('---');
console.log(generateEveryPizzaWithoutDuplication());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment