docs: def place_items_in_square(items, t):
      """
      Returns a list of rows that are stored as a priority queue to be
      used with heapq functions.
  
      >>> place_items_in_square([1,5,7], 4)
      [(2, 1, [(1, 5), (3, 7)]), (3, 0, [(1, 1)])]
      >>> place_items_in_square([1,5,7], 3)
      [(2, 0, [(1, 1)]), (2, 1, [(2, 5)]), (2, 2, [(1, 7)])]
      """
  
      # A minheap (because that's all that heapq supports :/)
      # of the length of each row. Why this is important is because
      # we'll be popping the largest rows when figuring out row displacements.
      # Each item is a tuple of (t - |row|, y, [(xpos_1, item_1), ...]).
      # Until the call to heapq.heapify(), the rows are ordered in
      # increasing row number (y).
      rows = [(t, y, []) for y in range(t)]
  
      for item in items:
          # Calculate the cell the item should fall in.
          x = item % t
          y = item // t
  
          # Push the item to its corresponding row...
          inverse_length, _, row_contents = rows[y]
          heapq.heappush(row_contents, (x, item))
  
          # Ensure the heap key is kept intact.
          rows[y] = inverse_length - 1, y, row_contents
  
      assert all(inv_len == t - len(rows) for inv_len, _, rows in rows)
  
      heapq.heapify(rows)
  
      # Return only rows that are populated.
      return [row for row in rows if row[2]]