Hone logo
Hone
Problems

Deadline Propagation in a Task Management System

Deadline propagation is a crucial feature in task management systems, ensuring that dependent tasks inherit and update their deadlines based on changes in their parent tasks. This challenge asks you to implement a simplified version of deadline propagation in Go, focusing on a directed acyclic graph (DAG) of tasks where each task has a deadline and can depend on other tasks. Successfully implementing this will allow you to model and manage task dependencies and their associated deadlines effectively.

Problem Description

You are tasked with creating a Go program that propagates deadlines through a DAG of tasks. Each task is represented by a struct containing its ID, deadline, and a list of task IDs it depends on. The program should take a list of tasks and a task ID as input. It should then propagate the deadline of the input task to all its dependents, and recursively propagate the deadlines of those dependents, and so on, until no further changes occur. The propagation should stop when a task's deadline is already the same as the propagated deadline.

Key Requirements:

  • Task Representation: Define a Task struct with ID (int), Deadline (int), and Dependencies (a slice of int representing task IDs).
  • Deadline Propagation Function: Implement a function PropagateDeadline(tasks []Task, startTaskID int, newDeadline int) []Task. This function should take a slice of Task structs, a starting task ID, and a new deadline as input. It should update the deadlines of all reachable tasks from the startTaskID with the newDeadline and return the updated slice of Task structs.
  • Cycle Detection: While the problem states the graph is a DAG, your solution should be robust and avoid infinite loops if a cycle is accidentally introduced. A simple check to prevent re-processing a task during propagation is sufficient.
  • No Unnecessary Updates: The propagation should only update deadlines if they are different from the propagated value.

Expected Behavior:

The PropagateDeadline function should modify the Deadline field of each task reachable from the startTaskID to the newDeadline. The order of propagation doesn't matter, but all reachable tasks should eventually have the updated deadline. The function should return the modified slice of Task structs.

Edge Cases to Consider:

  • Task Not Found: If the startTaskID does not exist in the tasks slice, the function should return the original tasks slice unchanged.
  • No Dependencies: A task with no dependencies should have its deadline updated directly.
  • Circular Dependencies (Robustness): While the problem specifies a DAG, your code should gracefully handle potential cycles without entering an infinite loop. A simple "already visited" check is sufficient.
  • Multiple Paths: If a task is reachable through multiple paths, its deadline should be updated to the newDeadline regardless of which path is traversed first.

Examples

Example 1:

Input: tasks = [{ID: 1, Deadline: 10, Dependencies: []}, {ID: 2, Deadline: 20, Dependencies: [1]}, {ID: 3, Deadline: 30, Dependencies: [2]}], startTaskID = 1, newDeadline = 15
Output: tasks = [{ID: 1, Deadline: 15, Dependencies: []}, {ID: 2, Deadline: 15, Dependencies: [1]}, {ID: 3, Deadline: 15, Dependencies: [2]}]
Explanation: Task 1's deadline is updated to 15. Task 2 depends on Task 1, so Task 2's deadline is also updated to 15. Task 3 depends on Task 2, so Task 3's deadline is updated to 15.

Example 2:

Input: tasks = [{ID: 1, Deadline: 10, Dependencies: [2]}, {ID: 2, Deadline: 20, Dependencies: []}, {ID: 3, Deadline: 30, Dependencies: [2]}], startTaskID = 2, newDeadline = 25
Output: tasks = [{ID: 1, Deadline: 10, Dependencies: [2]}, {ID: 2, Deadline: 25, Dependencies: []}, {ID: 3, Deadline: 25, Dependencies: [2]}]
Explanation: Task 2's deadline is updated to 25. Task 1 depends on Task 2, so Task 1's deadline remains unchanged. Task 3 depends on Task 2, so Task 3's deadline is updated to 25.

Example 3: (Edge Case - Task Not Found)

Input: tasks = [{ID: 1, Deadline: 10, Dependencies: []}, {ID: 2, Deadline: 20, Dependencies: [1]}], startTaskID = 3, newDeadline = 15
Output: tasks = [{ID: 1, Deadline: 10, Dependencies: []}, {ID: 2, Deadline: 20, Dependencies: [1]}]
Explanation: Task 3 does not exist, so the original tasks slice is returned unchanged.

Constraints

  • 1 <= len(tasks) <= 1000
  • 1 <= Task.ID <= 1000
  • 0 <= Task.Deadline <= 1000
  • 0 <= len(Task.Dependencies) <= 100
  • Task.Dependencies contains only valid task IDs (present in the tasks slice).
  • The graph represented by the tasks is a Directed Acyclic Graph (DAG).
  • Performance: The solution should complete within 1 second for the given constraints.

Notes

  • Consider using a recursive approach to propagate the deadline.
  • A "visited" set or map can be helpful to prevent infinite loops in case of accidental cycles.
  • Focus on clarity and correctness first, then optimize for performance if necessary.
  • The PropagateDeadline function should modify the tasks in place and return the modified slice. Creating new Task structs for each update is less efficient.
Loading editor...
go