Основы программирования на языке Python

Содержание

Слайд 2

А на прошлом уроке было… Разбор ошибок и задания на закрепление прошедшего материала

А на прошлом уроке было…

Разбор ошибок и задания на закрепление прошедшего

материала
Слайд 3

Python Imaging Library (PIL) Возможности библиотеки: поддержка бинарных, полутоновых, индексированных, полноцветных

Python Imaging Library (PIL)

Возможности библиотеки:
поддержка бинарных, полутоновых, индексированных, полноцветных и CMYK

изображений;
поддержка форматов BMP, EPS, GIF, JPEG, PDF, PNG, PNM, TIFF и некоторых других на чтение и запись;
поддержка множества форматов (ICO, MPEG, PCX, PSD, WMF и др.) только для чтения;
преобразование изображений из одного формата в другой;
правка изображений (использование различных фильтров, масштабирование, рисование, матричные операции и т. д.);
использование библиотеки из Tkinter и PyQt.

В настоящее время актуальный модуль – pillow, модификация библиотеки PIL

Официальная страница поддержки http://www.pythonware.com/products/pil/

Слайд 4

Делаем отражения изображения Возьмем в качестве примера стандартное тестовое изображение «Лена»

Делаем отражения изображения

Возьмем в качестве примера стандартное тестовое изображение «Лена»

Вертикальное отражение

for

i in range(x // 2): for j in range(y): pixels[i, j], pixels[x - i - 1, j] \ = pixels[x - i - 1, j], pixels[i, j]
Слайд 5

Горизонтальное отражение for i in range(x): for j in range(y //

Горизонтальное отражение

for i in range(x): for j in range(y // 2):

pixels[i, j], pixels[i, y - j - 1] \ = pixels[i, y - j - 1], pixels[i, j]
Слайд 6

Отражение относительно главной диагонали for i in range(x): for j in

Отражение относительно главной диагонали

for i in range(x): for j in range(i):

pixels[i, j], pixels[j, i] \ = pixels[j, i], pixels[i, j]
Слайд 7

Отражение относительно побочной диагонали for i in range(x): for j in

Отражение относительно побочной диагонали

for i in range(x): for j in range(x

- i): pixels[j, i], pixels[x - i - 1, x - j - 1] \ = pixels[x - i - 1, x - j - 1], pixels[j, i]
Слайд 8

Напишите функцию twist_image(input_file_name, output_file_name), которая будет менять местами правую верхнюю и

Напишите функцию twist_image(input_file_name, output_file_name), которая будет менять местами правую верхнюю и

левую нижнюю четверти изображения.
Параметр input_file_name задаёт имя исходного файла, а output_file_name — имя файла, куда следует сохранить результат.

Некоторые примеры

Слайд 9

from PIL import Image def twist_image(input_file_name, output_file_name): im = Image.open(input_file_name) pixels

from PIL import Image def twist_image(input_file_name, output_file_name): im = Image.open(input_file_name) pixels =

im.load() x, y = im.size for i in range(x // 2, x): for j in range(y // 2): pixels[i, j], pixels[x - i - 1, y - j - 1] \ = pixels[x - i - 1, y - j - 1], pixels[i, j] im.save(output_file_name)
Слайд 10

А теперь будем менять местами правую нижнюю и левую верхнюю четверти изображения

А теперь будем менять местами правую нижнюю и левую верхнюю четверти

изображения
Слайд 11

from PIL import Image def twist_image(input_file_name, output_file_name): im = Image.open(input_file_name) pixels

from PIL import Image def twist_image(input_file_name, output_file_name): im = Image.open(input_file_name) pixels =

im.load() x, y = im.size for i in range(x // 2, x): for j in range(y // 2, y): pixels[i, j], pixels[x - i - 1, y - j - 1] \ = pixels[x - i - 1, y - j - 1], pixels[i, j] im.save(output_file_name)
Слайд 12

А если хочется что-нибудь самому нарисовать? Для рисования на изображении используется

А если хочется что-нибудь самому нарисовать?

Для рисования на изображении используется объект

Draw из библиотеки ImageDraw. У этого объекта есть много инструментов для создания графических примитивов: прямых, кривых, точек, прямоугольников, дуг и т.д.

new_image = Image.new('RGB', (x_size, y_size), (r, g, b))

Функция создания «холста»

Палитра

Размеры по осям x и y

Код цвета в палитре

Подробно про библиотеку ImageDraw: https://pillow.readthedocs.io/en/stable/reference/ImageDraw.html#functions

Слайд 13

draw = ImageDraw.Draw(new_image) На холсте создаем место, где будет создан рисунок

draw = ImageDraw.Draw(new_image)

На холсте создаем место, где будет создан рисунок

from PIL

import Image, ImageDraw new_image = Image.new("RGB", (100, 200), (0, 0, 0)) draw = ImageDraw.Draw(new_image) draw.line((0, 0, 100, 200), fill=(255, 0, 0), width=1) # сохраним изображением в файл формата PNG new_image.save('line.png', 'PNG')

На черном прямоугольнике размера 100*200 создать красную линию, проходящую из левого верхнего в правый нижний угол, толщиной 1

Слайд 14

На черном квадрате размерность 200* 200 разместить три квадрата размера 50*50

На черном квадрате размерность 200* 200 разместить три квадрата размера 50*50

– красный, начинающийся в левом верхнем углу, зеленый – посередине и синий, заканчивающийся в правом нижнем углу

from PIL import Image, ImageDraw new_image = Image.new("RGB", (200, 200), (0, 0, 0)) draw = ImageDraw.Draw(new_image) draw.rectangle((0, 0, 50, 50), fill=(255, 0, 0)) draw.rectangle((75, 75, 125, 125), fill=(0, 255, 0)) draw.rectangle((150, 150, 200, 200), fill=(0, 0, 255)) new_image.save('rectangle.png', 'PNG')

Слайд 15

На черном фоне нарисуем синюю вертикальную линию со сдвигом 50 от

На черном фоне нарисуем синюю вертикальную линию со сдвигом 50 от

левого края. Холст – квадрат 500*500, линия толщиной 10

from PIL import Image, ImageDraw new_image = Image.new("RGB", (500, 500), (0, 0, 0)) draw = ImageDraw.Draw(new_image) color = 0, 0, 255 draw.line((50, 0, 50, 500), fill=color, width=10) new_image.save('line.png', 'PNG')

Слайд 16

Нарисуем дугу между начальными и конечными углами, внутри данной ограничительной области

Нарисуем дугу между начальными и конечными углами, внутри данной ограничительной области

from

PIL import Image, ImageDraw new_image = Image.new("RGB", (100, 100), (0, 0, 0)) draw = ImageDraw.Draw(new_image) color = 0, 0, 255 draw.arc((10, 10, 90, 90), -45, 90, fill=color, width=10) new_image.save('arc.png', 'PNG')
Слайд 17

from PIL import Image, ImageDraw new_image = Image.new("RGB", (600, 200), (0,

from PIL import Image, ImageDraw new_image = Image.new("RGB", (600, 200), (0, 0,

0)) draw = ImageDraw.Draw(new_image) color = 255, 0, 255 draw.polygon((10, 10, 500, 150, 20, 200), fill='white', outline=color) new_image.save('poligon.png', 'PNG')

Рисуем многоугольник

Координаты вершин

Цвет фона

Цвет границы

Слайд 18

На черном квадрате размерность 200* 200 разместить три круга размера 50*50

На черном квадрате размерность 200* 200 разместить три круга размера 50*50

– красный, начинающийся в правом верхнем углу, зеленый – посередине и синий, заканчивающийся в левом нижнем углу

from PIL import Image, ImageDraw new_image = Image.new("RGB", (200, 200), (0, 0, 0)) draw = ImageDraw.Draw(new_image) draw.ellipse((150, 0, 200, 50), fill=(255, 0, 0)) draw.ellipse((75, 75, 125, 125), fill=(0, 255, 0)) draw.ellipse((0, 150, 50, 200), fill=(0, 0, 255)) new_image.save('circule.png', 'PNG')

Слайд 19

from PIL import Image, ImageDraw new_image = Image.new("RGB", (300, 300), (0,

from PIL import Image, ImageDraw new_image = Image.new("RGB", (300, 300), (0, 0,

0)) draw = ImageDraw.Draw(new_image) draw.rectangle((0, 100, 300, 200), fill=(255, 255, 255)) new_image.save('rectangle.png', 'PNG')

По середине черного квадрата размера 300*300 сделать горизонтальную полосу толщиной 100

Слайд 20

В середине предыдущего рисунка разместить красный круг from PIL import Image,

В середине предыдущего рисунка разместить красный круг

from PIL import Image, ImageDraw new_image

= Image.new("RGB", (300, 300), (0, 0, 0)) draw = ImageDraw.Draw(new_image) draw.rectangle((0, 100, 300, 200), fill=(255, 255, 255)) draw.ellipse((100, 100, 200, 200), fill=(255, 0, 0)) new_image.save('rectangle1.png', 'PNG')
Слайд 21

Шахматная доска from PIL import Image, ImageDraw Импортируем из библиотеки необходимые

Шахматная доска

from PIL import Image, ImageDraw

Импортируем из библиотеки необходимые объекты

def board(num,

size): new_image = Image.new("RGB", (num * size, num * size), (0, 0, 0)) draw = ImageDraw.Draw(new_image)

Объявим функцию, аргументы которой - количество клеток по горизонтали (и по вертикали) и размер клетки.
Внутри функции создадим новое изображение соответствующего размера, на черном фоне

Слайд 22

for x in range(num): for y in range((x + 1) %

for x in range(num): for y in range((x + 1) %

2, num, 2): draw.rectangle((x * size, y * size, (x + 1) * size - 1, (y + 1) * size - 1), fill=(255, 255, 255))

Заполняем поле белыми квадратами

Сохраняем получившееся изображение в файле

new_image.save('res.png', "PNG")

Слайд 23

Красивое имя Напишите программу, которая красиво рисует имя своего автора. Каждую

Красивое имя

Напишите программу, которая красиво рисует имя своего автора. Каждую букву

надо нарисовать с помощью графических примитивов (линий, дуг и прочее), для заливки так же необходимо использовать функции библиотеки PIL.
Главное правило – не использовать встроенные шрифты.
Сохраните полученный рисунок в файле name.png.

В качестве примера – имя «Дима»

Слайд 24

from PIL import Image, ImageDraw new_image = Image.new('RGB', (700, 300), (0,

from PIL import Image, ImageDraw new_image = Image.new('RGB', (700, 300), (0, 0,

0))

Импортируем из библиотеки необходимые элементы.
Создаем основу – черное поле размера 700 на 300

draw.rectangle((25, 0, 50, 300), 'yellow')

Желтый прямоугольник

draw.arc(((0, 0), (100, 300)), -90, 90, 'green', 25)

Зеленая дуга

Слайд 25

color = ['red', 'gray', 'magenta', 'white', 'cyan', 'blue'] for i in

color = ['red', 'gray', 'magenta', 'white', 'cyan', 'blue'] for i in range(6):

draw.rectangle((125, i * 50, 150, i * 50 + 50), color[i]) draw.rectangle((200, i * 50, 225, i * 50 + 50), color[i])

Две вертикальных палочки в букве «И». Сделаем их разного цвета

Перекладина буквы «И». Оранжевая

draw.line(((150, 300), (200, 0)), 'orange', 20)

Слайд 26

Букву «М» будем делать с помощью кружков разного цвета Для этого

Букву «М» будем делать с помощью кружков разного цвета

Для этого используем

объект эллипс -

draw.ellipse

for i in range(0, 300, 50): draw.ellipse(((250, i), (300, i + 50)), 'green') draw.ellipse(((450, i), (500, i + 50)), 'yellow')

Две вертикальных палочки в букве «M».

draw.ellipse(((300, 50), (350, 100)), 'red') draw.ellipse(((400, 50), (450, 100)), 'white') draw.ellipse(((350, 100), (400, 150)), 'blue')

Середина буквы «М»

Слайд 27

Букву «А» нарисуем с помощью трех линий draw.line(((550, 300), (650, 0)),

Букву «А» нарисуем с помощью трех линий

draw.line(((550, 300), (650, 0)), 'cyan',

20) draw.line(((650, 300), (650, 0)), 'magenta', 20) draw.line(((600, 150), (650, 150)), 'green', 20)

И сохраним получившийся результат

new_image.save('name.png')

Слайд 28

Библиотеки. Часть № 3 (графика + звук) Применение фильтров к изображению.

Библиотеки. Часть № 3 (графика + звук)

Применение фильтров к изображению.
Модуль wave

для работы со звуком
Слайд 29

Фильтры Давайте применим фильтры к нашей старой знакомой Риане. Искомое изображение

Фильтры

Давайте применим фильтры к нашей старой знакомой Риане.
Искомое изображение находится в

папке с программами и называется image.jpg
Слайд 30

Сделаем изображение черно-белым from PIL import Image im = Image.open('image.jpg') pixels

Сделаем изображение черно-белым

from PIL import Image im = Image.open('image.jpg') pixels = im.load() x,

y = im.size for i in range(x): for j in range(y): r, g, b = pixels[i, j] bw = (r + g + b) // 3 pixels[i, j] = bw, bw, bw im.save('reы.jpg')


Черно-белое изображение содержит только информацию о яркости, но не о цветах. У таких изображений все три компоненты имеют одинаковое значение, поэтому мы можем просто «размазать» суммарную яркость пикселя поровну по трём компонентам.

Слайд 31

Поменяем местами зелёный и синий каналы for i in range(x): for

Поменяем местами зелёный и синий каналы

for i in range(x): for j

in range(y): r, g, b = pixels[i, j] pixels[i, j] = r, b, g

Для значения х негативом будет 255 - x


for i in range(x): for j in range(y): r, g, b = pixels[i, j] pixels[i, j] = 255 - r, 255 - g, 255 - b

Слайд 32

Высветлить компонент Во многих графических редакторах (включая Photoshop) есть инструмент Кривые

Высветлить компонент

Во многих графических редакторах (включая Photoshop) есть инструмент Кривые (Curves).

Он позволяет задать функцию, меняющую яркость всего пикселя или отдельной компоненты в зависимости от исходной яркости. Изначально эта функция представляет собой прямую y=x.

Давайте высветлим темные участки в изображении, не трогая светлые. Для этого напишем функцию, которая работает как инструмент Curves

Слайд 33

def curve(pixel): r, g, b = pixel brightness = r +

def curve(pixel): r, g, b = pixel brightness = r +

g + b if brightness < 60: k = 60 / brightness return min(255, int(r * k ** 2)), \ min(255, int(g * k ** 2)), \ min(255, int(b * k ** 2)) else: return r, g, b

for i in range(x): for j in range(y): pixels[i, j] = curve(pixels[i, j])

Изменения в теле программы

Слайд 34

Работа со звуком. Модуль wave Фильтры можно накладывать не только на

Работа со звуком. Модуль wave

Фильтры можно накладывать не только на изображение,

но и на звуковые файлы. Для манипуляции с «сырыми», необработанными аудиоданными предназначен модуль wave.

Сырые аудиоданные представляет собой зависимость амплитуды звукового сигнала от времени. Вдоль оси абсцисс откладывается время, вдоль оси ординат — амплитуда (интенсивность, громкость) звукового сигнала.

График строится по точкам, причём вместо пар (t, y) хранятся только значения y, а ось абсцисс задана частотой дискретизации (количеством отсчетов в секунду) — как правило, она составляет 44 100 Гц.

Слайд 35

Создадим программу, которая будет разворачивать звуковой файл в обратную сторону, то

Создадим программу, которая будет разворачивать звуковой файл в обратную сторону, то

есть проигрывать задом наперед

Будем открывать два файла: исходный — source и формируемый — dest.

Слайд 36

Модуль struct позволяет паковать и извлекать несколько значений в бинарные структуры.

Модуль struct позволяет паковать и извлекать несколько значений в бинарные структуры.

Это чем-то похоже на структуры в С. В примере со звуковыми волнами значение y хранится как знаковое двухбайтное число.

Используем возможности встроенного модуля struct. Пока договоримся, что функции этого модуля могут на лету распаковывать и запаковывать данные разной природы.

Слайд 37

import wave import struct source = wave.open("in.wav", mode="rb") dest = wave.open("out.wav",

import wave import struct source = wave.open("in.wav", mode="rb") dest = wave.open("out.wav", mode="wb") dest.setparams(source.getparams()) # найдем количество

фреймов frames_count = source.getnframes() data = struct.unpack("<" + str(frames_count) + "h", source.readframes(frames_count)) # собственно, основная строка программы - переворот списка newdata = data[::-1] newframes = struct.pack("<" + str(len(newdata)) + "h", *newdata) # записываем содержимое в преобразованный файл. dest.writeframes(newframes) source.close() dest.close()
Слайд 38

Некоторые наблюдения Если убрать , например, каждый второй фрейм, то ускорим

Некоторые наблюдения

Если убрать , например, каждый второй фрейм, то ускорим произведение

вдвое. При этом частота тоже вырастет в два раза.
Если увеличить все фреймы в какое-то количество раз, то произведение станет громче, а если уменьшим — тише.
Копируя каждый фрейм 2 раза, замедлим воспроизведение и понизим частоту.

На телевидении и радио часто ускоряют видео и аудио на 5-10%: это незаметно для уха, но позволяет разместить больше рекламы в эфире.


Слайд 39

Библиотеки Python. Numpy. Часть 3 Клеточные автоматы

Библиотеки Python. Numpy. Часть 3

Клеточные автоматы

Слайд 40

Клеточные автоматы. Игра «Жизнь» Клеточный автомат — это модель однородного пространства

Клеточные автоматы. Игра «Жизнь»

Клеточный автомат — это модель однородного пространства с

некоторыми клетками. Каждая клетка может находиться в одном из нескольких состояний и иметь некоторое количество соседей. Задаются правила перехода из одного состояния в другое в зависимости от текущего состояния клетки и её соседей

Каждая клетка имеет 8 соседей (сверху, снизу, справа, слева и по диагонали). Клетка может иметь два состояния: живая (на клетке стоит фишка) и мёртвая (фишки нет).

Пространство «Жизни» — бесконечное поле клеток.

В 1970 году Джон Конвей придумал игру «Жизнь» («Genesis»), основанную на клеточном автомате, ставшую довольно популярной и повлиявшую на назвитие многих точных наук.

Джон Хортон Конвей
(род. 26 декабря 1937)

Слайд 41

Правила Если клетка была живой, то она выживет, если у неё

Правила

Если клетка была живой, то она выживет, если у неё 2

или 3 соседа. Если соседей 4, 5, 6, 7 или 8, то она умирает от перенаселённости, а если 0 или 1 — то от одиночества.
Новая клетка рождается в поле, у которого есть ровно 3 соседа.

Время дискретно и считается поколениями.
Всё начинается с начальной расстановки фишек (0 поколение), в дальнейшем рассматривается эволюция клеточного пространства в 1, 2, 3 и т. д. поколении.
Процессы смерти и рождения происходят одновременно, после чего строится следующее поколение.

Игра прекращается, если:
на поле не останется ни одной «живой» клетки;
конфигурация на очередном шаге в точности (без сдвигов и поворотов) повторит себя же на одном из более ранних шагов (складывается периодическая конфигурация);
при очередном шаге ни одна из клеток не меняет своего состояния (складывается стабильная конфигурация: предыдущее правило, вырожденное до одного шага назад)

Слайд 42

Программируем игру «Жизнь» import numpy as np population = np.array( [[0,

Программируем игру «Жизнь»

import numpy as np population = np.array( [[0, 0, 0,

0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 1, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=np.uint8)

Заданим поле 10 x 10, в центр которого поместим конструкцию, известную как «глайдер»

Поле имеет тип uint8, чтобы оно занимало меньше памяти. Каждый его элемент занимает ровно 1 байт (8 бит) и является целым беззнаковым (unsigned) числом в диапазоне от 0 до 255.

Живые клетки обозначаются единицей, а мёртвые — нулём.

Слайд 43

Невозможно обеспечить бесконечность в обоих направлениях, поэтому замкнём поле само на

Невозможно обеспечить бесконечность в обоих направлениях, поэтому замкнём поле само

на себя. Если выйти за нижнюю границу, мы окажемся наверху, а если за правую — появимся слева, и наоборот. Получается что-то вроде глобуса.
Слайд 44

[[0 0 0 0 0 0 0 0 0 0] [0

[[0 0 0 0 0 0 0 0 0 0]
[0

0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 1 0 0 0 0 0]
[0 0 0 0 0 1 0 0 0 0]
[0 0 0 1 1 1 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]]

[[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 1 0 0 0 0 0]
[0 0 0 0 0 1 0 0 0 0]
[0 0 0 1 1 1 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]]

new_generation = np.roll(population, 2, 0)

Например, вот так можно сдвинуть исходный массив на две строки вниз

Было

Стало

Слайд 45

[[0 0 0 0 0 0 0 0 0 0] [0

[[0 0 0 0 0 0 0 0 0 0]
[0

0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 1 0 0 0 0 0]
[0 0 0 0 0 1 0 0 0 0]
[0 0 0 1 1 1 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]]

new_generation = np.roll(population, 2, 1)

Было

Стало

[[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 1 0 0 0]
[0 0 0 0 0 0 0 1 0 0]
[0 0 0 0 0 1 1 1 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]]

Правильно, на два столбца вправо


Слайд 46

Можем посчитать количество соседей у каждой клетки, просто сделав 8 копий

Можем посчитать количество соседей у каждой клетки, просто сделав 8 копий

со сдвигом массива и просуммировав их

neighbors = sum([ np.roll(np.roll(population, -1, 1), 1, 0), np.roll(np.roll(population, 1, 1), -1, 0), np.roll(np.roll(population, 1, 1), 1, 0), np.roll(np.roll(population, -1, 1), -1, 0), np.roll(population, 1, 1), np.roll(population, -1, 1), np.roll(population, 1, 0), np.roll(population, -1, 0) ])

[[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 1 1 1 0 0 0 0]
[0 0 0 1 1 2 1 0 0 0]
[0 0 1 3 5 3 2 0 0 0]
[0 0 1 1 3 2 2 0 0 0]
[0 0 1 2 3 2 1 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]]

Матрица соседей

Слайд 47

Генерируем новую популяцию Выполним на матрице следующую операцию: «если у клетки

Генерируем новую популяцию

Выполним на матрице следующую операцию: «если у клетки 3

соседа, то в следующем поколении на этом месте будет клетка; а если 2 соседа, то клетка будет при условии, что она была "жива" в текущем поколении».
Для этого воспользуемся операторами | (или) и & (и).

[[False False False False False False False False False False]
[False False False False False False False False False False]
[False False False False False False False False False False]
[False False False False False False False False False False]
[False False False True False True False False False False]
[False False False False True False False False False False]
[False False False False True False False False False False]
[False False False False False False False False False False]
[False False False False False False False False False False]
[False False False False False False False False False False]]

neighbors == 3

Имеется три соседа

Слайд 48

Была жизнь и имеется ровно два соседа population & (neighbors ==

Была жизнь и имеется ровно два соседа

population & (neighbors == 2)

[[0

0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 1 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]]
Слайд 49

population = (neighbors == 3) | (population & (neighbors == 2))

population = (neighbors == 3) | (population & (neighbors == 2))

Объединим

эти два условия

[[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 1 0 1 0 0 0 0]
[0 0 0 0 1 1 0 0 0 0]
[0 0 0 0 1 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]]

Слайд 50

Проследим эволюцию глайдера на протяжении 4 поколений. Для этого создадим функцию

Проследим эволюцию глайдера на протяжении 4 поколений. Для этого создадим функцию

next_population()

def next_population(population): neighbors = sum([ np.roll(np.roll(population, -1, 1), 1, 0), np.roll(np.roll(population, 1, 1), -1, 0), np.roll(np.roll(population, 1, 1), 1, 0), np.roll(np.roll(population, -1, 1), -1, 0), np.roll(population, 1, 1), np.roll(population, -1, 1), np.roll(population, 1, 0), np.roll(population, -1, 0) ]) return (neighbors == 3) | (population & (neighbors == 2))

for _ in range(4): print(population, '\n') population = next_population(population)

Слайд 51

[[0 0 0 0 0 0 0 0 0 0] [0

[[0 0 0 0 0 0 0 0 0 0]
[0

0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 1 0 0 0 0 0]
[0 0 0 0 0 1 0 0 0 0]
[0 0 0 1 1 1 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]]

[[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 1 0 1 0 0 0 0]
[0 0 0 0 1 1 0 0 0 0]
[0 0 0 0 1 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]]

[[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 1 0 0 0 0]
[0 0 0 1 0 1 0 0 0 0]
[0 0 0 0 1 1 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]]

[[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 1 0 0 0 0 0]
[0 0 0 0 0 1 1 0 0 0]
[0 0 0 0 1 1 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]]

Глайдер «летит»: каждые четыре поколения он сдвигается вниз и вправо. Иными словами, он движется в правый нижний угол

Слайд 52

Задание numpy. Одномерный клеточный автомат Ограничение времени 100 секунд Ограничение памяти

Задание numpy. Одномерный клеточный автомат

Ограничение времени 100 секунд
Ограничение памяти 64Mb
Ввод стандартный ввод или input.txt
Вывод стандартный

вывод или output.txt

На рисунке показано несколько поколений одномерного клеточного автомата. У каждой клетки только два соседа — слева и справа, а поле представляет собой бесконечную полосу клеток (правый сосед последней клетки – это первая клетка, а левый сосед первой клетки – последняя). Эволюция идёт сверху вниз: первое поколение приведено в верхней строчке, второе — во второй сверху и т.д.

Слайд 53

Правило эволюции дано в верхней части рисунка. Цвет каждой ячейки текущего

Правило эволюции дано в верхней части рисунка. Цвет каждой ячейки текущего

поколения определяется сочетанием цветов трёх соседних ячеек предыдущего поколения, расположенных над ней: непосредственно сверху и по диагоналям (сверху-слева и сверху-справа).
Всего возможны восемь разных «триплетов», порождающих в следующем поколении либо закрашенную ячейку (1), либо пустую (0). Это дает 256 возможных правил эволюции. В этой задаче используется правило номер 30.
Используя библиотеку numpy, напишите функцию generation(line), которая вычисляет и возвращает десятое поколение клеточного автомата по правилу 30.
Слайд 54

Подсказка import numpy as np Импортируем библиотеку под псевдонимом np rules

Подсказка

import numpy as np

Импортируем библиотеку под псевдонимом np

rules = { (0,

0, 0): 0, (0, 0, 1): 1, (0, 1, 0): 1, (0, 1, 1): 1, (1, 0, 0): 1, (1, 0, 1): 0, (1, 1, 0): 0, (1, 1, 1): 0, }

Правила клеточного автомата оформим в виде словаря. Ключом будет кортеж, состоящий из клеток - соседей предыдущего поколения, элементом – текущее состояние клетки. 0 – белая клетка, 1 – черная.

Слайд 55

def generation(line): Собственно напишем функцию s = np.array([int(i) for i in

def generation(line):

Собственно напишем функцию

s = np.array([int(i) for i in line]) size =

len(s)

На вход функции подается строчка, которую надо преобразовать в массив целых чисел.
Определим длину массива

for i in range(10):

Нам нужно десятое поколение клеточного автомата, поэтому вычисления повторятся в цикле соответствующее число раз