Skip to content

Instantly share code, notes, and snippets.

@tatsuyax25
Created December 12, 2025 18:32
Show Gist options
  • Select an option

  • Save tatsuyax25/106dbbf6e187c0c7ebc06558cb9c95b9 to your computer and use it in GitHub Desktop.

Select an option

Save tatsuyax25/106dbbf6e187c0c7ebc06558cb9c95b9 to your computer and use it in GitHub Desktop.
You are given an integer numberOfUsers representing the total number of users and an array events of size n x 3. Each events[i] can be either of the following two types: Message Event: ["MESSAGE", "timestampi", "mentions_stringi"] This event indica
/**
* @param {number} numberOfUsers
* @param {string[][]} events
* @return {number[]}
*/
var countMentions = function(numberOfUsers, events) {
// Result: mentions per user
const mentions = new Array(numberOfUsers).fill(0);
// Online state and offline-until times
const online = new Array(numberOfUsers).fill(true);
const offlineUntil = new Array(numberOfUsers).fill(-1);
// Normalize and sort:
// - ensure timestamps are numbers
// - sort by timestamp ascending
// We'll handle same-timestamp ordering by grouping, not by sort key.
const normalized = events.map(e => [e[0], Number(e[1]), e[2]]);
normalized.sort((a, b) => a[1] - b[1]);
// Group events by timestamp
const byTime = new Map();
for (const [type, ts, arg] of normalized) {
if (!byTime.has(ts)) byTime.set(ts, []);
byTime.get(ts).push([type, ts, arg]);
}
// Helper: process auto-online at a given timestamp
const applyAutoOnline = (t) => {
for (let u = 0; u < numberOfUsers; u++) {
if (!online[u] && offlineUntil[u] <= t) {
online[u] = true;
offlineUntil[u] = -1;
}
}
};
// Iterate timestamps in ascending order
const times = Array.from(byTime.keys()).sort((a, b) => a - b);
for (const t of times) {
const bucket = byTime.get(t);
// Phase 1: auto-online before any events at time t
applyAutoOnline(t);
// Phase 2: apply all OFFLINE events at time t
for (const [type, ts, arg] of bucket) {
if (type !== "OFFLINE") continue;
const id = Number(arg);
if (Number.isInteger(id) && id >= 0 && id < numberOfUsers) {
// User becomes offline for 60 units from ts.
// If already offline, extend window if needed.
online[id] = false;
const until = ts + 60;
offlineUntil[id] = Math.max(offlineUntil[id], until);
}
}
// Phase 3: apply all MESSAGE events at time t
for (const [type, ts, arg] of bucket) {
if (type !== "MESSAGE") continue;
// Split tokens by whitespace; ignore empties
const tokens = String(arg).trim().split(/\s+/);
for (const token of tokens) {
if (token === "ALL") {
// All users (online or offline)
for (let u = 0; u < numberOfUsers; u++) {
mentions[u] += 1;
}
} else if (token === "HERE") {
// Only currently online users (after auto-online, after OFFLINE at t)
for (let u = 0; u < numberOfUsers; u++) {
if (online[u]) mentions[u] += 1;
}
} else if (token.startsWith("id")) {
// id<number>
const idStr = token.slice(2);
const id = Number(idStr);
if (Number.isInteger(id) && id >= 0 && id < numberOfUsers) {
// Explicit mentions count even if user is offline
mentions[id] += 1;
}
// Invalid ids are ignored
}
// Unrecognized tokens are ignored
}
}
}
return mentions;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment