Задача: Журчащие ручьи

Задача: Журчащие ручьи

Денис Ястребов

Сложность: 5 / 10

Оригинал: https://dmoj.ca/problem/ccc00s2


Несколько ручьев сбегает по склону горы. Склон горы очень каменистый, поэтому ручьи много раз разделяются и воссоединяются. У подножия горы несколько ручьев превращаются в реки. Ваша задача - вычислить, сколько воды течет в каждой реке.

Условия и Переменные

  1. Сначала дается число ручьев, которые начинают течь по склону.
  2. Затем для каждого ручья указывается объем воды.
  3. В процессе потока вниз ручьи могут разделяться: один ручей делится на два (с указанием процента воды, уходящего в левый поток, а оставшаяся часть — в правый).
  4. Ручьи также могут сливаться: два соседних ручья объединяются в один.
  5. Задача завершается командой, указывающей конец входных данных.

Входные параметры

  1. Число N — количество ручьев в начале.
  2. N последующих строк — объем воды в каждом из ручьев.
  3. Далее идет несколько команд:

    - 99 — сигнал разделения ручья: после него следует номер ручья и процент воды, уходящий в левый поток.

    - 88 — сигнал объединения двух соседних ручьев: после него указывается номер первого ручья, который объединяется со следующим (правым) ручьем.
    Примечание:
    не может быть выбран последний элемент списка
  4. 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()


Краткая аналитика

Я бы хотел обсудить несколько моментов, которые касаются не только логики программы, но каких эстетических моментов.

  1. Задача требует, что бы по итогу мы вывели строку со всеми потоками. Так как в процессе нам нужно делать некоторые вычисления, мы добавляем потоки в массив как int, а уже перед выводом преобразуем список в строку -> строка 35
  2. Задача требует в итоге округлить каждое значение до ближайшего целого, но для решение достаточно привести каждое итоговое значение к int
  3. Так как счет потоков начинается с единицы, а индексы в списках начинаются с нуля, мы вынуждены в любом случае от n отнимать 1 - int(n - 1)
    Для удобной манипуляции выражением и удобочитаемости кода присваиваю результат выражения int(n - 1) переменной position. Без этого можно обойтись, но так код более понятный -> строки 19 и 28
  4. При разделении потока я предпочел использовать среза для добавления элемента в произвольное место списка -> строки с 21 по 23
  5. При объединении потока нам придется избавиться от объединяющихся значений в пользу нового значения. Мы могли бы сначала получить новое значение, затем затем удалить старые значения из списка, затем добавить новое значение в список. Но по сути можно к нужному потоку прибавить правый поток, а второй строкой удалить правый поток -> строки с 30 по 31

Good coding 🧑‍💻

Report Page