import math import random words = [ (8, ' AAA '), (6, ' BBB '), (8, ' CCC '), (8, ' DDD '), (3, ' EEE '), (8, ' FFF '), (2, ' GGG '), ] height = 30 width = 40 middle = (20, 15) grid = [[] for x in range(height + 1)] grid[middle[1]].append((middle[0] * 2, (middle[0] * 2 + 1), 'X')) def space_available (grid, start, end, line): other_words = grid[line] for other_start, other_end, _ in other_words: if start < other_end and end > other_start: return False return True for distance, word in words: placed = False angle = random.random() * math.pi * 2 step = 0 steps = 20 while (not placed) and step < steps: x = int(round(math.cos(angle) * distance) + middle[0]) * 2 y = int(round(math.sin(angle) * distance) + middle[1]) start = x - max(0, int(math.floor(len(word) / 2))) end = start + len(word) if space_available(grid, start, end, y): grid[y].append((start, end, word)) placed = True angle += (math.pi * 2 / steps) # print(angle, x, y) print(grid) for row in grid: # Sort by first key of the tuples, start of the word row = sorted(row, key=lambda r: r[0]) if not len(row): print (width * ' ') else: line = '' for start, _, word in row: line += (start - len(line)) * ' ' + word line += (width - len(line)) * ' ' print(line)