from collections import defaultdict def get_short_names(names): ''' Given an iterable names, return the shortest prefix for each element so that all prefixes are different. All elements in names must be unique. >>> get_short_names(['cat', 'castor', 'could', 'fire', 'first']) ['cat', 'cas', 'co', 'fire', 'firs'] ''' lengths = {name: 1 for name in names} if len(lengths) != len(names): raise ValueError('names must only contain unique values') while True: buckets = defaultdict(list) valid = True for name in names: bucket = buckets[name[:lengths[name]]] if bucket: valid = False bucket.append(name) for bucket in buckets.values(): if len(bucket) > 1: for name in bucket: lengths[name] += 1 if valid: break return [name[:lengths[name]] for name in names] def text_width(text): return max((len(line) for line in text.split('\n')), default=0) def wrap(text, width, tabwidth=4): text = text.replace('\t', ' ' * tabwidth) if not text: yield '' return for index in range(0, len(text), width): yield text[index:index + width] def align(text, width, alignment): if alignment == '=': return text.center(width) elif alignment == '<': return text.ljust(width) elif alignment == '>': return text.rjust(width) else: raise ValueError(f'Invalid value for align {alignment}') def colorize(text, color): code = f"\033[{color}m" restore = f"\033[0m" return "".join([code, text, restore]) def wrap_align(text, width=None, alignment='<'): ''' Return value justified to the given width, either to the left if align is '<', to the right if it is '>' or centered if it is '='. ''' lines = text.split('\n') width = max(map(len, lines)) if width is None else width lines = [sub_line for line in lines for sub_line in wrap(line, width)] return '\n'.join( align(line, width=width, alignment=alignment) for line in lines) def join(columns, separator=''): widths = [len(column[0].split('\n', 1)[0]) for column in columns] joined = [] for rows in zip(*columns): rows_lines = [row.split('\n') for row in rows] height = max(map(len, rows_lines)) rows_lines = [ row_lines + [' ' * width] * (height - len(row_lines)) for row_lines, width in zip(rows_lines, widths) ] joined_row = [] for lines in zip(*rows_lines): joined_row.append(separator.join(lines)) joined.append('\n'.join(joined_row)) return joined
Memory