1
\$\begingroup\$

The task

You are given a list of data entries that represent entries and exits of groups of people into a building. An entry looks like this:

{"timestamp": 1526579928, count: 3, "type": "enter"}

This means 3 people entered the building. An exit looks like this:

{"timestamp": 1526580382, count: 2, "type": "exit"}

This means that 2 people exited the building. timestamp is in Unix time.

Find the busiest period in the building, that is, the time with the most people in the building. Return it as a pair of (start, end) timestamps. You can assume the building always starts off and ends up empty, i.e. with 0 people inside.

const stamp = [
  {"timestamp": 1526579928, count: 3, "type": "enter"},
  {"timestamp": 1526580382, count: 2, "type": "exit"},
  {"timestamp": 1526579938, count: 6, "type": "enter"},
  {"timestamp": 1526579943, count: 1, "type": "enter"},
  {"timestamp": 1526579944, count: 0, "type": "enter"},
  {"timestamp": 1526580345, count: 5, "type": "exit"},
  {"timestamp": 1526580351, count: 3, "type": "exit"},
];

My imperative solution:

const findBusiestPeriod = lst => {
  let visitors = 0;
  const busiestPeriod = {
    start: null,
    end: null,
    maxVisitors: null,
  };

  lst.forEach((v, i) => {
    visitors = v.type === "enter" ?
      visitors + v.count :
      visitors - v.count;

    if (visitors > busiestPeriod.maxVisitors) {
      busiestPeriod.maxVisitors = visitors;
      busiestPeriod.start = v.timestamp;
      busiestPeriod.end = lst[i + 1].timestamp;
    } else if (visitors === busiestPeriod.maxVisitors){
      busiestPeriod.end = lst[i + 1].timestamp;
    }
  });
  return [busiestPeriod.start, busiestPeriod.end];
};

console.log(findBusiestPeriod(stamp));

My functional solution

const findBusiestPeriod2 = lst => {
  const {start, end} = lst.reduce((busiestPeriod, v, i) => {
    busiestPeriod.visitors = v.type === "enter" ?
      busiestPeriod.visitors + v.count :
      busiestPeriod.visitors - v.count;
    const visitors = busiestPeriod.visitors;
    if (!busiestPeriod.maxVisitors || visitors > busiestPeriod.maxVisitors) {
      busiestPeriod.maxVisitors = visitors;
      busiestPeriod.start = v.timestamp;
      busiestPeriod.end = lst[i + 1].timestamp;
    } else if (visitors === busiestPeriod.maxVisitors){
      busiestPeriod.end = lst[i + 1].timestamp;
    }
    return busiestPeriod;
  }, {visitors: 0, maxVisitor: null,});
  return [start, end];
};

console.log(findBusiestPeriod2(stamp));
\$\endgroup\$
1
\$\begingroup\$

From a short review;

  • I advise avoiding null, you could either not define the member or use undefined
  • busiestPeriod is a really long name, given how often you use it
  • You really only need to track the log entry with the most visitors, the start of the period would be timestamp of the entry before that
  • This: busiestPeriod.visitors = v.type === "enter" ? busiestPeriod.visitors + v.count : busiestPeriod.visitors - v.count; could be

    busiestPeriod.visitors += (v.type == "enter" ? v.count : - v.count);

    or even

    busiestPeriod.visitors += (v.type == "enter" ? 1 : -1) * v.count;

This is my counter-proposal:

function findBusiestTime(logs){

  function analyzeLogEntry(acc, log, index){
    if(log.type == "enter"){
      acc.count += log.count;   
    }else{
      if(acc.count > acc.maxCount){
        acc.maxCount = acc.count;
        acc.index = index;
      }
      acc.count -= log.count;
    }
    return acc;
  }

  let {index} = logs.reduce(analyzeLogEntry,{count:0, maxCount: 0});
  return [logs[index-1].timestamp,logs[index].timestamp];  
}
\$\endgroup\$
  • \$\begingroup\$ Why do you advice against using null? \$\endgroup\$ – thadeuszlay Apr 16 at 20:52
  • \$\begingroup\$ There is little null can do that undefined can't do, to me it's like the appendix of JavaScript \$\endgroup\$ – konijn Apr 16 at 21:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.