From 2320d90132b5ab28b283cd3eaa7a9f4abf79aa1d Mon Sep 17 00:00:00 2001 From: kosuri-indu Date: Sun, 15 Oct 2023 10:21:38 +0530 Subject: [PATCH 01/17] to add job seq program --- greedy_methods/job_sequence.py | 54 ++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 greedy_methods/job_sequence.py diff --git a/greedy_methods/job_sequence.py b/greedy_methods/job_sequence.py new file mode 100644 index 000000000000..2d77a9876ff4 --- /dev/null +++ b/greedy_methods/job_sequence.py @@ -0,0 +1,54 @@ +""" +Given a list of tasks, each with a deadline and reward, +The maximum number of tasks that can be scheduled to maximize reward. +We can only complete one task at a time, and each task takes 1 unit +of time to complete. Once a task has passed its deadline, it can no +longer be scheduled. + +Example : +tasks_info = [(4, 20), (1, 10), (1, 40), (1, 30)] +max_tasks will return (2, [2, 0]) - +which is by scheduling the tasks with rewards 40, 20 + +This problem can be solved using the concept of "GREEDY ALGORITHM". +Time Complexity - O(n log n) + +We iterate over the tasks array once, sorting it in descending order of reward. +Then we iterate over the sorted tasks array once more, scheduling each +task if its deadline is greater than the current time.The greedy choice at +each point is to either schedule the current task if its deadline is greater +than the current time, or skip it otherwise. +""" + +class Task: + def __init__(self, id, deadline, reward): + self.id = id + self.deadline = deadline + self.reward = reward + +def max_tasks(tasks_info : list[tuple[int]]) -> int: + """ + >>> max_tasks([(4, 20), (1, 10), (1, 40), (1, 30)]) + (2, [2, 0]) + >>> max_tasks([(1, 10), (2, 20), (3, 30), (2, 40)]) + (2, [3, 2]) + """ + tasks = [Task(i, d, p) for i, (d, p) in enumerate(tasks_info)] + + tasks.sort(key=lambda task: task.reward, reverse=True) + + schedule = [] + current_time = 0 + + for task in tasks: + if task.deadline > current_time: + schedule.append(task.id) + current_time += 1 + + return len(schedule),schedule + +if __name__ == "__main__": + import doctest + doctest.testmod() + + print(max_tasks([(4, 20), (1, 10), (1, 40), (1, 30)])) From 3b3f3a844a8e12111ec3780fc373b894867f99af Mon Sep 17 00:00:00 2001 From: kosuri-indu Date: Sun, 15 Oct 2023 10:24:45 +0530 Subject: [PATCH 02/17] to add job seq program --- greedy_methods/job_sequence.py | 54 ++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 greedy_methods/job_sequence.py diff --git a/greedy_methods/job_sequence.py b/greedy_methods/job_sequence.py new file mode 100644 index 000000000000..2d77a9876ff4 --- /dev/null +++ b/greedy_methods/job_sequence.py @@ -0,0 +1,54 @@ +""" +Given a list of tasks, each with a deadline and reward, +The maximum number of tasks that can be scheduled to maximize reward. +We can only complete one task at a time, and each task takes 1 unit +of time to complete. Once a task has passed its deadline, it can no +longer be scheduled. + +Example : +tasks_info = [(4, 20), (1, 10), (1, 40), (1, 30)] +max_tasks will return (2, [2, 0]) - +which is by scheduling the tasks with rewards 40, 20 + +This problem can be solved using the concept of "GREEDY ALGORITHM". +Time Complexity - O(n log n) + +We iterate over the tasks array once, sorting it in descending order of reward. +Then we iterate over the sorted tasks array once more, scheduling each +task if its deadline is greater than the current time.The greedy choice at +each point is to either schedule the current task if its deadline is greater +than the current time, or skip it otherwise. +""" + +class Task: + def __init__(self, id, deadline, reward): + self.id = id + self.deadline = deadline + self.reward = reward + +def max_tasks(tasks_info : list[tuple[int]]) -> int: + """ + >>> max_tasks([(4, 20), (1, 10), (1, 40), (1, 30)]) + (2, [2, 0]) + >>> max_tasks([(1, 10), (2, 20), (3, 30), (2, 40)]) + (2, [3, 2]) + """ + tasks = [Task(i, d, p) for i, (d, p) in enumerate(tasks_info)] + + tasks.sort(key=lambda task: task.reward, reverse=True) + + schedule = [] + current_time = 0 + + for task in tasks: + if task.deadline > current_time: + schedule.append(task.id) + current_time += 1 + + return len(schedule),schedule + +if __name__ == "__main__": + import doctest + doctest.testmod() + + print(max_tasks([(4, 20), (1, 10), (1, 40), (1, 30)])) From 8bc46298d36f1a12940c9c0e132717ae41b6fadb Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 15 Oct 2023 05:10:58 +0000 Subject: [PATCH 03/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- greedy_methods/job_sequence.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/greedy_methods/job_sequence.py b/greedy_methods/job_sequence.py index 2d77a9876ff4..733c8aafef61 100644 --- a/greedy_methods/job_sequence.py +++ b/greedy_methods/job_sequence.py @@ -1,32 +1,34 @@ """ Given a list of tasks, each with a deadline and reward, The maximum number of tasks that can be scheduled to maximize reward. -We can only complete one task at a time, and each task takes 1 unit -of time to complete. Once a task has passed its deadline, it can no +We can only complete one task at a time, and each task takes 1 unit +of time to complete. Once a task has passed its deadline, it can no longer be scheduled. -Example : +Example : tasks_info = [(4, 20), (1, 10), (1, 40), (1, 30)] -max_tasks will return (2, [2, 0]) - -which is by scheduling the tasks with rewards 40, 20 +max_tasks will return (2, [2, 0]) - +which is by scheduling the tasks with rewards 40, 20 This problem can be solved using the concept of "GREEDY ALGORITHM". Time Complexity - O(n log n) We iterate over the tasks array once, sorting it in descending order of reward. -Then we iterate over the sorted tasks array once more, scheduling each -task if its deadline is greater than the current time.The greedy choice at -each point is to either schedule the current task if its deadline is greater +Then we iterate over the sorted tasks array once more, scheduling each +task if its deadline is greater than the current time.The greedy choice at +each point is to either schedule the current task if its deadline is greater than the current time, or skip it otherwise. """ + class Task: def __init__(self, id, deadline, reward): self.id = id self.deadline = deadline self.reward = reward -def max_tasks(tasks_info : list[tuple[int]]) -> int: + +def max_tasks(tasks_info: list[tuple[int]]) -> int: """ >>> max_tasks([(4, 20), (1, 10), (1, 40), (1, 30)]) (2, [2, 0]) @@ -45,10 +47,12 @@ def max_tasks(tasks_info : list[tuple[int]]) -> int: schedule.append(task.id) current_time += 1 - return len(schedule),schedule + return len(schedule), schedule + if __name__ == "__main__": import doctest + doctest.testmod() - + print(max_tasks([(4, 20), (1, 10), (1, 40), (1, 30)])) From 4a20527b3e072bcd196553f83045049742d895cd Mon Sep 17 00:00:00 2001 From: kosuri-indu Date: Sun, 15 Oct 2023 10:48:01 +0530 Subject: [PATCH 04/17] to add definitions in parameters --- greedy_methods/job_sequence.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/greedy_methods/job_sequence.py b/greedy_methods/job_sequence.py index 2d77a9876ff4..300cc5cdc314 100644 --- a/greedy_methods/job_sequence.py +++ b/greedy_methods/job_sequence.py @@ -21,7 +21,7 @@ """ class Task: - def __init__(self, id, deadline, reward): + def __init__(self, id : int, deadline : int, reward : int): self.id = id self.deadline = deadline self.reward = reward From f6c1223df9728ba2f8eab94b40bde78f5d2e4ea2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 15 Oct 2023 05:19:03 +0000 Subject: [PATCH 05/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- greedy_methods/job_sequence.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/greedy_methods/job_sequence.py b/greedy_methods/job_sequence.py index 92df3f96154c..2ac3e5e384c5 100644 --- a/greedy_methods/job_sequence.py +++ b/greedy_methods/job_sequence.py @@ -22,7 +22,7 @@ class Task: - def __init__(self, id : int, deadline : int, reward : int): + def __init__(self, id: int, deadline: int, reward: int): self.id = id self.deadline = deadline self.reward = reward From 3aacb093a480bdc0b4a19567ace8a5849cd33101 Mon Sep 17 00:00:00 2001 From: kosuri-indu Date: Sun, 15 Oct 2023 10:50:04 +0530 Subject: [PATCH 06/17] to add definitions in parameters --- greedy_methods/job_sequence.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/greedy_methods/job_sequence.py b/greedy_methods/job_sequence.py index 92df3f96154c..8f8ec8494193 100644 --- a/greedy_methods/job_sequence.py +++ b/greedy_methods/job_sequence.py @@ -22,7 +22,7 @@ class Task: - def __init__(self, id : int, deadline : int, reward : int): + def __init__(self, id : int, deadline : int, reward : int) -> None: self.id = id self.deadline = deadline self.reward = reward From 7fe25bf36086a6fed25698fbff190df85aa22aa9 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 15 Oct 2023 05:21:27 +0000 Subject: [PATCH 07/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- greedy_methods/job_sequence.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/greedy_methods/job_sequence.py b/greedy_methods/job_sequence.py index 3523bace8b74..4159c3bcc401 100644 --- a/greedy_methods/job_sequence.py +++ b/greedy_methods/job_sequence.py @@ -20,12 +20,14 @@ than the current time, or skip it otherwise. """ + class Task: - def __init__(self, id : int, deadline : int, reward : int) -> None: + def __init__(self, id: int, deadline: int, reward: int) -> None: self.id = id self.deadline = deadline self.reward = reward + def max_tasks(tasks_info: list[tuple[int]]) -> int: """ >>> max_tasks([(4, 20), (1, 10), (1, 40), (1, 30)]) From c2209656bd92ab2cf8979e7aa1db3975db089fe1 Mon Sep 17 00:00:00 2001 From: kosuri-indu Date: Sun, 15 Oct 2023 10:57:22 +0530 Subject: [PATCH 08/17] to add definitions in parameters --- greedy_methods/job_sequence.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/greedy_methods/job_sequence.py b/greedy_methods/job_sequence.py index 4159c3bcc401..b8f427874775 100644 --- a/greedy_methods/job_sequence.py +++ b/greedy_methods/job_sequence.py @@ -20,10 +20,11 @@ than the current time, or skip it otherwise. """ +from typing import Any class Task: - def __init__(self, id: int, deadline: int, reward: int) -> None: - self.id = id + def __init__(self, task_id: Any, deadline: int, reward: int) -> None: + self.task_id = task_id self.deadline = deadline self.reward = reward @@ -44,7 +45,7 @@ def max_tasks(tasks_info: list[tuple[int]]) -> int: for task in tasks: if task.deadline > current_time: - schedule.append(task.id) + schedule.append(task.task_id) current_time += 1 return len(schedule), schedule From 349c3248894991eb103ecdac200452dccaac3e99 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 15 Oct 2023 05:28:03 +0000 Subject: [PATCH 09/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- greedy_methods/job_sequence.py | 1 + 1 file changed, 1 insertion(+) diff --git a/greedy_methods/job_sequence.py b/greedy_methods/job_sequence.py index b8f427874775..e3344f6b23e7 100644 --- a/greedy_methods/job_sequence.py +++ b/greedy_methods/job_sequence.py @@ -22,6 +22,7 @@ from typing import Any + class Task: def __init__(self, task_id: Any, deadline: int, reward: int) -> None: self.task_id = task_id From 58856c9c584c6c9a14d24ff37914d13c3c64486b Mon Sep 17 00:00:00 2001 From: kosuri-indu Date: Sun, 15 Oct 2023 11:14:43 +0530 Subject: [PATCH 10/17] changes as recommended --- greedy_methods/job_sequence.py | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/greedy_methods/job_sequence.py b/greedy_methods/job_sequence.py index e3344f6b23e7..e686292839bd 100644 --- a/greedy_methods/job_sequence.py +++ b/greedy_methods/job_sequence.py @@ -13,43 +13,38 @@ This problem can be solved using the concept of "GREEDY ALGORITHM". Time Complexity - O(n log n) +URL : https://www.google.com/imgres?imgurl=https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afit%3A648%2F1*fCm4EwGIm_KFvHrniNR_yw.jpeg&tbnid=YzfEiVyu7FIWQM&vet=12ahUKEwjFi5i2rPeBAxV7a2wGHbghCd8QMygCegQIARBh..i&imgrefurl=https%3A%2F%2Fmedium.com%2F%40nihardudhat2000%2Fjob-sequencing-with-deadline-17ddbb5890b5&docid=wcDisrtMy41SsM&w=648&h=328&q=job%20sequence&client=firefox-b-d&ved=2ahUKEwjFi5i2rPeBAxV7a2wGHbghCd8QMygCegQIARBh + We iterate over the tasks array once, sorting it in descending order of reward. Then we iterate over the sorted tasks array once more, scheduling each task if its deadline is greater than the current time.The greedy choice at each point is to either schedule the current task if its deadline is greater than the current time, or skip it otherwise. """ - from typing import Any +from dataclasses import dataclass - +@dataclass class Task: - def __init__(self, task_id: Any, deadline: int, reward: int) -> None: - self.task_id = task_id - self.deadline = deadline - self.reward = reward + task_id: Any + deadline: int + reward: int - -def max_tasks(tasks_info: list[tuple[int]]) -> int: +def max_tasks(tasks_info: list[tuple[int]]) -> list: """ >>> max_tasks([(4, 20), (1, 10), (1, 40), (1, 30)]) - (2, [2, 0]) + [2, 0] >>> max_tasks([(1, 10), (2, 20), (3, 30), (2, 40)]) - (2, [3, 2]) + [3, 2] + """ tasks = [Task(i, d, p) for i, (d, p) in enumerate(tasks_info)] tasks.sort(key=lambda task: task.reward, reverse=True) - schedule = [] - current_time = 0 - - for task in tasks: - if task.deadline > current_time: - schedule.append(task.task_id) - current_time += 1 + schedule = [task.task_id for current_time, task in enumerate(tasks, start=1) if task.deadline >= current_time] - return len(schedule), schedule + return schedule if __name__ == "__main__": From a036fd633ed2d64e8547cdf01bace092c9440108 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 15 Oct 2023 05:45:21 +0000 Subject: [PATCH 11/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- greedy_methods/job_sequence.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/greedy_methods/job_sequence.py b/greedy_methods/job_sequence.py index e686292839bd..91e6bcc33b24 100644 --- a/greedy_methods/job_sequence.py +++ b/greedy_methods/job_sequence.py @@ -24,12 +24,14 @@ from typing import Any from dataclasses import dataclass + @dataclass class Task: task_id: Any deadline: int reward: int + def max_tasks(tasks_info: list[tuple[int]]) -> list: """ >>> max_tasks([(4, 20), (1, 10), (1, 40), (1, 30)]) @@ -42,7 +44,11 @@ def max_tasks(tasks_info: list[tuple[int]]) -> list: tasks.sort(key=lambda task: task.reward, reverse=True) - schedule = [task.task_id for current_time, task in enumerate(tasks, start=1) if task.deadline >= current_time] + schedule = [ + task.task_id + for current_time, task in enumerate(tasks, start=1) + if task.deadline >= current_time + ] return schedule From 688fd27b62a6a2bdc161209f6ecc27b537940b49 Mon Sep 17 00:00:00 2001 From: kosuri-indu Date: Sun, 15 Oct 2023 11:15:58 +0530 Subject: [PATCH 12/17] type hint error resolved --- greedy_methods/job_sequence.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/greedy_methods/job_sequence.py b/greedy_methods/job_sequence.py index e686292839bd..2ad5561a4106 100644 --- a/greedy_methods/job_sequence.py +++ b/greedy_methods/job_sequence.py @@ -30,7 +30,7 @@ class Task: deadline: int reward: int -def max_tasks(tasks_info: list[tuple[int]]) -> list: +def max_tasks(tasks_info: list[tuple[int, int]]) -> list: """ >>> max_tasks([(4, 20), (1, 10), (1, 40), (1, 30)]) [2, 0] From 37ad1112b073a783d29d40bf712be4aa240973c2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 15 Oct 2023 05:47:35 +0000 Subject: [PATCH 13/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- greedy_methods/job_sequence.py | 1 + 1 file changed, 1 insertion(+) diff --git a/greedy_methods/job_sequence.py b/greedy_methods/job_sequence.py index 9a3d08a86fd6..df20ffe6d9c9 100644 --- a/greedy_methods/job_sequence.py +++ b/greedy_methods/job_sequence.py @@ -31,6 +31,7 @@ class Task: deadline: int reward: int + def max_tasks(tasks_info: list[tuple[int, int]]) -> list: """ >>> max_tasks([(4, 20), (1, 10), (1, 40), (1, 30)]) From 82877b3e6caebcec68ab91699c98ad59f7a8cc3e Mon Sep 17 00:00:00 2001 From: kosuri-indu Date: Sun, 15 Oct 2023 11:19:27 +0530 Subject: [PATCH 14/17] removed lambda --- greedy_methods/job_sequence.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/greedy_methods/job_sequence.py b/greedy_methods/job_sequence.py index 9a3d08a86fd6..6284144dc252 100644 --- a/greedy_methods/job_sequence.py +++ b/greedy_methods/job_sequence.py @@ -23,7 +23,7 @@ """ from typing import Any from dataclasses import dataclass - +from operator import attrgetter @dataclass class Task: @@ -41,7 +41,7 @@ def max_tasks(tasks_info: list[tuple[int, int]]) -> list: """ tasks = [Task(i, d, p) for i, (d, p) in enumerate(tasks_info)] - tasks.sort(key=lambda task: task.reward, reverse=True) + tasks.sort(key=attrgetter('reward'), reverse=True) schedule = [ task.task_id From f2ed330f8c1352b045989de63398bfad0943b4da Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 15 Oct 2023 05:50:16 +0000 Subject: [PATCH 15/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- greedy_methods/job_sequence.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/greedy_methods/job_sequence.py b/greedy_methods/job_sequence.py index 6b3a97dd33a5..43dba7fa91c3 100644 --- a/greedy_methods/job_sequence.py +++ b/greedy_methods/job_sequence.py @@ -25,6 +25,7 @@ from dataclasses import dataclass from operator import attrgetter + @dataclass class Task: task_id: Any @@ -42,7 +43,7 @@ def max_tasks(tasks_info: list[tuple[int, int]]) -> list: """ tasks = [Task(i, d, p) for i, (d, p) in enumerate(tasks_info)] - tasks.sort(key=attrgetter('reward'), reverse=True) + tasks.sort(key=attrgetter("reward"), reverse=True) schedule = [ task.task_id From 148a08d4316eb140a009d77b7edc3bc7b61895fa Mon Sep 17 00:00:00 2001 From: kosuri-indu Date: Sun, 15 Oct 2023 11:26:49 +0530 Subject: [PATCH 16/17] import stmts order --- greedy_methods/job_sequence.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/greedy_methods/job_sequence.py b/greedy_methods/job_sequence.py index 6b3a97dd33a5..4a06bc3a0abb 100644 --- a/greedy_methods/job_sequence.py +++ b/greedy_methods/job_sequence.py @@ -21,9 +21,9 @@ each point is to either schedule the current task if its deadline is greater than the current time, or skip it otherwise. """ -from typing import Any from dataclasses import dataclass from operator import attrgetter +from typing import Any @dataclass class Task: From 20f0dd0cb02a73186845b180bf3d059a3f27b257 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sun, 15 Oct 2023 12:13:42 +0200 Subject: [PATCH 17/17] Update and rename job_sequence.py to job_sequence_with_deadline.py --- greedy_methods/job_sequence.py | 62 ------------------------ scheduling/job_sequence_with_deadline.py | 62 ++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 62 deletions(-) delete mode 100644 greedy_methods/job_sequence.py create mode 100644 scheduling/job_sequence_with_deadline.py diff --git a/greedy_methods/job_sequence.py b/greedy_methods/job_sequence.py deleted file mode 100644 index 647d6a482712..000000000000 --- a/greedy_methods/job_sequence.py +++ /dev/null @@ -1,62 +0,0 @@ -""" -Given a list of tasks, each with a deadline and reward, -The maximum number of tasks that can be scheduled to maximize reward. -We can only complete one task at a time, and each task takes 1 unit -of time to complete. Once a task has passed its deadline, it can no -longer be scheduled. - -Example : -tasks_info = [(4, 20), (1, 10), (1, 40), (1, 30)] -max_tasks will return (2, [2, 0]) - -which is by scheduling the tasks with rewards 40, 20 - -This problem can be solved using the concept of "GREEDY ALGORITHM". -Time Complexity - O(n log n) - -URL : https://www.google.com/imgres?imgurl=https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afit%3A648%2F1*fCm4EwGIm_KFvHrniNR_yw.jpeg&tbnid=YzfEiVyu7FIWQM&vet=12ahUKEwjFi5i2rPeBAxV7a2wGHbghCd8QMygCegQIARBh..i&imgrefurl=https%3A%2F%2Fmedium.com%2F%40nihardudhat2000%2Fjob-sequencing-with-deadline-17ddbb5890b5&docid=wcDisrtMy41SsM&w=648&h=328&q=job%20sequence&client=firefox-b-d&ved=2ahUKEwjFi5i2rPeBAxV7a2wGHbghCd8QMygCegQIARBh - -We iterate over the tasks array once, sorting it in descending order of reward. -Then we iterate over the sorted tasks array once more, scheduling each -task if its deadline is greater than the current time.The greedy choice at -each point is to either schedule the current task if its deadline is greater -than the current time, or skip it otherwise. -""" -from dataclasses import dataclass -from operator import attrgetter -from typing import Any - - -@dataclass -class Task: - task_id: Any - deadline: int - reward: int - - -def max_tasks(tasks_info: list[tuple[int, int]]) -> list: - """ - >>> max_tasks([(4, 20), (1, 10), (1, 40), (1, 30)]) - [2, 0] - >>> max_tasks([(1, 10), (2, 20), (3, 30), (2, 40)]) - [3, 2] - - """ - tasks = [Task(i, d, p) for i, (d, p) in enumerate(tasks_info)] - - tasks.sort(key=attrgetter("reward"), reverse=True) - - schedule = [ - task.task_id - for current_time, task in enumerate(tasks, start=1) - if task.deadline >= current_time - ] - - return schedule - - -if __name__ == "__main__": - import doctest - - doctest.testmod() - - print(max_tasks([(4, 20), (1, 10), (1, 40), (1, 30)])) diff --git a/scheduling/job_sequence_with_deadline.py b/scheduling/job_sequence_with_deadline.py new file mode 100644 index 000000000000..fccb49cd88e8 --- /dev/null +++ b/scheduling/job_sequence_with_deadline.py @@ -0,0 +1,62 @@ +""" +Given a list of tasks, each with a deadline and reward, calculate which tasks can be +completed to yield the maximum reward. Each task takes one unit of time to complete, +and we can only work on one task at a time. Once a task has passed its deadline, it +can no longer be scheduled. + +Example : +tasks_info = [(4, 20), (1, 10), (1, 40), (1, 30)] +max_tasks will return (2, [2, 0]) - +Scheduling these tasks would result in a reward of 40 + 20 + +This problem can be solved using the concept of "GREEDY ALGORITHM". +Time Complexity - O(n log n) +https://medium.com/@nihardudhat2000/job-sequencing-with-deadline-17ddbb5890b5 +""" +from dataclasses import dataclass +from operator import attrgetter + + +@dataclass +class Task: + task_id: int + deadline: int + reward: int + + +def max_tasks(tasks_info: list[tuple[int, int]]) -> list[int]: + """ + Create a list of Task objects that are sorted so the highest rewards come first. + Return a list of those task ids that can be completed before i becomes too high. + >>> max_tasks([(4, 20), (1, 10), (1, 40), (1, 30)]) + [2, 0] + >>> max_tasks([(1, 10), (2, 20), (3, 30), (2, 40)]) + [3, 2] + >>> max_tasks([(9, 10)]) + [0] + >>> max_tasks([(-9, 10)]) + [] + >>> max_tasks([]) + [] + >>> max_tasks([(0, 10), (0, 20), (0, 30), (0, 40)]) + [] + >>> max_tasks([(-1, 10), (-2, 20), (-3, 30), (-4, 40)]) + [] + """ + tasks = sorted( + ( + Task(task_id, deadline, reward) + for task_id, (deadline, reward) in enumerate(tasks_info) + ), + key=attrgetter("reward"), + reverse=True, + ) + return [task.task_id for i, task in enumerate(tasks, start=1) if task.deadline >= i] + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + print(f"{max_tasks([(4, 20), (1, 10), (1, 40), (1, 30)]) = }") + print(f"{max_tasks([(1, 10), (2, 20), (3, 30), (2, 40)]) = }")