Quick Overview

This question evaluates a candidate's ability to design and implement time-ordered in-memory data structures and APIs, testing competencies in temporal event ordering and precedence, scheduled deletions, priority-sorted retrieval, user-task assignment, and historical (time-travel) queries.

Implement timestamped task management system APIs

Company: Instacart

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: medium

Interview Round: Take-home Project

You are implementing an in-memory **Task Management System**. All API methods are called with a `timestamp` representing the logical time when the operation happens. Assume: - API calls are processed in **non-decreasing `timestamp` order**. - Task IDs and user IDs are strings (or ints). - If an operation references a non-existent task/user, it should be a no-op (or return null/false) — choose a consistent behavior and document it. ## Data model Each task has: - `task_id` - `description` - `priority` (integer), default `0` at creation - optional assignment to one or more users (define whether multiple users can be assigned; if unspecified, assume **a task can be assigned to multiple users** and each user can have multiple tasks) ## Required APIs ### 1) CRUD tasks Implement four methods (all take `timestamp`): - `createTask(timestamp, task_id, description)` - `getTask(timestamp, task_id) -> description | null` - `updateTask(timestamp, task_id, new_description)` - `deleteTask(timestamp, task_id)` Deleting a task removes it from the system and unassigns it from all users. ### 2) Priorities and sorted retrieval Implement: - `updateTaskPriority(timestamp, task_id, new_priority)` - `getSortedPrioritizedTasks(timestamp) -> List[task_id]` `getSortedPrioritizedTasks` should return all **currently existing** tasks sorted by: 1. higher `priority` first 2. tie-break by `task_id` ascending (or another deterministic rule you state) ### 3) Users, assignment, and scheduled deletion Implement: - `addUser(timestamp, user_id)` - `assignTaskToUser(timestamp, user_id, task_id)` - `unassignTaskToUser(timestamp, user_id, task_id)` - `scheduleDeletion(timestamp, task_id, delay)` `scheduleDeletion` schedules the task to be deleted at time `timestamp + delay`. **Important ordering rule:** If one or more deletions are scheduled to occur at time `T`, then at timestamp `T` those deletions must be applied **before any other operations at the same timestamp `T`**. ### 4) Time-travel query Implement: - `getUserTaskNumsAt(timestamp, user_id, time_at) -> int` This returns the number of tasks assigned to `user_id` **at logical time `time_at`** (where `time_at <= timestamp`). The result must reflect all creates/deletes/assigns/unassigns/scheduled-deletes that happened up to `time_at`, with the same deletion-precedence rule at identical timestamps. ## Constraints (you may assume) - Up to ~200k operations. - Timestamps fit in 64-bit integers. - Your implementation should be efficient (roughly near O(log n) per operation for the expensive parts).

Quick Answer: This question evaluates a candidate's ability to design and implement time-ordered in-memory data structures and APIs, testing competencies in temporal event ordering and precedence, scheduled deletions, priority-sorted retrieval, user-task assignment, and historical (time-travel) queries.

Implement an in-memory **Task Management System** driven by a list of timestamped operations. Implement `solution(operations)`: each item in `operations` is a list whose first element is the method name and whose second element is the integer `timestamp`. Operations arrive in **non-decreasing timestamp order**. Return the list of outputs produced by the query methods, in order. **Methods** (arguments shown after `timestamp`): - `["createTask", ts, task_id, description]` — create a task (priority defaults to 0). - `["getTask", ts, task_id]` — append the task's `description`, or `None` if it does not exist. - `["updateTask", ts, task_id, new_description]` — update an existing task's description. - `["deleteTask", ts, task_id]` — delete the task and unassign it from all users. - `["updateTaskPriority", ts, task_id, new_priority]` — set a task's priority. - `["getSortedPrioritizedTasks", ts]` — append the list of all currently existing `task_id`s sorted by higher priority first, breaking ties by `task_id` ascending. - `["addUser", ts, user_id]` — register a user. - `["assignTaskToUser", ts, user_id, task_id]` — assign a task to a user (a task may be assigned to multiple users; a user may have multiple tasks). - `["unassignTaskToUser", ts, user_id, task_id]` — remove an assignment. - `["scheduleDeletion", ts, task_id, delay]` — schedule the task to be deleted at time `ts + delay`. - `["getUserTaskNumsAt", ts, user_id, time_at]` — append the number of tasks assigned to `user_id` at logical time `time_at` (`time_at <= ts`). **Deletion-precedence rule:** if one or more deletions are scheduled to fire at time `T`, those deletions must be applied **before any other operation at the same timestamp `T`** (and this same precedence is reflected in `getUserTaskNumsAt` time-travel results). Referencing a non-existent task or user is a no-op (queries return `None`/`0`). Re-creating an id that was previously deleted is allowed.

Constraints

  • Up to ~200,000 operations.
  • Timestamps fit in 64-bit integers and arrive in non-decreasing order.
  • Task IDs and user IDs are strings or integers.
  • time_at <= timestamp for getUserTaskNumsAt.
  • Expensive operations should be near O(log n).

Examples

Input: ([['createTask', 1, 't1', 'desc1'], ['getTask', 2, 't1'], ['updateTask', 3, 't1', 'desc1-updated'], ['getTask', 4, 't1'], ['getTask', 5, 'tX'], ['deleteTask', 6, 't1'], ['getTask', 7, 't1']],)

Expected Output: ['desc1', 'desc1-updated', None, None]

Explanation: Basic CRUD: create then getTask returns 'desc1'; after updateTask getTask returns the new description; getTask on a missing id 'tX' returns None; after deleteTask, getTask returns None.

Input: ([['createTask', 1, 'a', 'A'], ['createTask', 1, 'b', 'B'], ['createTask', 1, 'c', 'C'], ['updateTaskPriority', 2, 'a', 5], ['updateTaskPriority', 2, 'b', 10], ['updateTaskPriority', 2, 'c', 5], ['getSortedPrioritizedTasks', 3], ['deleteTask', 4, 'b'], ['getSortedPrioritizedTasks', 5]],)

Expected Output: [['b', 'a', 'c'], ['a', 'c']]

Explanation: Sorted retrieval orders by higher priority first, then task_id ascending: b(10) before a(5) and c(5), with a before c on the id tie-break. After deleting b, only a and c remain.

Hints

  1. Because operations arrive in non-decreasing timestamp order, you can flush all scheduled deletions whose due time is <= the current operation's timestamp BEFORE processing that operation. This enforces the deletion-precedence rule for free.
  2. Use a min-heap keyed by (due_time, sequence) for scheduled deletions, and mark each scheduled entry alive/cancelled so a manually-deleted task does not double-delete.
  3. For getUserTaskNumsAt, keep a per-user history of (timestamp, cumulative_count). On each assign/unassign/delete append/overwrite the entry for that timestamp, then answer a query with a binary search for the last entry whose timestamp <= time_at.
  4. deleteTask must also unassign the task from every user; keep a reverse index task_id -> set(user_id) so you can update each affected user's count.

Loading coding console...