Kodduu Python
1.08K subscribers
311 photos
28 videos
186 links
Научись программировать на Python на интересных примерах

Самый быстрый курс https://stepik.org/a/187914
Самый нескучный курс https://stepik.org/a/185238

Во вопросам сотрудничества: @AlexErf
Download Telegram
Распродажи Stepik курсов и программ которые сгорят под бой курантов🎄Можно купить себе или подарить 🎁

1️⃣ Python: самый быстрый курс

2️⃣ Python Data Science: самый быстрый курс

👉 Junior Python Data Scientist (программа из курсов 1️⃣ и 2️⃣)

3️⃣ Python в нескучных примерах (50)

👉 Junior Python Developer and Data Scientist (программа из курсов 1️⃣, 2️⃣ и 3️⃣)

4️⃣ Топ 100 вопросов с реальных собеседований по Python (шпаргалка) 👉 бесплатный курс

5️⃣ Язык программирования BrainFuck или ВыносМозга! 👉 бесплатный курс

Подпишись 👉🏻 @KodduuPython 🤖
В Python концепция контекста реализована с помощью менеджеров контекста и ключевого слова with. Менеджеры контекста предоставляют способ работы с ресурсами (например, файлами, сетевыми соединениями или блокировками) и автоматически управляют их открытием и закрытием, даже в случае возникновения исключений.

---

### Пример: Использование менеджера контекста для работы с файлами


# Работа с файлом без менеджера контекста
file = open("example.txt", "w")
try:
file.write("Hello, World!")
finally:
file.close() # Закрываем файл вручную

# Работа с файлом через менеджер контекста
with open("example.txt", "w") as file:
file.write("Hello, World!") # Файл будет автоматически закрыт


---

### Пример: Создание собственного менеджера контекста

Для создания собственного менеджера контекста можно использовать класс с методами __enter__ и __exit__.


class MyContextManager:
def __enter__(self):
print("Входим в контекст")
return self # Можно вернуть объект, если нужно
def __exit__(self, exc_type, exc_value, traceback):
print("Выходим из контекста")
if exc_type:
print(f"Произошла ошибка: {exc_value}")
return True # Подавляет исключение, если нужно

# Используем менеджер контекста
with MyContextManager() as cm:
print("Внутри контекста")
raise ValueError("Что-то пошло не так") # Исключение будет обработано
print("Контекст завершен")


#### Результат:

Входим в контекст
Внутри контекста
Произошла ошибка: Что-то пошло не так
Выходим из контекста
Контекст завершен


---

### Пример: Менеджер контекста с использованием contextlib

Модуль contextlib предоставляет декоратор @contextmanager, упрощающий создание менеджеров контекста.


from contextlib import contextmanager

@contextmanager
def my_context():
print("Входим в контекст")
try:
yield "Ресурс" # Передаем управление блоку `with`
except Exception as e:
print(f"Произошла ошибка: {e}")
finally:
print("Выходим из контекста")

# Используем менеджер контекста
with my_context() as resource:
print(f"Используем {resource}")
raise RuntimeError("Пример ошибки")


#### Результат:

Входим в контекст
Используем Ресурс
Произошла ошибка: Пример ошибки
Выходим из контекста


---

### Пример: Контекст для блокировки ресурсов

Менеджеры контекста часто применяются для управления блокировками (например, с помощью `threading.Lock`).


import threading

lock = threading.Lock()

def critical_section():
with lock: # Блокировка автоматически освобождается после завершения блока
print(f"Поток {threading.current_thread().name} выполняет критическую секцию")

# Создание потоков
threads = [threading.Thread(target=critical_section) for _ in range(5)]

# Запуск потоков
for thread in threads:
thread.start()

for thread in threads:
thread.join()


---

### Вывод:
Контексты в Python позволяют безопасно управлять ресурсами, упрощая такие задачи, как открытие и закрытие файлов, управление соединениями или блокировками, и делают код чище и устойчивее к ошибкам.

Подпишись 👉🏻 @KodduuPython 🤖
5👍4
Работа с GPS в Python может быть выполнена с использованием модулей, таких как gpsd, pyserial или pynmea2. Эти модули позволяют подключаться к GPS-устройствам, получать данные о местоположении и разбирать их.

---

### Пример 1: Использование gpsd

gpsd — это сервер, который предоставляет данные от GPS-устройства. В Python можно использовать библиотеку gpsd-py3 для взаимодействия с gpsd.

#### Установка:

pip install gpsd-py3


#### Код:

import gpsd

# Подключаемся к gpsd
gpsd.connect()

# Получаем данные от GPS
packet = gpsd.get_current()

# Вывод информации о местоположении
if packet.mode >= 2: # Режим 2D или 3D
print(f"Широта: {packet.lat}")
print(f"Долгота: {packet.lon}")
if packet.mode == 3: # Режим 3D
print(f"Высота: {packet.alt}")
else:
print("Нет данных о местоположении")


---

### Пример 2: Использование pyserial для чтения данных NMEA

Данные от GPS-устройства часто передаются в формате NMEA (текстовый формат), который можно обработать вручную или с помощью библиотек, например, pynmea2.

#### Установка:

pip install pyserial pynmea2


#### Код:

import serial
import pynmea2

# Подключение к GPS через COM-порт (здесь используется примерный порт)
gps_port = "/dev/ttyUSB0" # Укажите порт вашего устройства
baud_rate = 9600 # Типичная скорость GPS
timeout = 5 # Тайм-аут

try:
# Открываем соединение
with serial.Serial(gps_port, baudrate=baud_rate, timeout=timeout) as ser:
print("Чтение данных от GPS...")

while True:
line = ser.readline().decode('ascii', errors='replace').strip()
if line.startswith('$GPGGA'): # Проверяем тип сообщения
msg = pynmea2.parse(line)
print(f"Широта: {msg.latitude} {msg.lat_dir}")
print(f"Долгота: {msg.longitude} {msg.lon_dir}")
print(f"Высота: {msg.altitude} {msg.altitude_units}")
except serial.SerialException as e:
print(f"Ошибка подключения к порту: {e}")
except pynmea2.ParseError as e:
print(f"Ошибка разбора NMEA данных: {e}")


---

### Пример 3: Работа с эмуляцией GPS

Для тестирования можно использовать файлы с NMEA-данными, которые эмулируют работу реального GPS. Такой подход полезен, если у вас нет физического устройства.

#### Тестовые данные (пример NMEA):

$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47


#### Код для эмуляции:

import pynmea2

# Пример NMEA-строки
nmea_data = "$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47"

# Разбор строки
try:
msg = pynmea2.parse(nmea_data)
print(f"Время: {msg.timestamp}")
print(f"Широта: {msg.latitude} {msg.lat_dir}")
print(f"Долгота: {msg.longitude} {msg.lon_dir}")
print(f"Высота: {msg.altitude} {msg.altitude_units}")
except pynmea2.ParseError as e:
print(f"Ошибка разбора NMEA данных: {e}")


---

### Вывод
Этот код демонстрирует, как получать и обрабатывать GPS-данные. В зависимости от вашего устройства и протокола взаимодействия, вы можете:
1. Использовать gpsd для высокоуровневого доступа к GPS.
2. Работать напрямую с портом через pyserial и разбирать данные в формате NMEA.
3. Эмулировать GPS-сигналы для тестирования.

Подпишись 👉🏻 @KodduuPython 🤖
👍6
Код 👆👆👆


import time
import os
import random

# Настройка размеров "экрана"
SCREEN_WIDTH = 40
SCREEN_HEIGHT = 20

# Новогодняя елка
TREE = [
" 🎄",
" 🎄🎄",
" 🎄🎄🎄",
" 🎄🎄🎄🎄",
" 🎄🎄🎄🎄🎄",
" 🎄🎄🎄🎄🎄🎄",
" 🎄🎄🎄🎄🎄🎄🎄",
" 🎄🎄🎄🎄🎄🎄🎄🎄",
" 🎄🎄🎄🎄🎄🎄🎄🎄🎄",
" ||",
" ||",
]

# Генерация начальных снежинок
snowflakes = [[random.randint(0, SCREEN_WIDTH - 1), random.randint(0, SCREEN_HEIGHT - 1)] for _ in range(50)]

# Функция рисования экрана
def draw_screen():
os.system('cls' if os.name == 'nt' else 'clear') # Очистка экрана

# Рисуем "снежный экран"
screen = [[" " for _ in range(SCREEN_WIDTH)] for _ in range(SCREEN_HEIGHT)]

# Добавляем снежинки
for flake in snowflakes:
x, y = flake
if 0 <= y < SCREEN_HEIGHT and 0 <= x < SCREEN_WIDTH:
screen[y][x] = "❄️"

# Рисуем елку
for i, line in enumerate(TREE):
if SCREEN_HEIGHT - len(TREE) + i >= 0:
screen[SCREEN_HEIGHT - len(TREE) + i][:len(line)] = line

# Вывод экрана
for row in screen:
print("".join(row))

# Главный цикл
try:
while True:
draw_screen()

# Обновляем положение снежинок
for flake in snowflakes:
flake[1] += 1 # Снежинка падает вниз
if flake[1] >= SCREEN_HEIGHT: # Перезапускаем снежинку сверху
flake[1] = 0
flake[0] = random.randint(0, SCREEN_WIDTH - 1)

# Добавляем задержку для анимации
time.sleep(0.2)

except KeyboardInterrupt:
print("\nС Новым Годом! 🎅🎁🎉")


Подпишись 👉🏻 @KodduuPython 🤖
7
This media is not supported in your browser
VIEW IN TELEGRAM
С наступающим 🎄❄️☃️ Сбычи мечт и много хорошего кода в новом 2025 году 🎁👩‍💻🧑‍💻

Подпишись 👉🏻 @KodduuPython 🤖
👍82🔥2
Не успели купить 🎁, подарите знания (любой курс можно подарить):

1️⃣ Python: самый быстрый курс

2️⃣ Python Data Science: самый быстрый курс

👉 Junior Python Data Scientist (программа из курсов 1️⃣ и 2️⃣)

3️⃣ Python в нескучных примерах (50)

👉 Junior Python Developer and Data Scientist (программа из курсов 1️⃣, 2️⃣ и 3️⃣)

4️⃣ Топ 100 вопросов с реальных собеседований по Python (шпаргалка) 👉 бесплатный курс

5️⃣ Язык программирования BrainFuck или ВыносМозга! 👉 бесплатный курс

Подпишись 👉🏻 @KodduuPython 🤖
👍41
Ниже пример простого скрипта на Python, который собирает новогоднее поздравление из случайно выбранных слов и фраз. Его можно расширять, добавлять дополнительные списки или логику по своему вкусу.


import random

def generate_new_year_greeting():
"""
Генерирует новогоднее поздравление, выбирая слова из списков случайным образом.
"""

# Приветствия/начальные фразы
starts = [
"Поздравляю",
"Сердечно поздравляю",
"От всей души приветствую",
"С огромной радостью поздравляю"
]

# Прилагательные/эпитеты
adjectives = [
"счастливого",
"волшебного",
"радостного",
"прекрасного",
"блестящего"
]

# Основные пожелания
wishes = [
"здоровья",
"удачи",
"радости",
"любви",
"тепла",
"творческих успехов",
"исполнения всех желаний"
]

# Дополнительные фразы
extras = [
"чтобы каждый день был наполнен чудесами",
"пусть все мечты сбываются",
"желаю верить в себя и покорять любые вершины",
"пусть в сердце живёт только добро",
"и пусть этот год принесёт много ярких событий"
]

# Заключительные фразы/пожелания
endings = [
"С Новым годом!",
"Пусть в этом году будет всё на высоте!",
"Пусть в новом году будет только лучше!",
"С праздником!",
"Свершений и новых побед!"
]

# Собираем предложение
greeting = (
f"{random.choice(starts)} с наступившим {random.choice(adjectives)} Новым годом!\n\n"
f"Желаю {random.choice(wishes)}, {random.choice(wishes)}, а также {random.choice(wishes)}.\n"
f"И, конечно, {random.choice(extras)}.\n\n"
f"{random.choice(endings)}"
)

return greeting

def main():
# Генерируем и выводим поздравление
print(generate_new_year_greeting())

if __name__ == "__main__":
main()


### Как это работает:
1. Списки со словами и фразами: Для разных частей поздравления (`starts`, adjectives, wishes, extras, `endings`) заведены отдельные списки.
2. Модуль `random`: При помощи random.choice выбирается по одной фразе/слову из каждого списка.
3. Сборка текста: Формируем итоговую строку (`greeting`), используя f-строки с подстановками.
4. Вывод результата: Вызов print(generate_new_year_greeting()) выдаёт нам случайное поздравление на каждом запуске.

При желании можно:
- Добавить больше слов в списки.
- Формировать более сложные конструкции предложений.
- Сохранять поздравление в файл или отправлять его по электронной почте.

Подпишись 👉🏻 @KodduuPython 🤖
👍84
Ниже приведён шуточный пример кода на Python, который «оценивает», сколько салата «Оливье» было съедено во всём мире на Новый год. Все расчёты, конечно, условны и сделаны для иллюстрации, а не на основе реальной статистики.


import random

def estimate_olivier_eaten():
"""
Возвращает приблизительное (и шуточное) количество килограммов Оливье,
которые были съедены на планете в новогоднюю ночь.
"""

# (1) Численность населения (приблизительно, в миллиардах)
world_population = 8.05 # млрд (примерно к 2024 году)

# (2) Процент людей, отмечающих Новый год
# Условно предположим, что его празднуют 80% населения
celebrating_people_percent = 0.8

# (3) Процент любителей Оливье среди тех, кто празднует
# Пусть из празднующих минимум 50% едят Оливье
olivier_lovers_percent = 0.5

# (4) Средняя порция Оливье на человека (в граммах)
# Предположим 300 г на душу – кто-то съест больше, кто-то меньше
avg_portion_per_person_grams = 300

# (5) Считаем
# Сколько людей ест Оливье
number_of_olivier_eaters = world_population * 1_000_000_000 \
* celebrating_people_percent \
* olivier_lovers_percent

# Сколько всего граммов Оливье пришлось на этих людей
total_grams_olivier = number_of_olivier_eaters * avg_portion_per_person_grams

# Переводим в килограммы
total_kilos_olivier = total_grams_olivier / 1000

return total_kilos_olivier

def main():
# Получим оценку
kilos_olivier = estimate_olivier_eaten()

# Для «дополнительной реалистичности» внесём случайный разброс ±10%
# Ведь точное число никто не знает 🙂
fluctuation_percent = random.uniform(-0.1, 0.1)
kilos_olivier *= (1 + fluctuation_percent)

# Красиво форматируем число (например, с разделением разрядов)
result_str = f"{kilos_olivier:,.0f}" # округлим до целых
print(f"По приблизительным (шуточным) оценкам, в новогоднюю ночь "
f"на планете было съедено около {result_str} кг Оливье!")

if __name__ == "__main__":
main()


### Как работает код

1. Параметры «мировой» статистики
- world_population — приблизительная численность населения Земли в миллиардах.
- celebrating_people_percent — доля тех, кто отмечает Новый год.
- olivier_lovers_percent — доля тех, кто в праздничную ночь ест Оливье (из тех, кто вообще празднует).

2. Средняя порция
В примере для простоты взято \(300\) граммов на человека. Кто-то съедает больше, кто-то меньше — но пусть будет так.

3. Вычисление
- Находим общее число людей, которые (гипотетически) ели Оливье.
- Умножаем на 300 г.
- Переводим всё это в килограммы.

4. Случайный разброс
В коде мы добавляем ±10% (переменная `fluctuation_percent`), чтобы сделать оценку ещё менее «точной» и более шутливой.

5. Вывод
В main() печатаем итоговое «псевдо-число» в красиво отформатированном виде.

---

Это, конечно, не настоящее научное исследование, а лишь пример того, как можно реализовать в Python «виртуальный счётчик» чего угодно — например, салата Оливье в новогоднюю ночь.

Подпишись 👉🏻 @KodduuPython 🤖
51
Ниже приведён упрощённый пример на Python, демонстрирующий базовые идеи, которые могли использоваться для плановых расчётов в экономике (как, например, в СССР). Он не претендует на историческую точность и полноту, но иллюстрирует общий подход к задачам планирования с применением математической оптимизации.

---

Краткое введение в задачу

Предположим, что у нас есть несколько типов ресурсов (например, металл, дерево, электроэнергия и т.д.), и мы хотим произвести несколько видов товаров (станки, мебель, автомобили и т.д.). У каждого товара есть:
1. План по выпуску (то есть минимальное количество, которое нужно произвести по указу «сверху»).
2. Потребление ресурсов на единицу выпуска (например, один автомобиль требует 1 тонну металла, 10 кВт⋅ч электроэнергии и т.п.).
3. Ограниченное количество ресурсов, доступных в нашей «народно-хозяйственной» системе.

Основная задача: найти, сколько каждого вида товара нужно произвести, чтобы:
- Выполнить (или превысить) плановые задания (заказ государства).
- Не превысить доступные объёмы ресурсов.
- Максимизировать (или минимизировать) некую целевую функцию — например, суммарную “пользу” (удовлетворение потребностей народа / вклад в экономику).

В реальном СССР и других плановых экономиках задач было в разы больше и сложнее: расчёты производились по десяткам тысяч наименований продукции, учитывалась логистика, взаимозаменяемость ресурсов, отраслевые приоритеты и т.д. В 70–80-х годах это было крайне затруднительно из-за недостатка вычислительной техники и несовершенства методов планирования, что приводило к неточностям, дефицитам и дисбалансам.

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

Сложность плановых расчётов в 70–80-х

Недостаток вычислительной техники. ЭВМ в СССР (например, «Минск», «Урал», ЕС ЭВМ) имели на порядки меньшую производительность по сравнению с современными ПК. В 70–80-е годы такие машины могли обрабатывать относительно простые и не слишком большие задачи. Полноценный учёт сотен тысяч наименований товаров и ресурсов представлял колоссальную computational-проблему.
Ручной труд экономистов и плановиков. Многие расчёты производились вручную, с помощью арифмометров, перфокарт. Часть плановых заданий корректировалась “на местах”, что приводило к искажению общей картины.
Ограничения математических моделей. Методологии линейного программирования, многокритериальной оптимизации и т. п. тогда не были развиты так широко, как сейчас. Вдобавок многие экономические и социальные факторы трудно формализовать линейной моделью.
В результате получался грубый (и часто запаздывающий) план, который вёл к дефициту одних товаров и избытку других, очередям, бартерным схемам и так далее.

Подпишись 👉🏻 @KodduuPython 🤖
## Пример кода на Python

Для решения подобных задач часто применяют библиотеки для линейного программирования (Linear Programming). Одна из популярных библиотек в Python — PuLP. Если её нет, установите командой:

pip install pulp


Ниже приведён пример задачи, где мы хотим произвести три вида продукции: A, B и C.
- Каждый вид продукции требует определённое количество ресурсов (R1 и R2).
- Есть плановый минимум по каждому товару.
- Есть ограничения на объём ресурсов.
- Мы хотим максимизировать так называемую “общественную пользу” (условный показатель важности каждого товара).

### Код


# Пример кода, иллюстрирующего подход к задаче планирования

from pulp import LpProblem, LpMaximize, LpVariable, LpInteger, lpSum, LpStatus, value

# Создаём задачу линейного программирования (ЛП)
problem = LpProblem("SovietPlan", LpMaximize)

# Объявим переменные:
# xA, xB, xC — количество единиц продукции A, B и C, которое мы собираемся произвести.
# для наглядности используем целочисленное программирование (LpInteger),
# хотя в реальности могут быть и вещественные переменные.
xA = LpVariable('xA', lowBound=0, cat=LpInteger)
xB = LpVariable('xB', lowBound=0, cat=LpInteger)
xC = LpVariable('xC', lowBound=0, cat=LpInteger)

# Плановые задания (минимальное количество, которое нужно произвести)
planA = 10
planB = 20
planC = 5

# Коэффициенты потребления ресурсов на единицу каждого товара.
# Пусть ресурс R1 (например, металл) и ресурс R2 (например, электроэнергия).
# Допустим, на производство 1 единицы A нужно 3 ед. R1 и 1 ед. R2,
# на производство 1 единицы B — 2 ед. R1 и 2 ед. R2,
# на производство 1 единицы C — 4 ед. R1 и 3 ед. R2
r1_for_A = 3
r2_for_A = 1

r1_for_B = 2
r2_for_B = 2

r1_for_C = 4
r2_for_C = 3

# Доступное количество ресурсов
R1_available = 100 # например, 100 тонн металла
R2_available = 90 # например, 90 кВт⋅ч условной электроэнергии

# "Польза" (или приоритет) от каждой единицы товара
# В реальном случае это могло бы учитывать потребности населения,
# важность для военной промышленности, экспортный потенциал и т.п.
benefitA = 5
benefitB = 4
benefitC = 6

# Целевая функция: максимизируем суммарную "пользу"
problem += (benefitA * xA + benefitB * xB + benefitC * xC), "Total_Benefit"

# Добавим ограничения

# 1. Выполнение плановых заданий
problem += xA >= planA, "Min_A"
problem += xB >= planB, "Min_B"
problem += xC >= planC, "Min_C"

# 2. Ограничение по ресурсам
problem += (r1_for_A * xA + r1_for_B * xB + r1_for_C * xC) <= R1_available, "Res_R1"
problem += (r2_for_A * xA + r2_for_B * xB + r2_for_C * xC) <= R2_available, "Res_R2"

# Решаем задачу
problem.solve()

# Вывод результатов
print(f"Статус решения: {LpStatus[problem.status]}")
print(f"Оптимальное количество продукции A (xA): {xA.varValue}")
print(f"Оптимальное количество продукции B (xB): {xB.varValue}")
print(f"Оптимальное количество продукции C (xC): {xC.varValue}")
print(f"Максимальная польза: {value(problem.objective)}")


### Интерпретация результатов

1. Статус решения может показать, что задача решена оптимально (`Optimal`) или что оптимального решения нет (если, например, требования слишком высоки и ресурсы не позволяют их удовлетворить).
2. Количество продукции (xA, xB, xC) — сколько штук каждого товара в итоге планируется выпускать.
3. Максимальная польза (value(problem.objective)) показывает значение целевой функции.

Подпишись 👉🏻 @KodduuPython 🤖
Ниже приведу пример задачи из современной практики, которая по своей структуре напоминает упрощённую модель плановой экономики, но уже в контексте цепочек поставок (Supply Chain). Это одна из наиболее распространённых и сложных задач в современной логистике и экономике. В реальных условиях такие задачи включают сотни (а то и тысячи) складов, фабрик, пунктов потребления, видов транспорта и видов продукции.

Пример:
- Есть два завода (Factory1, Factory2), на которых производятся два вида товаров (Product A и Product B).
- Есть два распределительных центра (склада) (DC1, DC2).
- Есть два региона с конечным спросом (Market1, Market2).
- Мы знаем спрос в каждом регионе по каждому товару, ограничения по мощности заводов (сколько каждого товара они могут произвести) и ёмкость складов (сколько там можно держать товаров).
- Мы хотим минимизировать совокупные затраты (произвести товар, перевезти с завода на склад, затем со склада — к конечному потребителю).

Подобная постановка задачи — задача оптимизации в цепочке поставок (supply chain optimization), которая, как и плановая задача, может вырасти до огромных масштабов и требовать значительных вычислительных ресурсов.

---

## Иллюстративный пример на Python (используем библиотеку PuLP)

> Для решения потребуется библиотека PuLP. Установить её можно командой:
>

> pip install pulp
>



from pulp import (
LpProblem, LpMinimize, LpVariable, LpStatus, lpSum, LpInteger, value
)

# ---------------------------
# 1. ДАННЫЕ ЗАДАЧИ
# ---------------------------

# Заводы (factories), Склады (distribution centers), Рынки/регионы (markets)
factories = ["Factory1", "Factory2"]
distribution_centers = ["DC1", "DC2"]
markets = ["Market1", "Market2"]
products = ["ProductA", "ProductB"]

# Производственные мощности (максимальное кол-во единиц товара,
# которое может быть выпущено на каждом заводе)
# form: capacity[завод][продукт]
capacity = {
"Factory1": {"ProductA": 100, "ProductB": 80},
"Factory2": {"ProductA": 120, "ProductB": 100}
}

# Ёмкость складов (сколько всего единиц любых товаров может храниться на складе)
# form: dc_capacity[склад]
dc_capacity = {
"DC1": 150,
"DC2": 150
}

# Спрос в регионах (сколько единиц каждого товара нужно в каждом рынке)
# form: demand[рынок][продукт]
demand = {
"Market1": {"ProductA": 60, "ProductB": 40},
"Market2": {"ProductA": 80, "ProductB": 70}
}

# Себестоимость производства (cost of production) на каждом заводе
# form: production_cost[завод][продукт]
production_cost = {
"Factory1": {"ProductA": 2.0, "ProductB": 3.0},
"Factory2": {"ProductA": 2.5, "ProductB": 2.8}
}

# Стоимость транспортировки с завода до склада (за 1 единицу товара)
# form: transport_cost_factory_dc[(завод, склад)]
transport_cost_factory_dc = {
("Factory1", "DC1"): 0.5,
("Factory1", "DC2"): 0.6,
("Factory2", "DC1"): 0.7,
("Factory2", "DC2"): 0.4
}

# Стоимость транспортировки со склада к рынку (за 1 единицу товара)
# form: transport_cost_dc_market[(склад, рынок)]
transport_cost_dc_market = {
("DC1", "Market1"): 0.3,
("DC1", "Market2"): 0.8,
("DC2", "Market1"): 0.6,
("DC2", "Market2"): 0.5
}

# ---------------------------
# 2. ПОСТАНОВКА ЗАДАЧИ
# ---------------------------
# Создадим задачу линейного программирования: минимизация общих затрат
problem = LpProblem("SupplyChainOptimization", LpMinimize)

# ---------------------------
# 3. ПЕРЕМЕННЫЕ
# ---------------------------
# Пусть:
# x_fdc[p, f, dc] = количество товара p, производимого на заводе f,
# и отправляемого на склад dc
#
# y_dcm[p, dc, m] = количество товара p, отгружаемого со склада dc на рынок m

# Объявим переменные как неотрицательные целые (или неотрицательные непрерывные — зависит от контекста)
x_fdc = {}
for p in products:
for f in factories:
for dc in distribution_centers:
x_fdc[(p, f, dc)] = LpVariable(
f"x_{p}_{f}_{dc}",
lowBound=0,
cat='Continuous'
)