From 08746034a11989da9898ac51d7d9465c67c81709 Mon Sep 17 00:00:00 2001 From: Margaret <62753112+meg-1@users.noreply.github.com> Date: Wed, 11 Oct 2023 17:09:50 +0300 Subject: [PATCH] adding a split_workload algorithm --- sorts/split_workload.py | 72 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 sorts/split_workload.py diff --git a/sorts/split_workload.py b/sorts/split_workload.py new file mode 100644 index 000000000000..0d7eb02a1db2 --- /dev/null +++ b/sorts/split_workload.py @@ -0,0 +1,72 @@ +def split_list( + timings: list[int | float | str], +) -> tuple[list[int | float], list[int | float], int | float] | None: + """ + + This algorithm is a brute-force search over (nearly) all 2^n + possible partitions and was created for educational purposes. + the asymptotic runtime of this code is: O(n * 2^n) + + this is a case of the partition problem. + it accepts a multiset ( list ) of integers, + distributes them, and returns a tuple, containing two lists, + with minimal difference between their sums + + >>> split_list([27, 21, 92, 87, 1, 32]) + ([27, 21, 87], [92, 1, 32], 10) + >>> split_list([52, 385, 9956, 25, 2367, 1111, 17, 925]) + ([9956], [52, 385, 25, 2367, 1111, 17, 925], 5074) + >>> split_list([12, 10, 11, 9]) + ([10, 11], [12, 9], 0) + >>> split_list([-1551, 2712, 2325, 2623]) + ([1551, 2712], [2325, 2623], 685) + >>> split_list(["12.5", "10", "11", "9"]) + ([10, 11], [12.5, 9], 0.5) + >>> split_list(["twelve", "ten", "eleven", "nine"]) + Traceback (most recent call last): + ValueError: Timings must be a list of numbers + + """ + valid_timings: list[int | float] = [] + for current_element in timings: + if ( + isinstance(current_element, str) + and current_element.replace(".", "", 1).isdigit() + ): + is_current_elem_int = float(current_element).is_integer() + if not is_current_elem_int: + valid_timings.append(abs(float(current_element))) + else: + valid_timings.append(abs(int(float(current_element)))) + elif isinstance(current_element, (int, float)): + valid_timings.append(abs(current_element)) + else: + print(type(current_element)) + raise ValueError("Timings must be a list of numbers") + + if len(valid_timings) == 0: + return ([], [], 0) + elif len(valid_timings) == 1: + return ([valid_timings[0]], [], valid_timings[0]) + + result = None + n = len(valid_timings) + smallest_diff = float("inf") + for i in range(1, 2**n - 1): + indices = [j for j in range(n) if i & (1 << j) != 0] + distributed_timings_1 = [valid_timings[j] for j in indices] + distributed_timings_2 = [valid_timings[j] for j in range(n) if j not in indices] + diff = abs(sum(distributed_timings_1) - sum(distributed_timings_2)) + + if diff < smallest_diff: + smallest_diff = diff + result = ( + distributed_timings_1, + distributed_timings_2, + smallest_diff, + ) + return result + + +if __name__ == "__main__": + __import__("doctest").testmod()