![]() |
|
|
Регистрация Восстановить пароль |
Регистрация | Задать вопрос |
Заплачу за решение |
Новые сообщения |
Сообщения за день |
Расширенный поиск |
Правила |
Всё прочитано |
![]() |
|
Опции темы | Поиск в этой теме |
![]() |
#1 |
Новичок
Джуниор
Регистрация: 26.11.2012
Сообщений: 2
|
![]()
На числовой прямой будем рассматривать только точки с целой координатой (в дальнейшем будем называть их целыми точками). Рассмотрим некоторое количество числовых промежутков, начало и конец которых являются целыми точками (предполагается, что начало и конец промежутка также входят в промежуток). С множествами чисел разрешается выполнять операции объединения, пересечения и разности:
Множество точек A+B содержит целые точки, которые принадлежат множеству A или множеству B (операция объединения). Множество точек A*B содержит целые точки, которые принадлежат одновременно и множеству A, и множеству B (операция пересечения). Множество точек A-B содержит целые точки, которые принадлежат множеству A, но не принадлежат множеству B (операция разности множеств). Задано выражение, содержащее перечисленные операции. В выражении сначала выполняются операции пересечения, после этого операции сложения и вычитания (при этом операции сложения и вычитания имеют одинаковый приоритет). Для изменения порядка выполнения действий можно использовать круглые скобки. Требуется определить множество точек (набор непересекающихся промежутков), являющееся значением заданного выражения для данных промежутков. Вход: файл input.txt, содержащий несколько строк с описанием промежутков в следующем формате: имя начало конец После описания промежутков (не более 26) в последней строке файла input.txt следует выражение, содержащие имена промежутков (только из описанного выше набора), знаки операций над промежутками (+, – и *) и круглые скобки. Прочих символов (в том числе пробелов и других разделителей) выражение не содержит. Ограничения:в описании каждого отрезка: имя – заглавная буква латинского алфавита (имя промежутка), начало и конец – целые числа от -2000000000 до 2000000000 (соответственно, начало и конец промежутка); длина выражения не превосходит 250. Выход: файл output.txt, содержащий одну или несколько строк – перечисление непересекающихся промежутков, из которых состоит результирующее множество точек (результат применения заданного выражения к предложенному набору промежутков). В каждой строке приводится два целых числа – начало и конец промежутка, разделенные пробелом. Промежутки перечисляются в порядке расположения на числовой прямой слева направо (то есть в порядке возрастания координат левых концов). Дополнительные ограничения: расстояние между соседними промежутками в выходном файле (разность между правым концом одного промежутка и левым концом другого) должно быть строго больше 1. Иначе говоря, смежные промежутки (те, между которыми нет целых точек) «сливаются» в один. Пример 1: input.txt output.txt A 1 5 B 3 7 A-B 1 2 Прошу помочь с этой задачкой, парюсь уже 5 дней, а решить никак не могу. Идеи есть, но реализация хромает. Прекрасно знаю, что строки названия промежутков и строки значений надо записать в отдельные массивы. Сделал. Знаю, что надо сперва обращать внимание на скобки, а затем на действия в них. Но как? Я вроде попытался в скобках посмотреть, но получается фигня какая-то. Буду благодарен. Мне важен сам принцип работы, как и куда писать, ибо понимание самой задачи есть. Вот само считывание и преобразование значений: Код:
________ Код нужно оформлять по правилам: тегом [CODE]..[/СODE] (это кнопочка с решёточкой #) Не забывайте об этом! Модератор. Последний раз редактировалось Serge_Bliznykov; 26.11.2012 в 20:21. |
![]() |
![]() |
![]() |
#2 |
Старожил
Регистрация: 25.10.2011
Сообщений: 3,178
|
![]()
0) В условии отсутствует важная деталь: операторы одного приоритета вычисляются либо слева направо, либо справа налево, либо в каком-то ином порядке. Будем считать, что они вычисляются справа налево.
Если игнорировать скорость, то вот вариант алгоритма: 1) Есть функция eval, которая идёт по выражению и вычисляет его, возвращая объект пользовательского типа "набор промежутков" по достижении либо конца строки, либо закрывающей скобки; в качестве побочного эффекта функция сдвигает "курсор" по выражению на конец вычисленного выражения. 2) При обнаружении открывающей скобки в качестве аргумента eval вызывает сама себя, сдвинув "курсор" на 1. Возвращённое значение есть значение аргумента в скобках; также по окончании рекурсивного вызова eval сдвигает курсор ещё раз. При обнаружении закрывающей скобки курсор сдвигается на 1 назад перед выходом. 3) При обнаружении буквы в качестве аргумента eval считает значением аргумента отрезок, соответствующий этой букве. 4) eval "накапливает" текущий результат, изначально равный пустому множеству, и возвращает его в конце своей работы. 5) При обнаружении оператора, eval определяет его приоритет. Если он больше либо равен текущему приоритету, применяется операция, соответствующая оператору, к текущему результату и результату работы функции eval с приоритетом, равным приоритету оператора. 6) Если приоритет обнаруженного оператора меньше текущего, курсор отодвигается на шаг назад и eval возвращает текущий результат. 7) Вызов eval применительно ко входному выражению с приоритетом, равным наименьшему возможному, возвращает значение этого выражения. Пример вычисления. Выражение A+B*C*(B*A-D)+С. Курсор обозначается точкой. Стек вызовов eval растёт слева направо. Для каждого вызова eval указаны приоритет и текущий результат. Знак в конце текущего результата означает, что eval прервала своё выполнение, уже "определившись" с операцией и лишь дожидаясь значения второго операнда. Код:
Последний раз редактировалось Abstraction; 26.11.2012 в 20:37. Причина: Дурацкая цветовая схема при обозначении курсора апострофом |
![]() |
![]() |
![]() |
#3 |
Новичок
Джуниор
Регистрация: 26.11.2012
Сообщений: 2
|
![]()
Спасибо за способ, но, к сожалению, время нужно не больше 6 секунд. И что-то я не замечал этой функции в паскале, буду благодарен за другие варианты.
|
![]() |
![]() |
![]() |
#4 |
Старожил
Регистрация: 25.10.2011
Сообщений: 3,178
|
![]()
М-м-м... подразумевалось, что eval напишете Вы - так, чтобы она исполняла 7 перечисленных правил.
Другие варианты подразумевают честное построение дерева синтаксического разбора и его оптимизацию (пустое множество является важным частным случаем, теоретически позволяющем обойтись без вычисления значительных подвыражений). То есть, скажем, та же eval, которая вместо вычисления выражений возвращает соответствующие им поддеревья; дальше на получившееся дерево (содержащее аргументы в символьном виде) можно натравить какой-нибудь алгоритм поиска общих подвыражений. По крайней мере, необходимо сохранять все найденные произведения и разности элементарных аргументов и, как уже сказано, пытаться выделять поддеревья, сворачивающиеся в пустое множество. В любом случае, разбор писать придётся, так что можете начать с него и проверить, медленный он или нет. |
![]() |
![]() |
![]() |
![]() |
||||
Тема | Автор | Раздел | Ответов | Последнее сообщение |
Числовая матрица | fus1on | Помощь студентам | 0 | 18.11.2010 20:00 |
числовая последовательность | Tata4ka | Помощь студентам | 5 | 01.11.2010 15:04 |
числовая последовательность | pelsh | Помощь студентам | 1 | 15.02.2008 03:20 |