def create_scoreboard(profiles): """Creates a scoreboard for all player profiles. :param profiles: The player profiles used add to the new scoreboard. :return: The newly created, unordered, scoreboard. """ scoreboard = Tree(lambda a, b: b - a) for name, stats in profiles: scoreboard.insert(stats.points, stats) return scoreboard
def load_season_player_scoreboard(season_stats): """Loads and sorts a player scoreboard for a given season. :param season_stats: The seasons player statistics. :return: The sorted player statistics for the given season. """ scoreboard = Tree(lambda a, b: b - a) for name, player_stats in season_stats: scoreboard.insert(player_stats.points, player_stats) return scoreboard
def pipe_vs_tree(): print('-' * 120) print('Pitting trees against pipe sort for single modification ranking.') print('The tree is expected to be faster.') print('Season ranking uses trees for this reason.') print('Pipe Sort = Uses runs then merges, average O(n log n)') print('Trees = Binary search then insertion, average O(log n)') print('-' * 120) array = [] tree = Tree() for i in range(0, 5000): value = random.randint(0, 5000) array.append(value) tree.insert(value, value) value = random.randint(0, 5000) pipe_single(array, value) tree_single(tree, value) prompt_next()
def sort(self): """Collects all runs and iteratively merges each, smallest first. :return: The sorted array. """ # Collect the final run. self._runs.insert(len(self._run), self._run) self._run = List() self.consume = self.__run_init # Iteratively merge each of the runs, smallest first. while len(self._runs) > 1: new_runs = Tree() iterator = iter(self._runs) run_a = next_run(iterator) run_b = next_run(iterator) while run_a is not None and run_b is not None: merged = self._merge(run_a, run_b) new_runs.insert(len(merged), merged) run_a = next_run(iterator) run_b = next_run(iterator) if run_a is not None: new_runs.insert(len(run_a), run_a) self._runs = new_runs sorted_run = next_run(iter(self._runs)) # Convert the run to an array if currently a linked list. if isinstance(sorted_run, List): sorted_run = sorted_run.to_array() # Return the final sorted run. return sorted_run
def list_vs_tree_vs_hash(): print('-' * 120) print( 'Pitting lists, trees and hash tables against each other for search.') print( 'Hashing is expected to be the fastest, followed by trees, then by lists.' ) print('All player statistics use hash tables for indexing.') print('Lists = Sequential search, average O(n)') print('Trees = Binary search, average O(log n)') print('Hash Tables = Hashing, average O(1)') print('-' * 120) linked_list = List() tree = Tree() hash_table = HashTable() for i in range(0, 5000): value = random.randint(0, 5000) linked_list.append(value) tree.insert(value, True) hash_table.insert(value, True) list_search(linked_list) tree_search(tree) hash_search(hash_table) prompt_next()
def tree_multiple(array): tree = Tree() for element in array: tree.insert(element, element)
class Sorter: """An optimal pipe-line sorting implementation. Attributes: _compare: How two elements should be compared. _runs: The tree of runs, sorted by their size. _run: The current run to append to. _previous: The previous element consumed by the pipe line. consume: The function pointer to however the next element should be consumed. """ def __init__(self, comparator=lambda a, b: a - b): self._compare = comparator self._runs = Tree() self._run = List() self._previous = None self.consume = self.__run_init def __run_init(self, x): """Initializes the first run. :param x: The element to append to the run. :return: None """ self._run.append(x) self._previous = x self.consume = self.__run_single def __run_single(self, x): """There should be a single element in the current run when called. This is where the sort decides whether to start appending elements to the front or the back of the current run. :param x: The element to append to the run. :return: None """ if self._compare(x, self._previous) < 0: self._run.append_front(x) self._previous = x self.consume = self.__run_back else: self._run.append(x) self._previous = x self.consume = self.__run_front def __run_front(self, x): """Continues appending to the run if still running upwards in value. Otherwise changes state to start creating reverse runs. :param x: The element to append to the run. :return: None """ if self._compare(x, self._previous) < 0: self._runs.insert(len(self._run), self._run) self._run = List() self._run.append(x) self._previous = x self.consume = self.__run_single else: self._run.append(x) self._previous = x def __run_back(self, x): """Continues appending to the front of the run if still running in reverse. Otherwise changes state to start creating forwards runs. :param x: The element to append to the run. :return: None """ if self._compare(x, self._previous) > 0: self._runs.insert(len(self._run), self._run) self._run = List() self._run.append(x) self._previous = x self.consume = self.__run_single else: self._run.append_front(x) self._previous = x def sort(self): """Collects all runs and iteratively merges each, smallest first. :return: The sorted array. """ # Collect the final run. self._runs.insert(len(self._run), self._run) self._run = List() self.consume = self.__run_init # Iteratively merge each of the runs, smallest first. while len(self._runs) > 1: new_runs = Tree() iterator = iter(self._runs) run_a = next_run(iterator) run_b = next_run(iterator) while run_a is not None and run_b is not None: merged = self._merge(run_a, run_b) new_runs.insert(len(merged), merged) run_a = next_run(iterator) run_b = next_run(iterator) if run_a is not None: new_runs.insert(len(run_a), run_a) self._runs = new_runs sorted_run = next_run(iter(self._runs)) # Convert the run to an array if currently a linked list. if isinstance(sorted_run, List): sorted_run = sorted_run.to_array() # Return the final sorted run. return sorted_run def _merge(self, run_a, run_b): """Merges two runs. :param run_a: The first run. :param run_b: The second run. :return: Both runs, A and B, merged. """ # merged = np.empty(len(run_a) + len(run_b), dtype=object) merged = [None] * (len(run_a) + len(run_b)) iterator_a = iter(run_a) iterator_b = iter(run_b) element_a = next(iterator_a, None) element_b = next(iterator_b, None) index = 0 while element_a is not None and element_b is not None: if self._compare(element_a, element_b) > 0: merged[index] = element_b element_b = next(iterator_b, None) else: merged[index] = element_a element_a = next(iterator_a, None) index += 1 while element_a is not None: merged[index] = element_a element_a = next(iterator_a, None) index += 1 while element_b is not None: merged[index] = element_b element_b = next(iterator_b, None) index += 1 return merged
def load_circuit_player_scoreboard(players): scoreboard = Tree(lambda a, b: b - a) for name, player in players: scoreboard.insert(player.stats.points, player.stats) return scoreboard