---
# System prepended metadata

title: OOPCreat5

---

# OOPCreat5

Реализовать иерархию классов, определяющих два вида элементов управления (controls): кнопки (buttons) и метки (labels). 

Абстрактные классы AbstractButton и AbstractLabel содержат метод GetControl, возвращающий строковое представление соответствующего элемента управления. Конкретные классы Button1, Button2, Label1, Label2 включают конструктор со строковым параметром text, который определяет текст, отображаемый на элементе управления (текст хранится в поле text). 

Конкретные классы отличаются видом строкового представления:

 - Для Button1 и Label1 (первый тип представления) текст отображается заглавными буквами, кнопки обрамляются квадратными скобками (например, \[CAPTION]), метки обрамляются символами = (например, =MESSAGE=).

 - Для Button2 и Label2 (второй тип представления) текст отображается строчными (маленькими) буквами, кнопки обрамляются угловыми скобками (например, \<caption>), метки обрамляются двойными кавычками (например, "message").

Реализовать иерархию классов ControlFactory (абстрактная фабрика), Factory1 и Factory2 (конкретные фабрики). Каждый класс содержит два метода: CreateButton(text) и CreateLabel(text). Для ControlFactory эти методы являются абстрактными, для конкретных фабрик они возвращают кнопку и метку соответствующего типа (первого или второго соответственно).

Также реализовать класс Client, предназначенный для формирования набора элементов управления.

 - Конструктор данного класса принимает параметр f типа ControlFactory, который в дальнейшем используется для генерации элементов управления требуемого типа.
 - Класс Client включает метод AddButton(text) для добавления в набор новой кнопки, метод AddLabel(text) для добавления в набор новой метки и метод GetControls, возвращающий текстовое представление полученного набора элементов управления.
 - В текстовом представлении каждый последующий элемент отделяется от предыдущего одним пробелом.

Дано целое число N (≤ 6) и набор из N строк. Каждая строка начинается либо с символа B (признак кнопки), либо с символа L (признак метки). Затем идет пробел и текст соответствующего элемента управления. Используя два экземпляра класса Client, сформировать и вывести два варианта текстового представления указанного набора элементов управления. Вначале выводится представление первого типа, затем второго.
    
# OOPCreat10

Реализовать систему классов, позволяющую по строковым описаниям генерировать идентификаторы, которые удовлетворяют соглашениям различных языков программирования. 

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

Абстрактный класс Builder содержит:
 - Методы для конструирования 
     - первого символа идентификатора (BuildStart)
     - первого символа каждого последующего слова (BuildFirstChar)
     - последующих символов слов (BuildNextChar)
     - символов-разделителей между словами (BuildFirstSpace).
 - Методы BuildStart, BuildFirstChar и BuildNextChar имеют символьный параметр, используемый при конструировании (возможно, после изменения его регистра);
 - метод BuildFirstSpace не имеет параметров. Все эти методы не возвращают значений; 
 - в классе Builder они не выполняют никаких действий. Кроме того, класс Builder содержит абстрактный метод GetResult без параметров, возвращающий строковое значение.

Конкретные классы BuilderPascal, BuilderPython, BuilderC содержат строковое поле product, которое инициализируется пустой строкой в конструкторе, обновляется в методе BuildStart и дополняется в методах BuildFirstChar, BuildNextChar и, возможно, в методе BuildFirstSpace. Метод GetResult возвращает значение поля product. При определении остальных методов конкретных строителей следует учитывать правила формирования идентификаторов для конкретных языков программирования:

 - для языка Pascal идентификатор должен начинаться со строчной (маленькой) буквы, последующие слова — с заглавной буквы, все прочие буквы являются строчными, пробелы игнорируются;

 - для языка Python все буквы являются строчными, а между словами добавляется символ подчеркивания;

 - для языка С все буквы являются строчными, а пробелы игнорируются.

Из перечисленных правил следует, в частности, что для классов BuilderPascal и BuilderC не требуется переопределять метод BuildFirstSpace.

Также определить класс Director, содержащий 
 - ссылочное поле b типа Builder (поле b инициализируется в конструкторе с использованием параметра конструктора того же типа)
 - и два метода: Construct(templat) и GetResult. 
     - Метод GetResult не имеет параметров и возвращает значение метода GetResult объекта b. 
     - Метод Construct обеспечивает построение продукта; его строковый параметр templat содержит строковое описание, на основании которого должен конструироваться идентификатор по правилам, реализованным в строителе b. В начале работы метод Construct должен вызвать метод BuildStart с параметром — первым символом строки templat. При анализе строки templat необходимо различать первый пробел в последовательности пробелов (для которого надо вызывать метод BuildFirstSpace) и последующие пробелы (которые должны игнорироваться).

Даны пять строк, содержащих строковые описания, которые удовлетворяют условиям, перечисленным в начале формулировки задания. Создать три объекта-распорядителя Director, связанных со строителями BuilderPascal, BuilderPython, BuilderC. Используя методы Construct и GetResult каждого из созданных распорядителей, получить по каждой из исходных строк идентификаторы на языке Pascal, Python и C и вывести их в указанном порядке (вначале выводятся идентификаторы, полученные на основе первой строки, затем на основе второй и т. д.).

# OOP2Struc6

 Реализовать иерархию классов, включающую 
 - абстрактный класс Device (устройство) с методами Add, GetName и GetTotalPrice 
 - конкретные классы SimpleDevice (простое устройство) и CompoundDevice (составное устройство).


 - Метод Add с параметром-ссылкой d типа Device добавляет устройство d в набор дочерних устройств (имеет смысл только для класса CompoundDevice; для класса SimpleDevice не выполняет никаких действий)
 - метод GetName возвращает строковое имя данного устройства
 - метод GetTotalPrice возвращает стоимость данного устройства и всех его потомков (целое число).
 - В классе Device метод Add не выполняет никаких действий
 -  методы GetName и GetTotalPrice являются абстрактными.

Классы SimpleDevice и CompoundDevice содержат
 - строковое поле name
 - целочисленное поле price

класс CompoundDevice хранит свои дочерние устройства в виде массива или другой структуры с элементами-ссылками типа Device (можно считать, что любой объект типа CompoundDevice содержит не более 15 дочерних устройств).

Конструктор классов SimpleDevice и CompoundDevice содержит два параметра: строку name и целое число price.

Дано целое число N (≤ 15) и N пар вида (name, price), где name — некоторая строка, а price — положительное целое число. Первый символ строки name является латинской буквой; если буква заглавная, то строка определяет составное устройство, а если строчная — то простое устройство. Кроме того, дан набор из N целых чисел, определяющих связи между исходными устройствами: число с индексом K (K = 0, …, N − 1) определяет индекс родительского устройства для исходного устройства с индексом K (при этом гарантируется, что родительское устройство обязательно имеет тип CompoundDevice). Если устройство не имеет родителя, то соответствующий элемент в исходном наборе чисел равен −1. Перебирая созданные устройства в порядке, соответствующем порядку их характеристик (name, price) и используя методы GetName и GetTotalPrice, вывести для каждого устройства название и полную стоимость.

# OOP2Stuc8

Реализовать иерархию классов, включающую абстрактный класс Function с абстрактными методами 
 - GetName (без параметров; возвращает строку) и 
 - GetValue(x) (с целочисленным параметром; возвращает целое число)

пять конкретных классов — потомков Function: 
 - FX
 - FDouble
 - FTriple
 - FSquare
 - FCube.

Класс FX не имеет полей; его метод GetName возвращает строку «X», а функция GetValue(x) возвращает свой параметр x.

Остальные конкретные классы являются декораторами;

все они содержат ссылочное поле f типа Function и конструктор с параметром-ссылкой f типа Function, который инициализирует это поле.

Метод GetName данных классов вызывает метод GetName класса f и возвращает его результат, снабженный дополнительным префиксом и суффиксом: 
 - «2*(» и «)» для FDouble
 - «3*(» и «)» для FTriple
 - «(» и «)^2» для FSquare
 - «(» и «)^3» для FCube.
 
Метод GetValue(x) данных классов вызывает метод GetValue(x) класса f и возвращает его результат, преобразованный следующим образом: 
 - результат умножается на 2 для FDouble
 - умножается на 3 для FTriple
 - возводится к квадрат для FSquare
 - возводится в куб для FCube.

Дано целое число N (≤ 10) и набор из N строк; каждая строка содержит комбинацию из букв «D», «T», «S» и «C» и может быть пустой. Кроме того, даны два целых числа X1 и X2. Создать набор из N объектов типа Function, формируя каждый элемент следующим образом: вначале создать объект типа FX, а затем последовательно применять к результирующему объекту декораторы FDouble, FTriple, FSquare, FCube, причем количество и порядок декораторов определяется символами соответствующей строки из исходного набора (например, в случае строки «TCSS» к исходному объекту типа FX надо последовательно применить декораторы FTriple, FCube и два декоратора FSquare). Перебирая созданный набор из N объектов в исходном порядке, вызвать для каждого из них методы GetName, GetValue(X1) и GetValue(X2) и вывести их возвращаемые значения.

# OOP3Behav2

Реализовать вариант взаимодействия субъектов и наблюдателей, не требующий специальных методов доступа к состоянию субъекта и упрощающий взаимодействие наблюдателя с несколькими субъектами.

Первая иерархия классов включает абстрактный класс Subject с абстрактными методами 
 - Attach(observ)
 - Detach(observ)
 - SetInfo(info)
класс-потомок ConcreteSubject.

Методы Attach и Detach имеют параметр-ссылку типа Observer и не возвращают значений.

Метод SetInfo имеет строковый параметр и также не возвращает значения.

В классе ConcreteSubject дополнительно описать поле observers — структуру с элементами-ссылками типа Observer, в которой хранятся все наблюдатели, присоединенные в настоящий момент к субъекту (можно считать, что наблюдателей не более 10).

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

 - Метод Attach(observ) добавляет объект observ в структуру observers
 - метод Detach(observ) удаляет объект observ из данной структуры. 
 - В методе SetInfo(info) выполняется перебор элементов структуры observers и для каждого элемента этой структуры вызывается его метод OnInfo(sender, info), 
     - причем в качестве параметра info указывается параметр метода SetInfo
     - в качестве параметра sender — ссылка на объект ConcreteSubject, вызвавший метод SetInfo. 
   Таким образом, наблюдатель сразу информируется и о наступившем событии, и о субъекте, который инициировал это событие. При реализации метода SetInfo необходимо учесть ситуацию, когда некоторые наблюдатели в своем методе OnInfo отсоединятся от субъекта, что приведет к изменению структуры observers.

Вторая иерархия включает 
 - абстрактный класс Observer с абстрактным методом 
     - OnInfo(sender, info)
 - класс-потомок ConcreteObserver.

     - Параметр sender метода OnInfo является ссылкой на объект типа Subject
     - параметр info — строковый.

 - Класс ConcreteObserver дополнительно имеет 
     - строковое поле log 
     - символьное поле detachInfo
   а также методы 
     - Attach
     - Detach
     - GetLog.

    Конструктор класса ConcreteObserver имеет 
     - параметр detachInfo, который инициализирует соответствующее поле
     - поле log инициализируется пустой строкой
     - Методы Attach(subj) и Detach(subj) имеют параметр-ссылку типа Subject и не возвращают значений
         - В методе Attach выполняется вызов метода Attach объекта subj
         - в методе Detach выполняется вызов метода Detach объекта subj, причем в качестве параметра в обоих вызываемых методах передается ссылка на объект ConcreteObserver, из которого вызваны эти методы. Метод GetLog не имеет параметров и возвращает значение поля log.

    Метод OnInfo(sender, info), переопределяемый в классе ConcreteObserver, является основным методом, обеспечивающим взаимодействие между конкретным субъектом и конкретным наблюдателем.
    
    Напомним, что этот метод вызывается конкретным субъектом для информирования всех присоединенных к нему в настоящий момент наблюдателей
     - причем информация передается в поле info
     - поле sender содержит ссылку на субъект, передавший эту информацию. 
     - В данном задании в методе OnInfo надо выполнить следующие действия: 
         - добавить содержимое параметра info в конец строки log объекта ConcreteObserver, для которого был вызван метод OnInfo
         - и, кроме того, если последний символ строки info совпадает со значением поля detachInfo объекта ConcreteObserver, то необходимо отсоединить этого наблюдателя от субъекта sender, вызвав метод Detach объекта ConcreteObserver с параметром sender.

Дано целое число N (≤ 10). Кроме того, дано целое число K (≤ 30) и набор различных двухсимвольных строк, первым символом которых является цифра «1» или «2», а вторым — строчная латинская буква. Создать два объекта subj1 и subj2 типа ConcreteSubject и набор observers из N объектов типа ConcreteObserver, указывая в качестве параметра detachInfo конструктора объектов ConcreteObserver строчные латинские буквы, которые перебираются в алфавитном порядке («a» для первого объекта ConcreteObserver, «b» для второго объекта и т. д.). Для каждого объекта ConcreteObserver вызвать методы Attach с параметрами-ссылками на объекты subj1 и subj2. Затем для каждой строки из данного набора строк вызвать метод SetInfo SetInfo объекта subj1 или subj2, передав эту строку в качестве параметра, причем если строка начинается с цифры «1», то метод SetInfo должен вызываться для объекта subj1, а если с цифры «2», то для объекта subj2. После обработки всех строк из исходного набора вывести значения полей log объектов из набора observ, используя метод GetLog класса ConcreteObserver (выведенные строки должны содержать все данные, переданные наблюдателям субъектами subj1 и subj2, вплоть до тех данных, которые вызвали отсоединение наблюдателя от соответствующего субъекта).

Примечание. Описанный вариант взаимодействия субъектов и наблюдателей можно реализовать с помощью делегаты и события (см. примечание к заданию OOP3Behav1).

# OOP3Behav4

Реализовать иерархию классов-валидаторов, включающую
 - класс Validator
 - его классы-потомки EmptyValidator, NumberValidator и RangeValidator.
 
Классы-валидаторы предназначены для проверки правильности введенных строковых данных.
 - Классы Validator, EmptyValidator и NumberValidator не имеют полей, их конструкторы не имеют параметров и не выполняют дополнительных действий. 

В классе Validator определен метод Validate(s), имеющий строковый параметр s и возвращающий строку с описанием ошибки, обнаруженной в строке s. 
 - Метод Validate класса Validator всегда возвращает пустую строку; таким образом, класс Validator считает допустимой любую строку.
 - Для класса EmptyValidator метод Validate(s) возвращает пустую строку, если параметр s не является пустой строкой; в противном случае он возвращает строку «!Empty text».
 - Для класса NumberValidator метод Validate(s) возвращает пустую строку, если параметр s содержит строковое представление некоторого целого числа; в противном случае он возвращает строку вида «!'\<s>': not a number», где в позиции \<s> указывается содержимое параметра s.

 - Класс RangeValidator содержит целочисленные поля min и max; 
    - его конструктор имеет целочисленные параметры a и b, инициализирующие поля таким образом, чтобы поле min было равно минимальному из чисел a и b, а поле max — максимальному из этих чисел.
   Для класса RangeValidator метод Validate(s) возвращает пустую строку, если параметр s содержит строковое представление некоторого целого числа и при этом данное число лежит в диапазоне от min до max включительно; в противном случае метод возвращает строку вида «!'\<s>': not in range \<min>..\<max>», где в позиции \<s> указывается содержимое параметра s, а в позициях \<min> и \<max> — значения соответствующих полей.

Реализовать класс TextBox, содержащий 
 - строковое поле text 
 - поле v — ссылку на объект типа Validator.

Конструктор класса не имеет параметров, 
 - в нем создается объект типа Validator и ссылка на него присваивается полю v, 
 - поле text инициализируется пустой строкой.

Класс TextBox включает три метода: 
 - SetText(text) — задает или изменяет поле text
 - SetValidator(v) — изменяет поле v
 - Validate (без параметров) — вызывает для объекта v метод Validate с параметром text и возвращает значение, возвращенное этим методом.

Также реализовать класс TextForm. Он содержит 
 - набор tb элементов типа TextBox (можно использовать массив или другую структуру данных).
Конструктор класса TextForm 
 - имеет параметр n, определяющий размер набора tb (можно считать, что параметр n не превосходит 10)
 - в конструкторе создаются все элементы набора tb.

Класс TextForm включает три метода: 
 - SetText(ind, text) — задает или изменяет поле text для элемента набора tb с индексом ind
 - SetValidator(ind, v) — изменяет поле v для элемента набора tb с индексом ind
 - Validate (без параметров) — последовательно вызывает методы Validate для всех элементов набора tb и возвращает строку, полученную объединением строк, возвращенных этими методами.

При реализации методов SetText и SetValidator можно считать, что параметр ind всегда лежит в допустимом диапазоне (от 0 до n − 1, где n — размер набора tb).

Даны 
 - три целых числа N, A, B, причем N лежит в диапазоне от 1 до 10
 - целое число K, не превосходящее N
 - набор из K пар (ind, val), где ind является целым числом в диапазоне от 0 до N − 1, а val является одним из символов «E», «N», «R». Все значения ind являются различными.
 - Кроме того, дано пять наборов строк, каждый из которых содержит по N элементов.

Создать объект tf типа TextForm, вызвав его конструктор с параметром N.

Для каждой пары (ind, val) вызвать метод SetValidator объекта tf с первым параметром ind и вторым параметром — ссылкой на объект-валидатор, тип которого соответствует символу val: «E» — EmptyValidator, «N» — NumberValidator, «R» — RangeValidator; 

 - для объекта RangeValidator использовать конструктор с параметрами A и B, где A и B — ранее указанные числа.

Для каждого из пяти данных наборов строк выполнить следующие действия: добавить набор строк в объект tf (вызвав требуемое число раз метод SetText объекта tf) и проверить правильность этого набора строк (вызвав метод Validate объекта tf и выведя его результат).

# OOP3Behav6

Реализовать иерархию классов, связанную с поиском минимальных и максимальных элементов в наборе данных и включающую
 - абстрактный класс AbstractComparable
и три его потомка: 
 - NumberComparable
 - LengthComparable
 - TextComparable.

В абстрактном классе реализованы четыре статических шаблонных метода 
 - IndexMax
 - LastIndexMax
 - IndexMin
 - LastIndexMin

Параметром каждого метода является набор comp объектов-ссылок типа AbstractComparable; (массив или другая структура данных); методы возвращают целое число — индекс первого наибольшего, последнего наибольшего, первого наименьшего и последнего наименьшего элемента набора comp соответственно (индексирование производится от нуля).

В шаблонных методах используется абстрактный метод CompareTo(other) с параметром-ссылкой other типа AbstractComparable. Этот метод позволяет сравнивать между собой экземпляры a и b одного и того же класса — потомка класса AbstractComparable: вызов Comparable(b) для объекта a возвращает 
 - отрицательное значение, если a «меньше», чем b
 - нулевое значение, если a «равно» b
 - положительное значение, если a «больше», чем b 
(слова «меньше», «равно» и «больше» взяты в кавычки, так как смысл сравнений может быть различным для разных потомков класса AbstractComparable).

Каждый из конкретных классов имеет конструктор со
 - строковым параметром data, который определяет значение поля key.

     - Для класса NumberComparable поле key имеет целый тип; если параметр data является строковым представлением некоторого целого числа, то в поле key записывается это число, если параметр data не удовлетворяет указанному условию, то поле key полагается равным 0.
     - Для класса LengthComparable поле key также имеет целый тип и полагается равным длине строки data.
     - Для класса TextComparable поле key имеет строковый тип и полагается равным самой строке data.

Реализовать в классах-потомках метод CompareTo(other) в котором
 - параметр other преобразуется к типу данного класса-потомка,
 -  после чего поля key объекта, вызвавшего метод, и объекта other сравниваются между собой
 -  если поле key объекта, вызвавшего метод, меньше, равно или больше поля key объекта other, то метод возвращает соответственно отрицательное, нулевое или положительное значение (для класса TextComparable строковые поля key сравниваются лексикографически).
 -  Не требуется особым образом обрабатывать ситуацию, когда параметр other не может быть преобразован к нужному типу, поскольку она не будет возникать при обработке правильно сформированных наборов данных.

Даны целые числа N (≤ 9), K (≤ 7), а также K наборов из N + 1 строки, причем начальная строка в каждом наборе имеет вид «N», «L» или «T». Описать структуру comp из N элементов-ссылок типа AbstractComparable (тип структуры должен совпадать с типом параметра шаблонных методов) и использовать эту структуру для обработки каждого исходного набора строк следующим образом:

(1) создать и записать в структуру comp объекты типа, определяемого начальной строкой обрабатываемого набора: если начальная строка равна «N», «L» или «T», то создаются объекты типа NumberComparable, LengthComparable или TextComparable соответственно; строки исходного набора указываются в качестве параметров конструкторов объектов, для начальной строки объект не создается;

(2) вызвать шаблонные методы IndexMax, LastIndexMax, IndexMin, LastIndexMin с параметром comp и вывести их возвращаемые значения в указанном порядке.

# OOP3Behav9

Задание 2. Реализовать набор классов для варианта паттерна Command с дополнительными возможностями, связанными с созданием макрокоманд и отменой предыдущих действий.

Имеются три класса-получателя, реализующих различные операции и умеющих отменять их: 
 - класс OperationA включает статические методы ActionA (выводит строку «+A») и UndoActionA (выводит строку «−A»)
 - класс OperationB включает статические методы ActionB (выводит строку «+B») и UndoActionB (выводит строку «−B»)
 - класс OperationC включает статические методы ActionC (выводит строку «+C») и UndoActionC (выводит строку «−C»). 

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

Иерархия классов-команд начинается с абстрактного класса Command, включающего методы 
 - Execute 
 - Unexecute (методы не имеют параметров и не возвращают значений).

Его потомками являются классы 
 - CommandA
 - CommandB
 - CommandC 
 - MacroCommand

Конструкторы классов CommandA, CommandB, CommandC не имеют параметров и не выполняют дополнительных действий. 

 - Метод Execute команды A выполняет вызов статического метода ActionA класса-получателя OperationA, метод Unexecute команды A выполняет вызов статического метода UndoActionA. 
 - Методы Execute и Unexecute команд B и C определяются аналогично, с использованием статических методов классов OperationB и OperationC.

Класс MacroCommand позволяет объединять имеющиеся команды в последовательности команд (макрокоманды). 
 - Он содержит структуру cmds (например, массив) с элементами-ссылками типа Command, которая инициализируется в конструкторе, имеющем соответствующий параметр-структуру (можно считать, что макрокоманда содержит не более 5 команд). 
 - Метод Execute класса MacroCommand выполняет вызов методов Execute всех элементов структуры cmds в исходном порядке, а метод Unexecute — вызов методов Unexecute всех элементов структуры cmds в обратном порядке.

Реализовать класс Menu, предоставляющий средства для настройки инициаторов команд, их выполнения, а также выполнения операций отмены и восстановления. Класс Menu содержит две структуры: 
 - массив availCmds размера 3, в котором хранятся ссылки на команды, доступные для выполнения
 - структуру lastCmds, в котором хранятся ссылки на ранее выполненные команды, что дает возможность отменять эти команды или, после отмены, восстанавливать их. 

    В качестве структуры lastCmds удобно использовать динамическую структуру, позволяющую добавлять в конец новые элементы и удалять часть последних элементов. Можно считать, что структура lastCmds в любой момент времени будет содержать не более 40 элементов.

    Со структурой lastCmds связано дополнительное целочисленное поле undoIndex, определяющее индекс элемента из lastCmd, после которого следуют ранее отмененные команды (которые впоследствии могут быть восстановлены). Конструктор класса Menu содержит два ссылочных параметра: cmd1 и cmd2 типа Command; эти параметры определяют два начальных элемента массива availCmds; третий элемент этого массива является макрокомандой (объектом типа MacroCommand), включающей команды cmd1 и cmd2 в указанном порядке.

Класс Menu содержит три метода
 - Invoke(cmdIndex)
 - Undo(count)
 - Redo(count); методы имеют целочисленные параметры и не возвращают значений.

Метод **Invoke**(cmdIndex) выполняет команду из массива availCmds с индексом cmdIndex (при реализации этого метода можно считать, что параметр cmdIndex всегда находится в допустимом диапазоне 0–2). Кроме того, при выполнении метода Invoke из структуры lastCmds удаляются все конечные элементы, начиная с элемента с индексом undoIndex + 1 (если такие элементы существуют), в конец структуры lastCmds добавляется ссылка на только что выполненную команду, а значение поля undoIndex полагается равным индексу добавленной команды.

Метод **Undo**(count) отменяет count выполненных команд, хранящихся в структуре lastCmds, начиная с команды с индексом undoIndex в направлении уменьшения индексов (если в структуре lastCmds содержится недостаточно элементов, то отменяются все доступные команды). Для каждой из этих команд вызывается метод Unexecute; кроме того, значение поля undoIndex корректируется так, чтобы оно соответствовало последней еще не отмененной команде (если отменены все команды из набора lastCmds, то значение undoIndex полагается равным −1).

Метод **Redo**(count) восстанавливает count ранее отмененных команд, выполняя метод Execute для элементов структуры lastCmds, начиная с команды с индексом undoIndex + 1 в направлении увеличения индексов (если в структуре lastCmds содержится недостаточно элементов, то восстанавливаются все ранее отмененные команды). Кроме того, значение поля undoIndex корректируется так, чтобы оно соответствовало последней восстановленной команде.

 > Описанный механизм отмены/восстановления команд позволяет отменять и восстанавливать любое количество ранее выполненных команд (с сохранением их исходного порядка выполнения), однако при выполнении новой команды он блокирует возможность восстановления ранее отмененных команд (поскольку их результат может конфликтовать с результатом выполнения новой команды).

Даны два различных символа C1 и C2, которые могут принимать три значения: «A», «B», «C». Символ C1 определяет тип первого параметра конструктора объекта Menu (значение «A» соответствует классу CommandA, значение «B» — классу CommandB, значение «C» — классу CommandC). Аналогичным образом, символ C2 определяет тип второго параметра конструктора объекта Menu. Используя указанную информацию, создать объект m типа Menu.

Также дано целое число N (≤ 40), задающее количество методов объекта m для выполнения, и набор из N двухсимвольных строк, кодирующих требуемые методы. Первый символ каждой строки является одной из букв «I», «U», «R», а второй символ является цифрой, причем в случае первого символа «I» возможны только цифры «0», «1», «2», а в случае символов «U» и «R» — только цифры в диапазоне от «1» до «9». Строки «I0», «I1», «I2» соответствуют методу Invoke с параметрами 0, 1, 2; строки, начинающиеся с символа «U», соответствуют методу Undo, причем цифра определяет количество команд для отмены (например, строка «U4» соответствует методу Undo(4)); строки, начинающиеся с символа «R», соответствуют методу Redo, а цифра определяет количество восстанавливаемых команд.

Выполнить в указанном порядке все методы для созданного объекта m типа Menu. Выводить какие-либо данные не требуется, так как вывод осуществляется в классах-получателях OperationA, OperationB и OperationC при выполнении соответствующих команд.