2022-08-03 09:38:52
Часть перваяПодготовительные работыИтак, первое, что делаем - пишем функцию, которая (внезапно) отдаёт нам случайное булевое значение:
from random import random
def random_bool() -> bool:
return random() < 0.5
Пожалуй, на этой славной ноте и закончим подготовительные работы. Булево значение для нас будет индикатором того, закрашена ли точка на изображении или все-таки нет.
Генерация необходимых данныхВторым шагом мы непременно должны создать список из булевых значений заданного размера, который у нас будет ответственен за ряд точек в изображении:
def generate_row(
cells_count: int,
) -> List[bool]:
return [random_bool() for _ in range(cells_count)]
Не то чтоб я каждую строку кода хочу выносить в отдельную функцию, но пока мне так больше нравится. Итак, шажок номер три, чтоб немного приблизиться к величию GitHub, нам необходимо генерировать три блока с данными, а затем склеивать их. Очевидно, что мы можем написать функцию, которая будет принимать целочисленное количество рядов в сетке значений и количество точек в этих рядах. Будем ожидать, что данная функция нам будет отдавать список из списков булевых значений:
def generate_block(
width: int,
height: int,
) -> List[List[bool]]:
return [generate_row(width) for _ in range(height)]
Теперь мы можем создать левый и центральный блок. Для правого блока нам ничего нового не нужно, а достаточно просто отзеркалить левый блок.
И вот, свет увидела еще одна функция в одну строчку:
def reverse_block(
block: List[List[bool]],
) -> List[List[bool]]:
return [list(reversed(i)) for i in block]
Теперь мы можем сгенерировать все три части изображения. Вот приблизительно как-то так:
left = generate_block(width=cells_count // 2, height=cells_count)
spacer = generate_block(width=cells_count % 2, height=cells_count)
right = reverse_block(left)
Очевидно, что нам надо как-то их соединить, и для этого мы напишем вот такую функцию:
def concatenate_blocks(
left: List[List[bool]],
spacer: List[List[bool]],
right: List[List[bool]],
) -> List[List[bool]]:
result = list()
for i, left_row in enumerate(left):
right_row = right[i]
spacer_row = spacer[i]
line = [*left_row, *spacer_row, *right_row]
result.append(line)
return result
И вуаля!
def generate_data(
cells_count: int = 5,
) -> List[List[bool]]:
left = generate_block(width=cells_count // 2, height=cells_count)
spacer = generate_block(width=cells_count % 2, height=cells_count)
right = reverse_block(left)
return concatenate_blocks(left, spacer, right)
Можно запустить данную функцию и вывести результат каким-то таким образом:
>>> from pprint import pprint
>>> data = generate_data()
>>> pprint(data)
[[False, True, True, True, False],
[False, True, False, True, False],
[False, True, True, True, False],
[False, True, True, True, False],
[True, False, False, False, True]]
Запускаем и любуемся на полученный результат из пяти списков. Во время просмотра результата работы скрипта задумываемся над тем, что нам нужна была картинка, а не вот это вот все, что есть на экране, и продолжаем писать код.
Пока, в сугубо отладочных целях, напишем страшенную функцию для быстрой визуализации такого списка, один раз её прогоним и забудем её как страшный сон:
>>> def data_to_str(data: List[List[bool]]) -> str:
>>> return "\\n".join(list("".join(list(map(lambda x: "#" if x else " ", row))) for row in data))
>>> print(data)
###
# #
###
###
# #
2.3K viewsA. Shpak, 06:38