Алгоритм, способы описания, свойства.



Алгоритм - описанная на некотором языке точная конечная система правил, определяющая содержание и порядок действий над некоторыми объектами, строгое выполнение которых дает решение поставленной задачи.

Алгоритм характеризуется следующими свойствами:

Дискретность (разрывность) - это свойство алгоритма, характеризующее его структуру: каждый алгоритм состоит из отдельных законченных действий, говорят «Делится на шаги».

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

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

Результативность - свойство, состоящее в том, что любой алгоритм должен завершаться за конечное (может быть очень большое) число шагов.

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

Рассмотрим следующие способы описания алгоритма:

Словесное описание представляет структуру алгоритма на естественном языке

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

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

Название символа Обозначение и пример заполнения Пояснение
Процесс Вычислительное действие или последовательность действий
Решение Проверка условий
Модификация Начало цикла
Предопределенный процесс Вычисления по подпрограмме, стандартной подпрограмме
Ввод-вывод Ввод-вывод в общем виде
Пуск-остановка Начало, конец алгоритма, вход и выход в подпрограмму
Документ Вывод результатов

 

Данные в Паскале. Типы данных. Переменные и константы.

Переменная - это программный объект, значение которого может изменяться в процессе работы программы.

Тип данных - это характеристика диапазона значений, которые могут принимать переменные, относящиеся к этому типу данных.

Все используемые в программе переменные должны быть описаны в специальном разделе var по следующему шаблону:

Константы

Константа - это объект, значение которого известно еще до начала работы программы.

В языке Pascal существует три вида констант:

- неименованные константы (цифры и числа, символы и строки, множества);

- именованные нетипизированные константы;

- именованные типизированные константы.

Неименованные константы

Неименованные константы не имеют имен, и потому их не нужно описывать.

Тип неименованной константы определяется автоматически, по умолчанию:

- любая последовательность цифр (возможно, предваряемая знаком "-" или "+" или разбиваемая одной точкой) воспринимается компилятором как неименованная константа - число (целое или вещественное);

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

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

Кроме того, существуют две специальные константы true и false, относящиеся к логическому типу данных.

Примерами использования неименованных констант могут послужить следующие операторы:

int1 := -10;

real2 := 12.075 + х;

boolean6 := true;

Нетипизированные константы

Именованные константы, как следует из их названия, должны иметь имя. Стало быть, эти имена необходимо сообщить компилятору, то есть описать в специальном разделе const.

Если не указывать тип константы, то по ее внешнему виду компилятор сам определит, к какому (базовому) типу ее отнести.

const n = -10;

x = 2.5;

c = 'z';

b = true;

Типизированные константы

Типизированные именованные константы представляют собой переменные(!) с начальным значением, которое к моменту старта программы уже известно. Следовательно, во-первых, типизированные константы нельзя использовать для определения других констант, типов данных и переменных, а во-вторых, их значения можно изменять в процессе работы программы.

Описание типизированных констант производится по следующему шаблону:

const n: integer = -10;

x: real = 2.5;

c: char = 'z';

b: boolean = true;

  1. Скалярные типы данных в Паскале.

СКАЛЯРНЫЕ ТИПЫ ДАННЫХ в языке Pascal.

В основе тип переменной – мн-во значений, которые принимает переменная. С каждым типом связан набор операций.

Типы бывают:

- структурированными

- простыми

- указатели

- строки

- процедурные типы

- объекты

В свою очередь простые типы подразделяются на:

- стандартный

- определяемый (задается с помощью правил)

 

СТАНДАРТНЫЙ ТИП:

1) упорядоченный:

1. целый:

- integer -32768..+32767

- byte 0..255

- word 0..65535

- shortint -128..+128

- longint -2147483648..+2147483647

Стандартные процедуры и функции:

abs, chr, dec, inc, odd, random, sqr, sqrt

2. логический:

true/false (1/0)

3. литерный: ASCII – American Standard Code for Information Interchange

Стандартные процедуры и функции:

ord, upcase

4. перечисляемый:

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

type

colors = (red, white, blue);

Соответствие между значениями перечисляемого типа и порядковыми номерами этих значений устанавливается порядком перечисления: первое значение в списке получает порядковый номер 0, второе - 1 и т.д.

5. тип-диапазон:

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

<мин.знач.>..<макс.знач.>

Здесь <мин.знач> - минимальное значение типа-диапазона; <макс.знач> - максимальное его значение.

2) неупорядоченный:

вещественный.

Расширение для вещественного типа в Турбо-Паскале:

- real 11..12

- single 7..8

- double 15..16

- extended 19..20

- comp 19..20

  1. Структурные типы данных в Паскале. Особенности различных структурных типов.

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

Массив - это упорядоченный набор переменных одного типа.

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

 

Описание массивов:

Var

Mas: Array [1..15] Of Real.

Work: Array [(Mon, Tue, Wed)] Of Integer.

B: Array ['A'..'Z'] Of Boolean.

C: Array [1..3, 1..5] Of Real.

D: Array [(Black, White)] Of 11..20.

В Паскале многомерный массив можно описать как одномерный:

Type

Mas = Array [1..3] Of Array [1..5] Of Integer;

Var

A, B: Mas;

C: Array [1..3, 1..5] Of Integer;

{такая же структура но определена как двумерный массив}

Ссылка на элемент матрицы А, лежащий на пересечении I-той строки и J-ого столбца выглядит следующим образом A[I][J]; законно и такое обращение A[2]:= B[1], для массива такая запись не верна. Все элементы структурированных типов допускают A:= B (исключение - переменные файлового типа).

 

Можно использовать комформант - массивы. Массивы с переменными границами в Турбо-Паскале использовать нельзя. Нельзя, также и сравнивать массивы:

If A = B Then ...

  1. Структура программы на языке Паскаль.

  1. Выражения, виды выражений, приоритет выполнения операций в выражении.

Логические операции выполняются над логическими данными. Результатом выполнения булевских (логических) операций является одно из двух значений: True –  истина, False – ложь.

Операции отношения выполняют сравнение двух операндов и определяют, истинно выражение или ложно. Их результат - логический.

Порядок выполнения действий:

С высшего к низшему

· действия в скобках;

· вычисление функций, если они есть;

· умножение и деление;

· сложение и вычитание;

· отношения.

  1. Оператор присваивания. Арифметические выражения. Арифметические операции.

Оператор присваивания - основной оператор любого языка программирования. Общая форма записи оператора:

имя величины := выражение

Например, V:=A; или V:=A+1;

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

Арифметические выражения должны быть записаны в так называемой линейной записи согласно следующим правилам:

• выражение должно быть записано в виде линейной цепочки символов;

• используемые операции приведены в таблице:

НАЗВАНИЕ ОПЕРАЦИИ ФОРМА ЗАПИСИ
сложение x + y
вычитание x - y
умножение x * y
деление x / y

• нельзя опускать знаки операций, например писать 5b. Для записи произведения чисел 5 и b надо писать 5*b;

• аргументы функций (sin, cos и др.) как и аргументы вспомогательных алгоритмов, записываются в круглых скобках, например sin(x), cos(4*x).

 

  1. Операторы ввода – вывода.

Read/Readln

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

Разница между работой оператора Read и Readln в Паскале состоит в следующем: после выполнения Read значение следующего данного считывается с этой же строчки, а после выполнения Readln — с новой строки

Write/Writeln

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

Различие между двумя операторами вывода в Паскале таково: после выполнения оператора Writeln (от Write line) происходит переход па новую строчку, а после выполнения инструкции Write переход на новую строчку не происходит и печать по последующим командам вывода Write или Writeln будет происходить на той же строчке. При вызове оператора Writeln без параметров просто происходит переход па новую строчку.

  1. Программирование разветвляющихся алгоритмов. Условный оператор. Операции отношения и логические операции.

В Паскале разветвляющиеся алгоритмы позволяет реализовать условный оператор. Условный оператор позволяет проверить некоторое логическое выражение и в зависимости от результатов проверки выполнить то или иное действие.
Структура условного оператора в полной форме имеет следующий вид:

IF (логическое выражение) THEN (оператор1) ELSE (оператор2);

Вначале вычисляется значение логического выражения, если результат - TRUE (истина), то выполняется оператор1, если результат есть FALSE (ложь), наоборот, выполняется оператор2.

Блок-схема условного оператора в полной форме:


В условном операторе после then, а также после else по синтаксису может стоять только один оператор. Если же при выполнении (или невыполнении)логического выражения надо выполнить не одно действие, а несколько, то их надо объединить в единый, составной оператор, т.е. заключить эту последовательность действий в операторные скобки.
Составной оператор имеет вид:

begin операторы end;

Перед служебным словом Else символ «;» не ставится.!!!!

Пример:

Блок-схема: Программный код: Var a,b,y:integer; begin if (a>b) then y:=a else y:=b; end.

Структура условного оператора в неполной форме имеет следующий вид:

IF (условие) THEN (оператор);

Вычисляется значение логического выражения, если оно имеет значение true, то выполняется оператор, записанный после then, если же значение ложно (false), то выполнение условного оператора завершается.

Пример:
if (x>-5) and (x<1) then writeln(‘no’);

В качестве операторов после служебных слов then и else в условном операторе можно использовать другие условные операторы. Такой оператор называется вложенной конструкцией условного оператора. При вложенных конструкциях условного оператора могут возникнуть неоднозначности в понимании того, к какой из вложенных конструкций условного оператора относится else. Компилятор Паскаля всегда считает, что else относится к последней из конструкций условного оператора, в котором не было раздела else. Говорят, что else относится к ближайшему then.
В условном операторе вида:

If A then If B then оператор1 else оператор2

A и B – логические выражения.
Проверяется значение логического выражения A, если оно истинно, то выполняется условный оператор в полной форме If B then оператор1 else оператор2. Если же значение ложно, то условный оператор не выполняется.
Если в условном операторе в полной форме после служебного слова then нужен условный оператор в сокращенной форме, то необходимо записать:

If A then begin If B then оператор1 end else оператор2

  1. Оператор выбора.

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

Структура оператора выбора в Паскале такова:

Здесь case, of, else, end – зарезервированные слова (случай, из, иначе, конец);

· <ключ_выбора> - выражение порядкового типа;

· <список_выбора> - одна или более конструкций вида:

o <константа_выбора>: <оператор>;

· <константа_выбора> - константа того же типа, что и выражение

o <ключ_выбора>;

<операторы> - произвольные операторы Паскаля.

Оператор выбора Паскаля работает следующим образом. Вначале вычисляется значение выражения <ключ_выбора>, а затем в последовательности <список_выбора> отыскивается константа, равная вычисленному значению. Выполняется оператор, который следует за найденной константой, после чего оператор выбора завершает работу. Если в списке выбора не будет найдена константа, соответствующая вычисленному значению ключа выбора, управление передается операторам, стоящим за словом else. Часть else <оператор_иначе> можно опустить, тогда при отсутствии в списке выбора нужной константы не будет выполнено никаких действий, и оператор выбора просто завершит свою работу.

Например, составим программу, которая по номеру дня недели выводит на экран его название:

 

  1. Операторы повторения. Оператор цикла с параметром.

Существует три различных цикла: for, while и repeat, каждый из которых работает с постусловием (Repeat) и предусловием (For, While). Цикл с предусловием означает, что программа выполняет цикл только после проверки условия, а для цикла с постусловием условие проверяется только после выполнения цикла. Условие в цикле необходимо для его завершения. Чтобы прервать любой цикл во время выполнения, необходимо внутри него поместить функцию break (с англ. «прервать»). Однако break предназначена для остановки лишь одного цикла, следовательно, чтобы непременно остановить два вложенных цикла необходимо внутрь каждого из них поместить break.

Цикл for

Структура данного цикла for следующая:


for i:=1 to 10 do
s:=s+10;

Вначале ставим ключевое слово for. Переменная i — счетчик (всегда целый (integer) числовой тип переменной). В данном примере счетчик увеличивается с 1 до 10. При этом переменная s каждый раз увеличивается на 10. Чтобы данный цикл уменьшать с большего числа до меньшего, вместо to поставим downto:


for i:=10 downto 1 do
s:=s+1;

16. Операторы повторения. Операторы цикла с пред- и постусловием.

Цикл while с предусловием

Структура цикла while следующая:

while a<b do

begin

a:=a+1;


while a<10 do
a:=a+1;

Вначале ставим ключевое слово while. Затем прописываем условие, при котором будет выполняться цикл и ставим ключевое слово do, после которого прописываем действия, которые необходимо повторить. Как только логическое значение условия станет false (ложь), цикл автоматически завершится. В данном примере действие a:=a+1 будет повторяться до тех пор, пока переменная a не станет больше 10.

Цикл Repeat с постусловием

Структура цикла repeat следующая:


repeat
a:=a+1;
until a=10;

Вначале ставим ключевое слово repeat. Затем выполняется часть кода до ключевого слова until, после которого задается условие. Между repeat и until begin и end, в отличие от циклов for и while, ставить не нужно. В данном примере цикл завершается только тогда, когда значение переменной a станет равным 10.

 

  1. Массивы. Описание массивов, действия с ними.

Массивом называют упорядоченный набор однотипных переменных (элементов). Каждый элемент имеет целочисленный порядковый номер, называемый индексом. Число элементов в массиве называют его размерностью. Массивы используются там, где нужно обработать сразу несколько переменных одного типа – например, оценки всех 20 студентов группы или координаты 10 точек на плоскости. Строку текста можно рассматривать как массив символов, а текст на странице – как массив строк.

Массив описывается в разделе var оператором следующего вида:

Var Имя Массива: array [Нижний Индекс .. Верхний Индекс] of Тип;

Var a: array [1..20] of integer;

Для обращения к отдельному элементу массива используется оператор вида

Имя Массива [Индекс]

A[1]:=1

Ввод массива с клавиатуры:

С onst n = 10;

Var a: array [1..n] of real;

i:integer;

Begin

Writeln ('Введите элементы массива ');

For i:=1 to n do read (A[i]);

Формирование массива из случайных значений уместно, если при решении задачи массив служит лишь для иллюстрации того или иного алгоритма, а конкретные значения элементов несущественны.

var a:array [1..20] of integer;

i:integer;

begin

Randomize;

for i:=1 to 20 do begin

a[i]:=Random(21)-10;

write (a[i]:4);

end;

end.

Обработка массива(в данном случае, вычисляется суммаsего положительных элементов)

Var b:array [1..5] of real;

s:real; i:integer;

Begin

Writeln ('Введите 5 элементов массива');

for i:=1 to 5 do read (b[i]);

s:=0;

for i:=1 to 5 do if b[i]>0 then s:=s+b[i];

Вывод массива на экран:

For i:=1 to 5 do write (b[i]:6:2);

  1. Сортировка массивов методом выбора.

  1. Сортировка массивов методом попарных перестановок.

Второй метод называется метод вставок., т.к. на j-ом этапе мы "вставляем" j-ый элемент M[j] в нужную позицию среди элементов M[1], M[2],. . ., M[j-1], которые уже упорядочены. После этой вставки первые j элементов массива M будут упорядочены.

Сказанное можно записать следующим образом:

нц для j от 2 до N

переместить M[j] на позицию i <= j такую, что

    M[j] < M[k] для i<= k < j и

    либо M[j] >= M[i-1], либо i=1

кц

Чтобы сделать процесс перемещения элемента M[j], более простым, полезно воспользоваться барьером: ввести "фиктивный" элемент M[0], чье значение будет заведомо меньше значения любого из "реальных"элементов массива (как это можно сделать?). Мы обозначим это значение через —оо.

Если барьер не использовать, то перед вставкой M[j], в позицию i-1 надо проверить, не будет ли i=1. Если нет, тогда сравнить M[j] ( который в этот момент будет находиться в позиции i) с элементом M[i-1].

Описанный алгоритм имеет следующий вид:

  1. Многомерные массивы. Обработка матриц.

Многомерный массив Pascal широко применяется при решении задач с матрицами. Например, двухмерный массив размерностью n*m это матрица с i-строкой и j-столбцом. Как и в одномерных массивах, элементы имеют любой тип, а индексы могут иметь любой ограниченный тип данных.

Синтаксис:

Var M: array[1..3,1..3] of Integer;

или

Var M: array[1..3] of array[1..3] of Integer;

Наиболее понятен первый вариант записи. Допустим, нам нужен трехмерный массив, тогда:

Операции:

Ввод

Вывод двумерного массива Паскаля на экран.

  1. Символьные данные: способы записи, множество значений, операции над ними.

Тип данных CHAR

Каждая переменная символьного типа может принимать значение только одного символа.

program lr1;

type sl =array [1..10] of char;

var s: sl; {описание массива символов}

i: integer;

begin

writeln ('введите 10 символов '):

for i:=1 to 10 do readln (s[i]);     {ввод массива }

for i:=1 to 10 do

if (s[i]>=’A’) and (s[i]<= ‘Z’) then

writeln (‘Символ :’, s[i], ‘ его код =’, ord (s[i]);

readln;

end.

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

'A'<'B'<...<'Z'

'a'<'b'<...<'z'

'0'<'1'<...<'9'

'а'<'б'<...<'я'

'А'<'Б'<...<'Я'

  1. Данные строкового типа: способы записи, операции над ними.

Тип данных STRING (st)

В Турбо Паскале предусмотрен тип данных STRING. Переменная типа STRING может принимать значения переменной длины. Максимально возможная длина переменной 255 символов. Например:

str: STRING[200];

ow: STRING[10];

Операция слияния (сцепления, конкатенации) применяется для соединения нескольких строк в одну, обозначается знаком «+». Операция слияния применима для любых строковых выражений, как констант, так и переменных.

Операции отношения позволяют сравнивать строки на отношение равенства (=), неравенства (<>), больше (>), меньше (<), больше или равно (>=), меньше или равно (<=). В результате сравнения двух строк получается логическое значение (true или false). Сравнение строк производится слева направо посимвольно до первого несовпадающего символа, большей считается та строка, в которой первый несовпадающий символ имеет больший код в таблице кодировки. Если строки имеют различную длину, но в общей части символы совпадают, считается, что короткая строка меньше. Строки равны, если они имеют равную длину и соответствующие символы совпадают.

  1. Использование подпрограмм. Процедуры.

Подпрограмма — это фрагмент кода, который имеет свое имя и создается в случае необходимости выполнять этот код несколько (много) раз. Подпрограмма описывается единожды перед началом основной программы (до begin). Компилятор пропускает данный фрагмент кода, пока в основной программе не встретит «вызов» подпрограммы, который выглядит как обращение к ней по имени (возможно, имени с аргументами, указанными в скобках).

Рассмотрим синтаксис объявления и описания процедуры в Паскале.

Формальный параметр процедуры указывается в скобках при ее описании. Обязательно необходимо указать тип формального параметра через двоеточие.

Фактический параметр — это то значение, которое указывается в скобках при вызове процедуры. Фактическим параметром может быть конкретное значение (литерал: число, символ, строка…), либо переменная, которые компилятор подставит вместо формального параметра. Поэтому тип данных у формального и фактического параметра процедуры должен быть одинаковым.

В примере формальные параметры a и b служат для помещения в них сравниваемых чисел, а параметр-переменная max — для сохранения в ней максимального из двух чисел. Параметр-переменная или выходной параметр передает свое значение в основную программу (фактическому параметру m), т.е. возвращает значение, тогда как формальные параметры-значения (входной параметр), наоборот, принимают значения из основной программы (из фактических параметров x и y). Для параметра-переменной (max) используются те ячейки памяти, которые отведены под соответствующий параметр при вызове процедуры (ячейка m).

  1. Использование подпрограмм. Функции.

Функция выглядит почти так же, как и процедура. Почти единственное отличие в том, что заголовок функции начинается с ключевого слова Function и кончается типом возвращаемого данной функцией значения.

function <имя функции> (<список формальных операторов>): <тип возвращаемого значения>;

  1. Стандартные модули Турбо-Паскаля. Модуль CRT.

В Turbo Pascal входит восемь стандартных модулей. Шесть из них SYSTEM, OVERLAY, GRAPH, DOS, CRT и PRINTER - осуществляют поддержку программ на Turbo Pascal; все они сохранены в TURBO.TPL. Программные ресурсы, сосредоточенные в стандартных модулях, образуют мощные пакеты системных средств, которые обеспечивают высокую эффективность и широкий спектр применений системы Turbo Pascal.

Каждый модуль хранится в одноименном TPU-файле в системном каталоге Turbo Pascal. Кроме того, обычно модули SYSTEM, DOS, CRT, PRINTER и OVERLAY входят в состав системного библиотечного файла TURBO.TPL. Для того, чтобы воспользоваться ресурсами стандартного модуля, необходимо указать его имя в спецификации использования по обычным правилам. Исключение сделано для модуля SYSTEM, имя которого можно не указывать, т.к. содержащиеся в нем ресурсы подключаются автоматически к любой программе.

Модуль System.

В модуль System входят все процедуры и функции авторской версии языка Pascal, подпрограммы стандартного Паскаля, а также много дополнительных подпрограмм общего характера, в частности, ориентированные на конкретную операционную среду.

Модуль DOS.

Модуль DOS содержит средства доступа к операционной системе и по существу является программным представлением системного интерфейса MS-DOS.

Модуль Crt.

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

Модуль Printer.

Модуль Printer содержит единственный интерфейсный элемент - переменную Lst стандартного типа text, системно связанную с логическим устройством PRN (т.е. печатное устройство, если оно имеется в конфигурации). Использование этой переменной в стандартных процедурах Write и WriteLn приводит к выводу информации на печать.

Модуль Overlay.

Модуль Overlay предоставляет средства для организации так называемых оверлейных программ, позволяющих обеспечить достаточно эффективное выполнение больших программных систем, размер которых превышает объем доступной оперативной памяти.

Оверлей - это часть программы, загружаемая в память, когда необходимо, и затем выгружаемая из нее. Это значит, что в память программа загружается не вся, а частями по необходимости. Работой оверлеев управляет специальная интеллектуальная программа монитор оверлеев.


Дата добавления: 2020-01-07; просмотров: 205; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!