Skip to content

Instantly share code, notes, and snippets.

@lem0n4de
Created May 4, 2019 23:00
Show Gist options
  • Select an option

  • Save lem0n4de/2649ceebdc6b975a8825a6f451545267 to your computer and use it in GitHub Desktop.

Select an option

Save lem0n4de/2649ceebdc6b975a8825a6f451545267 to your computer and use it in GitHub Desktop.
#!/bin/env python
from typing import List
class Ders:
length : int
name : str
path : str
def __init__(self, name : str, length : int, path : str = ""):
self.name = name
self.length = length
self.path = path
def __str__(self):
return f"{self.name} - {self.length} pages"
def __repr__(self):
return self.__str__()
# https://stackoverflow.com/questions/35517051/split-a-list-of-numbers-into-n-chunks-such-that-the-chunks-have-close-to-equal
def partition_list(a : List[Ders], k : int) -> List[List[Ders]]:
if k <= 1: return [a]
if k >= len(a): return [[x] for x in a]
partition_between = [(i+1)*len(a) // k for i in range(k-1)]
average_height = float(sum([item.length for item in a]))/k
best_score = None
best_partitions = None
count = 0
while True:
starts = [0] + partition_between
ends = partition_between + [len(a)]
partitions = [a[starts[i]:ends[i]] for i in range(k)]
# heights2 = [[x.length for x in l] for l in partitions]
# heights = list(map(sum, partitions))
heights = [sum([item.length for item in l]) for l in partitions]
abs_height_diffs = list(map(lambda x: abs(average_height - x), heights))
worst_partition_index = abs_height_diffs.index(max(abs_height_diffs))
worst_height_diff = average_height - heights[worst_partition_index]
if best_score is None or abs(worst_height_diff) < best_score:
best_score = abs(worst_height_diff)
best_partitions = partitions
no_improvements_count = 0
else:
no_improvements_count += 1
if worst_height_diff == 0 or no_improvements_count > 5 or count > 100:
return best_partitions
count += 1
move = -1 if worst_height_diff < 0 else 1
bound_to_move = 0 if worst_partition_index == 0\
else k-2 if worst_partition_index == k-1\
else worst_partition_index-1 if (worst_height_diff < 0) ^ (heights[worst_partition_index-1] > heights[worst_partition_index+1])\
else worst_partition_index
direction = -1 if bound_to_move < worst_partition_index else 1
partition_between[bound_to_move] += move * direction
def print_best_partition(a : List[Ders], k : int) -> None:
print('Partitioning {0} into {1} partitions'.format(a, k))
p = partition_list(a, k)
print('The best partitioning is {0}\n With heights {1}\n'.format(p, [sum([item.length for item in l]) for l in p]))
a = [1, 6, 2, 3, 4, 1, 7, 6, 4]
b = [Ders("1", 1), Ders("2", 2), Ders("3", 3), Ders("4", 4),
Ders("5", 5), Ders("6", 6)]
print_best_partition(b, 2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment