Search code examples
javascriptjsonstring-comparison

Javascript - Finding Pizza winner out of JSON


Any customer that orders a three-topping pizza with a unique combination of toppings across all pizzas in all stores for that month will receive a coupon for a free pizza by email (if they provide their email address).

Here are two methods for finding out the winner. But none of these methods is working properly. I am not sure where the bug is. Also which dataset should I use to test these implementations? How can I solve this problem with database queries?

// Here is the json array and functions:
const inputArray = [{"email": "email1@example.com", "toppings":
    ["Mushrooms","Pepperoni","Peppers"]},
    {"email": "email2@example.com", "toppings":
    ["Cheddar","Garlic","Oregano"]},
    {"email": "email3@example.com", "toppings": ["Bacon","Ham","Pineapple"]},
    {"email": "", "toppings": ["Parmesan","Tomatoes"]},
    {"email": "email4@example.com", "toppings":
    ["Mushrooms","Pepperoni","Peppers"]},
    {"email": "", "toppings": ["Cheddar","Tomatoes"]},
    {"email": "email5@example.com", "toppings": ["Bacon","Ham","Pineapple"]},
    {"email": "email6@example.com", "toppings": ["Beef","Parmesan"]},
    {"email": "", "toppings": ["Onions","Pepperoni"]},
    {"email": "", "toppings": ["Bacon","Ham","Pineapple"]}]


function printWinners1(inputArray) {
  // Perform a QuickSort on the array.
  inputArray.sort((a, b) => {
    // Convert each toppings array to a string and do a string comparison
    return a.toppings.toString().localeCompare(b.toppings.toString());
  });
  let previousEmail = '';
  let previousToppingsAsString = '';
  let previousToppingCount = 0;
  let numberOfSimilarOrders = 0;
  // Iterate through the array, with "order" being each item in the  array.
  inputArray.map((order) => {
    let toppingsAsString = order.toppings.toString();
    if (toppingsAsString === previousToppingsAsString) {
      numberOfSimilarOrders++;
    } else {
      if ((numberOfSimilarOrders === 1) && 
          (previousToppingCount === 3) && 
          (previousEmail) !== '') {
        // Print out the email.
        console.log(previousEmail);
      }
      previousToppingsAsString = toppingsAsString;
      previousEmail = order.email;
      previousToppingCount = order.toppings.length;
      numberOfSimilarOrders = 1;
    }
  });
}

function printWinners2(inputArray) {
  let hashTable = new Map();
  // Iterate through the array, with "order" being each item in the array.
  inputArray.map((order) => {
    if ((order.toppings.length === 3) && (order.email !== '')) {
      let toppingsAsString = order.toppings.toString();
      let matchingValue = hashTable.get(toppingsAsString);
      if (matchingValue) {
        // This key was already in the hash table.
        // matchingValue is a reference to the object in the hash table.
        matchingValue.duplicate = true;
      } else {
        // Insert into the hash table, using the toppings as the           key and an object containing the email as the value.
        hashTable.set(toppingsAsString, {
          email: order.email,
          duplicate: false
        });
      }
    }
  });
  // Iterate through the values in the hash table, with "value" being each value.
  hashTable.forEach((value) => {
    if (!value.duplicate) {
      // Print out the email.
      console.log(value.email);
    }
  });
}
printWinners1(inputArray)


Solution

  • Here is my take on it.

    I go through your order list and rearrange it in an object ("hash") according to the chosen topping triplets. The toppings are sorted to make the order in which they are mentioned irrelevant.

    I then filter through them again a to check for their uniqueness. The output is an array of arrays: each sub-array contains the topping combination followed by a one-item-array of emails of winners.

    const inputArray = [{"email": "email1@example.com", "toppings":
    ["Mushrooms","Pepperoni","Peppers"]},
    {"email": "email2@example.com", "toppings":
    ["Cheddar","Garlic","Oregano"]},
    {"email": "email3@example.com", "toppings": ["Bacon","Ham","Pineapple"]},
    {"email": "", "toppings": ["Parmesan","Tomatoes"]},
    {"email": "email4@example.com", "toppings":
    ["Mushrooms","Pepperoni","Peppers"]},
    {"email": "", "toppings": ["Cheddar","Tomatoes"]},
    {"email": "email5@example.com", "toppings": ["Bacon","Ham","Pineapple"]},
    {"email": "email6@example.com", "toppings": ["Beef","Parmesan"]},
    {"email": "", "toppings": ["Onions","Pepperoni"]},
    {"email": "", "toppings": ["Bacon","Ham","Pineapple"]}];
    
    var win=Object.entries(inputArray.reduce((a,c)=>{
      if (c.toppings.length==3){
    let top=c.toppings.sort().join('_');
    if (c.email) (a[top]=a[top]||[]).push(c.email);
      }
      return a;
    }, {})).filter(([t,m])=>m.length==1);
    
    console.log(win);
    // The actual list of winners is extracted like this:
    console.log(win.map(c=>c[1][0]))