Домашние работы курса 2-ого семестра «Парадигмы программирования» кафедры КТ, университета ИТМО
-
Доработайте правило
(evaluate Expression Varsiables Result)
вычисляющее арифметические выражения.-
Пример вычисления выражения
2x-3
дляx = 5
:eval( operation(op_subtract, operation(op_multiply, const(2), variable(x) ), const(3) ), [(x, 5)], 7 )
-
Поддерживаемые операции: сложение (
op_add
,+
), вычитание (op_subtract
,-
), умножение (op_multiply
,*
), деление (op_divide
,/
), противоположное число(op_negate
,negate
).
-
-
Простой вариант.
Реализуйте правило
(suffix_str Expression Atom)
, разбирающее/выводящее выражения, записанные в суффиксной форме. Например,suffix_str( operation(op_subtract,operation(op_multiply,const(2),variable(x)),const(3)), '((2 x *) 3 -)' )
-
Сложный вариант.
Реализуйте правило
(infix_str Expression Atom)
, разбирающее/выводящее выражения, записанные в полноскобочной инфиксной форме. Например,infix_str( operation(op_subtract,operation(op_multiply,const(2),variable(x)),const(3)), '((2 * x) - 3)' )
-
Правила должны быть реализованы с применением DC-грамматик.
-
Модификации
Variables
. Дополнительно реализовать поддержку:- Переменных, состоящих из произвольного количества букв
XYZ
в любом регистре. Настоящее имя переменной определяется первой буквой ее имени
- Переменных, состоящих из произвольного количества букв
VarBoolean
. Сделать модификациюVariables
и дополнительно реализовать поддержку:- Булевских операций
- Аргументы: число больше 0 →
true
, иначе →false
- Результат:
true
→ 1,false
→ 0 And
(&&
) – и:5 & -6
равно 0Or
(||
) - или:5 & -6
равно 1Xor
(^^
) - исключающее или:5 ^ -6
равно 1- операции по увеличению приоритета:
^^
,||
,&&
, операции базовой модификации
- Аргументы: число больше 0 →
- Булевских операций
-
Реализуйте ассоциативный массив (map) на основе деревьев поиска. Для решения можно реализовать любое дерево поиска логарифмической высоты.
-
Простой вариант. Разработайте правила:
map_build(ListMap, TreeMap)
, строящее дерево из упорядоченного списка пар ключ-значение (O(n));map_get(TreeMap, Key, Value)
, проверяющее, что массив содержит заданную пару ключ-значение (O(log n)).
-
Сложный вариант. Дополнительно разработайте правила:
-
map_put(TreeMap, Key, Value, Result)
; добавляющее пару ключ-значение в массив, или заменяющее текущее значение для ключа (O(log n)); -
map_remove(TreeMap, Key, Result)
удаляющее отображение для ключа (O(log n)); -
map_build(ListMap, TreeMap)
, строящее дерево из неупорядоченного списка пар ключ-значение (O(n log n)).
-
-
Добавьте правила:
map_headMapSize(Map, ToKey, Size)
, возвращающее число пар меньших ToKey;map_tailMapSize(Map, FromKey, Size)
, возвращающее число пар больших или равных FromKey,
- Разработайте правила:
prime(N)
, проверяющее, чтоN
– простое число.composite(N)
, проверяющее, чтоN
– составное число.prime_divisors(N, Divisors)
, проверяющее, что списокDivisors
содержит все простые делители числаN
, упорядоченные по возрастанию. ЕслиN
делится на простое числоP
несколько раз, тоDivisors
должен содержать соответствующее число копийP
.
- Варианты
- Простой:
N
≤ 1000. - Сложный:
N
≤ 105. - Бонусный:
N
≤ 107.
- Простой:
- Вы можете рассчитывать, на то, что до первого запроса будет выполнено правило
init(MAX_N)
. - Добавьте правило
prime_index(P, N)
, подсчитывающее номер простого числа:prime_index(2, 1)
,prime_index(101, 26)
-
Простой вариант.
Реализуйте функцию
(parseObjectSuffix "expression")
, разбирающую выражения, записанные в суффиксной форме, и функциюtoStringSuffix
, возвращающую строковое представление выражения в этой форме. Например,(toStringSuffix (parseObjectSuffix "( ( 2 x * ) 3 - )"))
должно возвращать((2 x *) 3 -)
. -
Сложный вариант.
Реализуйте функцию
(parseObjectInfix "expression")
, разбирающую выражения, записанные в инфиксной форме, и функциюtoStringInfix
, возвращающую строковое представление выражения в этой форме. Например,(toStringInfix (parseObjectInfix "2 * x - 3"))
должно возвращать((2 * x) - 3)
. -
Бонусный вариант. Добавьте в библиотеку комбинаторов возможность обработки ошибок и продемонстрируйте ее использование в вашем парсере.
-
Функции разбора должны базироваться на библиотеке комбинаторов, разработанной на лекции.
-
Модификации:
Variables
. Дополнительно реализовать поддержку:- Переменных, состоящих из произвольного количества букв
XYZ
в любом регистре- Настоящее имя переменной определяется первой буквой ее имени
- Переменных, состоящих из произвольного количества букв
Boolean
. Сделать модификацию Variables и дополнительно реализовать поддержку:- Булевских операций
- Аргументы: число больше 0 →
true
, иначе →false
- Результат:
true
→ 1,false
→ 0 And
(&&
) – и:5 & -6
равно 0Or
(||
) - или:5 & -6
равно 1Xor
(^^
) - исключающее или:5 ^ -6
равно 1- операции по увеличению приоритета:
^^
,||
,&&
, операции базовой модификации
- Аргументы: число больше 0 →
- Булевских операций
ImplIff
. Сделать модификациюBoolean
и дополнительно реализовать поддержку:- Булевских операций
Impl
(->
) – импликация (правоассоциативна):-4 -> 1
равно 1Iff
(<->
) - тогда и только тогда:2 <-> 6
равно 1- операции по увеличению приоритета:
<->
,->
, операции модификации Boolean
- Булевских операций
-
Разработайте конструкторы
Constant
,Variable
,Add
,Subtract
,Multliply
иDivide
для представления выражений с одной переменной.-
Пример описания выражения
2x-3
:(def expr (Subtract (Multiply (Constant 2) (Variable "x")) (Constant 3)))
-
Функция
(evaluate expression vars)
должна производить вычисление выраженияexpression
для значений переменных, заданных отображениемvars
. Например,(evaluate expr {"x" 2})
должно быть равно 1. -
Функция
(toString expression)
должна выдавать запись выражения в стандартной для Clojure форме. -
Функция
(parseObject "expression")
должна разбирать выражения, записанные в стандартной для Clojure форме. Например,(parseObject "(- (* 2 x) 3)")
должно быть эквивалентноexpr
. -
Функция
(diff expression "variable")
должна возвращать выражение, представляющее производную исходного выражения по заданой пермененной. Например,(diff expression "x")
должен возвращать выражение, эквивалентное(Constant 2)
, при этом выражения(Subtract (Constant 2) (Constant 0))
и(Subtract (Add (Multiply (Constant 0) (Variable "x")) (Multiply (Constant 2) (Constant 1))) (Constant 0))
так же будут считаться правильным ответом.
-
-
Сложный вариант. Констуркторы
Add
,Subtract
,Multiply
иDivide
должны принимать произвольное число аргументов. Разборщик так же должен допускать произвольное число аргументов для+
,-
,*
,/
. -
При выполнение задания можно использовать любой способ преставления объектов.
-
Дополнительно реализовать поддержку:
- операций произвольного числа аргументов:
ArithMean
(arith-mean
) – арифметическое среднее(arith-mean 1 2 6)
равно 3;GeomMean
(geom-mean
) – геометрическое среднее(geom-mean 1 2 4)
равно 2;HarmMean
(harm-mean
) – гармоническое среднее,(harm-mean 2 3 6)
равно 3;
- операций произвольного числа аргументов:
-
Разработайте функции
constant
,variable
,add
,subtract
multiply
иdivide
для представления арифметических выражений.-
Пример описания выражения
2x-3
:(def expr (subtract (multiply (constant 2) (variable "x")) (constant 3)))
-
Выражение должно быть функцией, возвращающей значение выражения при подстановке переменных, заданных отображением. Например,
(expr {"x" 2})
должно быть равно 1.
-
-
Разработайте разборщик выражений, читающий выражения в стандартной для Clojure форме. Например,
(parseFunction "(- (* 2 x) 3)")
должно быть эквивалентноexpr
. -
Сложный вариант. Функции
add
,subtract
,multiply
иdivide
должны принимать произвольное число аргументов. Разборщик так же должен допускать произвольное число аргументов для+
,-
,*
,/
. -
При выполнение задания следует обратить внимание на:
- Выделение общего кода для операций.
-
Дополнительно реализовать поддержку:
- операций произвольного числа аргументов:
mean
– математическое ожидание аргументов,(mean 1 2 6)
равно 3;varn
– дисперсия аргументов,(varn 2 5 11)
равно 14;
- Разработайте функции для работы с объектами линейной алгебры, которые представляются следующим образом:
- скаляры – числа
- векторы – векторы чисел;
- матрицы – векторы векторов чисел.
- Функции над векторами:
v+
/v-
/v*
/vd
– покоординатное сложение/вычитание/умножение/деление;scalar
/vect
– скалярное/векторное произведение;v*s
– умножение на скаляр.
- Функции над матрицами:
m+
/m-
/m*
/md
– поэлементное сложение/вычитание/умножение/деление;m*s
– умножение на скаляр;m*v
– умножение на вектор;m*m
– матричное умножение;transpose
– транспонирование;
- Сложный вариант.
- Ко всем функциям должны быть указаны контракты. Например, нельзя складывать вектора разной длины.
- Все функции должны поддерживать произвольное число аргументов. Например
(v+ [1 2] [3 4] [5 6])
должно быть равно[9 12]
.
- При выполнение задания следует обратить внимание на:
- Применение функций высшего порядка.
- Выделение общего кода для операций.
- Назовем тензором многомерную прямоугольную таблицу чисел.
-
Форма тензора – последовательность чисел
(s1..n)
=(s1, s2, …,sn)
, гдеn
– размерность тензора, аsi
– число элементов поi
-ой оси. Например, форма тензора[[[2 3 4] [5 6 7]]]
равна(1, 2, 3)
, а форма1
равна()
. -
Тензор формы
(s1..n)
может быть распространен (broadcast
) до тензора формы(u1..m)
, если(si..n)
является префиксом(u1..m)
. Для этого, элементы тензора копируются по недостающим осям. Например, распространив тензор[[1 2]]
формы(1, 2)
до формы(1, 2, 3)
получим[[[1 1 1] [2 2 2]]]
, а распространив1
до формы(2, 3)
получим[[1 1 1] [1 1 1]]
. -
Например, тензоры формы
(1, 2, 3)
и(1, 2)
совместимы, а(1, 2, 3)
и(2, 1)
– нет. Числа совместимы с тензорами любой формы. -
Добавьте операции поэлементного сложения (
tb+
), вычитания (tb-
), умножения (tb*
) и деления (tbd
) совместимых тензоров. Если формы тензоров не совпадают, то тензоры меньшей размерности должны быть предварительно распространены до тензоров большей размерности. Например,(tb+ 1 [[10 20 30] [40 50 60]] [100 200])
должно быть равно[[111 121 131] [241 251 261]]
.
-
- Добавьте в предыдущее домашнее задание функцию
parsePrefix(string)
, разбирающую выражения, задаваемые записью вида(- (* 2 x) 3)
. Если разбираемое выражение некорректно, методparsePrefix
должен бросать человеко-читаемое сообщение об ошибке. - Добавьте в предыдущее домашнее задание метод
prefix()
, выдающий выражение в формате, ожидаемом функциейparsePrefix
. - При выполнение задания следует обратить внимание на:
- Применение инкапсуляции.
- Выделение общего кода для операций.
- Минимизацию необходимой памяти.
- Обработку ошибок.
Дополнительно реализовать поддержку:
- операций произвольного числа аргументов:
ArithMean
(arith-mean
) – арифметическое среднее(arith-mean 1 2 6)
равно 3;GeomMean
(geom-mean
) – геометрическое среднее(geom-mean 1 2 4)
равно 2;HarmMean
(harm-mean
) – гармоническое среднее,(harm-mean 2 3 6)
равно 3;
-
Разработайте классы
Const
,Variable
,Add
,Subtract
,Multiply
,Divide
,Negate
, для представления выражений с одной переменной. -
Пример описания выражения
2x-3
let expr = new Subtract(
new Multiply(
new Const(2),
new Variable("x")
),
new Const(3)
);
console.log(expr.evaluate(5));
-
При вычислении такого выражения вместо каждой переменной подставляется её значение, переданное в качестве аргумента метода
evaluate
. Таким образом, результатом вычисления приведенного примера должно стать число 7. -
Метод
toString()
должен выдавать запись выражения в обратной польской записи. Например,expr.toString()
должен выдавать «2 x * 3 -
». -
Сложный вариант.
Метод
diff("x")
должен возвращать выражение, представляющее производную исходного выражения по переменнойx
. Например,expr.diff("x")
должен возвращать выражение, эквивалентноеnew Const(2)
(выраженияnew Subtract(new Const(2), new Const(0))
иnew Subtract( new Add( new Multiply(new Const(0), new Variable("x")), new Multiply(new Const(2), new Const(1)) ) new Const(0) )
так же будут считаться правильным ответом).
Функция parse
должна выдавать разобранное объектное выражение.
-
Бонусный вариант.
Требуется написать метод
simplify()
, производящий вычисления константных выражений. Например,
parse("x x 2 - * 1 *").diff("x").simplify().toString()
должно возвращать «x x 2 - +»
-
Дополнительно реализовать поддержку функций от двух аргументов:
Hypot
(hypot
) – квадрат гипотенузы,3 4 hypot
равно 25;HMean
(hmean
) – гармоническое среднее,5 20 hmean
равно 8;
-
При выполнение задания следует обратить внимание на:
- Применение инкапсуляции.
- Выделение общего кода для операций.
- Минимизацию необходимой памяти.
-
Разработайте функции
cnst
,variable
,add
,subtract
,multiply
,divide
,negate
для вычисления выражений с одной переменной. -
Функции должны позволять производить вычисления вида:
let expr = subtract( multiply( cnst(2), variable("x") ), cnst(3) ); println(expr(5));
При вычислении такого выражения вместо каждой переменной подставляется значение, переданное в качестве параметра функции
expr
(на данном этапе имена переменных игнорируются). Таким образом, результатом вычисления приведенного примера должно стать число 7. -
Тестовая программа должна вычислять выражение
x2−2x+1
, дляx
от 0 до 10. -
Требуется дополнительно написать функцию
parse
, осуществляющую разбор выражений, записанных в обратной польской записи. Например, результатомparse("x x 2 - * x * 1 +")(5)
должно быть число76
. -
Дополнительно реализовать поддержку:
- переменных:
y
,z
- констант:
one
– 1;two
– 2;
- операций:
*+
(madd
) – тернарный оператор произведение-сумма,2 3 4 *+
равно 10;_
(floor
) – округление вниз2.7 _
равно 2;^
(ceil
) – округление вверх2.7 ^
равно 3.
- переменных:
-
При выполнение задания следует обратить внимание на:
-
Применение функций высшего порядка.
-
Выделение общего кода для операций.
-
Добавьте в программу разбирающую и вычисляющую выражения трех переменных поддержку вычисления в различных типах.
-
Создайте класс
expression.generic.GenericTabulator
, реализующий интерфейсexpression.generic.Tabulator
:public interface Tabulator { Object[][][] tabulate(String mode, String expression, int x1, int x2, int y1, int y2, int z1, int z2) throws Exception; }
- Дополнительно реализовать унарные операции:
abs
– модуль числа,abs -5
равно 5;square
– возведение в квадрат,square 5
равно 25.
- Дополнительно реализовать бинарную операцию (максимальный приоритет):
mod
– взятие по модулю, приоритет как у умножения (1 + 5 mod 3
равно1 + (5 mod 3)
равно3
).
Аргументы
-
mode
— режим работыРежим Тип i
int
(с детекцией переполнений)d
double
bi
BigInteger
u
вычисления в int
без проверки на переполнениеp
вычисления в целых числах в кольце вычетов по модулю 1009 b
вычисления в byte
без проверки на переполнение -
expression
— вычисляемое выражение; -
x1
,x2
;y1
,y2
;z1
,z2
— диапазоны изменения переменны (включительно).
Возвращаемое значение — таблица значений функции, где
R[i][j][k]
соответствуетx = x1 + i
,y = y1 + j
,z = z1 + k
. Если вычисление завершилось ошибкой, в соответствующей ячейке должен бытьnull
. - Дополнительно реализовать унарные операции:
-
Доработайте интерфейс командной строки:
-
Первым аргументом командной строки программа должна принимать указание на тип, в котором будут производится вычисления:
Опция Тип -i
int
(с детекцией переполнений)-d
double
-bi
BigInteger
-u
вычисления в int
без проверки на переполнение-p
вычисления в целых числах в кольце вычетов по модулю 1009 -b
вычисления в byte
без проверки на переполнение -
Вторым аргументом командной строки программа должна принимать выражение для вычисления.
-
Программа должна выводить результаты вычисления для всех целочисленных значений переменных из диапазона −2..2.
-
-
Реализация не должна содержать непроверяемых преобразований типов.
-
Реализация не должна использовать аннотацию
@SuppressWarnings
. -
При выполнении задания следует обратить внимание на простоту добавления новых типов и операциий.
- Определите интерфейс очереди
Queue
и опишите его контракт. - Реализуйте класс
LinkedQueue
— очередь на связном списке. - Выделите общие части классов
LinkedQueue
иArrayQueue
в базовый классAbstractQueue
.
Это домашнее задание связанно с предыдущим.
- Добавить в интерфейс очереди и реализовать методы
getNth(n)
– создать очередь, содержащую каждый n-й элемент, считая с 1removeNth(n)
– создать очередь, содержащую каждый n-й элемент, и удалить их из исходной очередиdropNth(n)
– удалить каждый n-й элемент из исходной очереди
- Тип возвращаемой очереди должен соответствовать типу исходной очереди
- Дублирования кода быть не должно
-
Определите модель и найдите инвариант структуры данных «очередь». Определите функции, которые необходимы для реализации очереди. Найдите их пред- и постусловия, при условии что очередь не содержит
null
. -
Реализуйте классы, представляющие циклическую очередь с применением массива.
- Класс
ArrayQueueModule
должен реализовывать один экземпляр очереди с использованием переменных класса. - Класс
ArrayQueueADT
должен реализовывать очередь в виде абстрактного типа данных (с явной передачей ссылки на экземпляр очереди). - Класс
ArrayQueue
должен реализовывать очередь в виде класса (с неявной передачей ссылки на экземпляр очереди). - Должны быть реализованы следующие функции (процедуры) / методы:
enqueue
– добавить элемент в очередь;push
– добавить элемент в начало очередиelement
– первый элемент в очереди;peek
– вернуть последний элемент в очередиdequeue
– удалить и вернуть первый элемент в очереди;remove
– вернуть и удалить последний элемент из очередиsize
– текущий размер очереди;- Реализовать метод
toArray
, возвращающий массив, содержащий элементы, лежащие в очереди в порядке от головы к хвосту. - Реализовать метод
toStr
, возвращающий строковое представление очереди в виде ‘[
’ голова ‘,
’ … ‘,
’ хвост ‘]
‘ isEmpty
– является ли очередь пустой;clear
– удалить все элементы из очереди.
- Инвариант, пред- и постусловия записываются в исходном коде в виде комментариев.
- Обратите внимание на инкапсуляцию данных и кода во всех трех реализациях.
- Класс
-
Напишите тесты к реализованным классам.
-
Реализуйте итеративный и рекурсивный варианты бинарного поиска максимума в массиве.
-
На вход подается массив полученный приписыванием отсортированного (строго) по убыванию массива в конец массива отсортированного (строго) по возрастанию. Требуется найти в нем максимальное значение.
-
Для функций бинарного поиска и вспомогательных функций должны быть указаны, пред- и постусловия. Для реализаций методов должны быть приведены доказательства соблюдения контрактов в терминах троек Хоара.
-
Интерфейс программы.
- Имя основного класса —
BinarySearchMax
. - Аргументы командной строки — элементы массива
- Имя основного класса —