Задача: Журчащие ручьи
Денис ЯстребовСложность: 5 / 10
Оригинал: https://dmoj.ca/problem/ccc00s2
Несколько ручьев сбегает по склону горы. Склон горы очень каменистый, поэтому ручьи много раз разделяются и воссоединяются. У подножия горы несколько ручьев превращаются в реки. Ваша задача - вычислить, сколько воды течет в каждой реке.
Условия и Переменные
- Сначала дается число ручьев, которые начинают течь по склону.
- Затем для каждого ручья указывается объем воды.
- В процессе потока вниз ручьи могут разделяться: один ручей делится на два (с указанием процента воды, уходящего в левый поток, а оставшаяся часть — в правый).
- Ручьи также могут сливаться: два соседних ручья объединяются в один.
- Задача завершается командой, указывающей конец входных данных.
Входные параметры
- Число N — количество ручьев в начале.
- N последующих строк — объем воды в каждом из ручьев.
- Далее идет несколько команд:
-99— сигнал разделения ручья: после него следует номер ручья и процент воды, уходящий в левый поток.
-88— сигнал объединения двух соседних ручьев: после него указывается номер первого ручья, который объединяется со следующим (правым) ручьем.
Примечание: не может быть выбран последний элемент списка 77— конец ввода.
# Пример ввода >>> 3 10 20 30 99 1 50 88 3 88 2 77
Выходные данные
Необходимо вывести конечный поток воды в каждом ручье у подножия горы. Имеется в виду не номера потоков, а объем каждого потока слева направо в виде числа округленного до ближайшего целого
# Пример вывода 5 55 >>>
Решение задачи
Прежде чем смотреть решение, потратьте как минимум 2-3 часа на самостоятельное решение и отправьте код для проверки на оригинальной странице.
def calculate_streams():
streams_count = int(input())
streams = []
for _ in range(streams_count):
volume = int(input())
streams.append(volume)
while True:
signal = int(input())
if signal == 99:
number = int(input())
percent = int(input())
position = int(number - 1)
left_stream = int(streams[position] * float(percent / 100))
streams[position] -= left_stream
streams[position:position] = [left_stream]
elif signal == 88:
number = int(input())
position = int(number - 1)
streams[position] += streams[position + 1]
streams.pop(position + 1)
else:
break
str_streams = [str(stream) for stream in streams]
print(' '.join(str_streams))
calculate_streams()
Краткая аналитика
Я бы хотел обсудить несколько моментов, которые касаются не только логики программы, но каких эстетических моментов.
- Задача требует, что бы по итогу мы вывели строку со всеми потоками. Так как в процессе нам нужно делать некоторые вычисления, мы добавляем потоки в массив как
int, а уже перед выводом преобразуем список в строку -> строка 35 - Задача требует в итоге округлить каждое значение до ближайшего целого, но для решение достаточно привести каждое итоговое значение к
int - Так как счет потоков начинается с единицы, а индексы в списках начинаются с нуля, мы вынуждены в любом случае от n отнимать 1 -
int(n - 1)
Для удобной манипуляции выражением и удобочитаемости кода присваиваю результат выраженияint(n - 1)переменнойposition. Без этого можно обойтись, но так код более понятный -> строки 19 и 28 - При разделении потока я предпочел использовать среза для добавления элемента в произвольное место списка -> строки с 21 по 23
- При объединении потока нам придется избавиться от объединяющихся значений в пользу нового значения. Мы могли бы сначала получить новое значение, затем затем удалить старые значения из списка, затем добавить новое значение в список. Но по сути можно к нужному потоку прибавить правый поток, а второй строкой удалить правый поток -> строки с 30 по 31
Good coding 🧑💻