GAZAR

Principal Engineer | Mentor

Get Most Cookie Used

Get Most Cookie Used

We have a list of cookies

cookie,timestamp
AtY0laUfhglK3lC7,2018-12-09T14:19:00+00:00
SAZuXPGUrfbcn5UA,2018-12-09T10:13:00+00:00
5UAVanZf6UtGyKVS,2018-12-09T07:25:00+00:00
AtY0laUfhglK3lC7,2018-12-09T06:19:00+00:00
SAZuXPGUrfbcn5UA,2018-12-08T22:03:00+00:00
4sMM2LxV07bPJzwf,2018-12-08T21:30:00+00:00
fbcn5UAVanZf6UtG,2018-12-08T09:30:00+00:00
4sMM2LxV07bPJzwf,2018-12-07T23:30:00+00:00

Write a command line program in your preferred language to process the log file and return the most active cookie for a specific day. Please include a -f parameter for the filename to process and a -d parameter to specify the date.

We define the most active cookie as one seen in the log the most times during a given day.

Assumptions:

  • If multiple cookies meet that criteria, please return all of them on separate lines.
  • Please only use additional libraries for testing, logging and cli-parsing. There are libraries for most
  • languages which make this too easy (e.g pandas) and we’d like you to show off your coding skills.
  • You can assume -d parameter takes date in UTC time zone.
  • You have enough memory to store the contents of the whole file.
  • Cookies in the log file are sorted by timestamp (most recent occurrence is the first line of the file).

We're looking for a concise, maintainable, extendable and correct solution. We're hoping you'll deliver your solution as production grade code and demonstrate:

  • good testing practices
  • knowledge of build systems, testing frameworks, etc.
  • clean coding practices (meaningful names, clean abstractions, etc.)

First thing first you want a function to find the occurance of that date in the file

function binarySearchFirstOccurrence(arr, targetDate) {
    let left = 0;
    let right = arr.length - 1;
    let result = -1;

    while (left <= right) {
        const mid = Math.floor((left + right) / 2);
        const [cookie, timestamp] = arr[mid].split(',');
        if (timestamp.startsWith(targetDate)) {
            result = mid;
            right = mid - 1;
        } else if (timestamp < targetDate) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }

    return result;
}

Then you need a HashTable to store the data

class HashTable {
    constructor() {
        this.table = {};
    }
    // Increment count for a cookie
    increment(cookie) {
        this.table[cookie] = (this.table[cookie] || 0) + 1;
    }
    // Get count for a cookie
    getCount(cookie) {
        return this.table[cookie] || 0;
    }

    // Get all cookies and their counts
    getAllCookies() {
        return this.table;
    }
}

And a function to count the cookies and fill the hash nodes

function getMostActiveCookie(filename, startDate, endDate) {
    const cookieMap = new HashTable();

    // Read the file line by line
    const fileContent = fs.readFileSync(filename, 'utf8').split('\n');
    // Find the index of the first occurrence of the start date
    const startIndex = binarySearchFirstOccurrence(fileContent, startDate);
    if (startIndex === -1) {
        console.log(`No entries found for ${startDate}.`);
        return;
    }


    // Find the index of the first occurrence of the end date
    const endIndex = binarySearchFirstOccurrence(fileContent, endDate);
    if (endIndex === -1) {
        console.log(`No entries found for ${endDate}.`);
        return;
    }

    // Populate cookieMap with counts for each cookie within the specified date range
    for (let i = startIndex; i <= endIndex; i++) {
        const [cookie, timestamp] = fileContent[i].split(',');
        if (timestamp >= startDate && timestamp <= endDate) {
            cookieMap.increment(cookie);
        }
    }

    // Find the most active cookie(s)
    let maxCount = 0;
    const allCookies = cookieMap.getAllCookies();
    Object.values(allCookies).forEach((count) => {
         maxCount = Math.max(maxCount, count);
    });
    
    const mostActiveCookies = Object.keys(allCookies).filter(
         (cookie) => allCookies[cookie] === maxCount
    );
    
    return mostActiveCookies;
}

And finally a bit of house chore to accept those flags

const args = process.argv.slice(2);
const filenameIndex = args.findIndex(arg => arg === '-f');
const startDateIndex = args.findIndex(arg => arg === '-s');
const endDateIndex = args.findIndex(arg => arg === '-e');
const filename = args[filenameIndex + 1];
const startDate = args[startDateIndex + 1];
const endDate = args[endDateIndex + 1];

if (!filename || !startDate || !endDate) {
    console.log('Usage: node script.js -f <filename> -s <start_date> -e <end_date>');
    process.exit(1);
}

const mostActiveCookies = getMostActiveCookie(filename, startDate, endDate);

if (mostActiveCookies) {
  console.log(mostActiveCookies.join("\n"));
}

And at the end count the cookies and type their counts

With this modification, you can now specify both the start date (-s) and the end date (-e) as command line arguments, and the program will count the occurrences of each cookie within the specified date range