├── README.md ├── artifacts ├── queue │ ├── ArrayQueueDequeTest.jar │ ├── ArrayQueueTest.jar │ ├── ArrayQueueToArrayTest.jar │ ├── QueueFunctionsTest.jar │ ├── QueueTest.jar │ └── QueueToArrayTest.jar ├── reverse │ ├── ReverseFastTest.jar │ ├── ReverseMaxTest.jar │ ├── ReverseMinFastTest.jar │ ├── ReverseSumFastTest.jar │ ├── ReverseTest.jar │ └── ReverseTransposeTest.jar ├── search │ ├── BinarySearchMissingTest.jar │ ├── BinarySearchSpanTest.jar │ └── BinarySearchTest.jar ├── sum │ ├── SumAbcFileTest.jar │ ├── SumAbcTest.jar │ ├── SumBigIntegerDigitTest.jar │ ├── SumFileTest.jar │ ├── SumHexFileTest.jar │ ├── SumHexTest.jar │ └── SumTest.jar └── wordStat │ ├── WordStatCountTest.jar │ ├── WordStatIndexTest.jar │ ├── WordStatInputTest.jar │ ├── WordStatLineIndexTest.jar │ └── WordStatWordsTest.jar └── java ├── base ├── Asserts.java ├── MainChecker.java ├── MainFilesChecker.java ├── MainStdChecker.java ├── Pair.java ├── Randomized.java └── TestCounter.java ├── expression ├── BaseTest.java ├── DoubleExpression.java ├── DoubleExpressionTest.java ├── Expression.java ├── ExpressionTest.java ├── TripleExpression.java ├── TripleExpressionTest.java ├── exceptions │ ├── ExceptionsAbsSqrtTest.java │ ├── ExceptionsMinMaxTest.java │ ├── ExceptionsPowLog2Test.java │ ├── ExceptionsTest.java │ └── Parser.java └── parser │ ├── Either.java │ ├── Parser.java │ ├── ParserBitwiseTest.java │ ├── ParserNotCountTest.java │ ├── ParserShiftsTest.java │ └── ParserTest.java ├── queue ├── ArrayQueueDequeTest.java ├── ArrayQueueTest.java ├── ArrayQueueToArrayTest.java ├── QueueFunctionsTest.java ├── QueueTest.java └── QueueToArrayTest.java ├── reverse ├── ReverseChecker.java ├── ReverseFastTest.java ├── ReverseMaxTest.java ├── ReverseMinFastTest.java ├── ReverseMinTest.java ├── ReverseSumFastTest.java ├── ReverseSumTest.java ├── ReverseTest.java └── ReverseTransposeTest.java ├── search ├── BinarySearchBaseTest.java ├── BinarySearchMissingTest.java ├── BinarySearchSpanTest.java └── BinarySearchTest.java ├── sum ├── SChecker.java ├── SumAbcFileTest.java ├── SumAbcTest.java ├── SumBigIntegerDigitTest.java ├── SumBigIntegerTest.java ├── SumChecker.java ├── SumFileChecker.java ├── SumFileTest.java ├── SumHexFileTest.java ├── SumHexTest.java └── SumTest.java └── wordStat ├── WordStatChecker.java ├── WordStatIndexChecker.java ├── WordStatIndexTest.java ├── WordStatInputTest.java ├── WordStatLineIndexTest.java └── WordStatWordsTest.java /README.md: -------------------------------------------------------------------------------- 1 | # Тесты к курсу «Программирование» 2 | 3 | Домашнее задание 12. Обработка ошибок 4 | ---- 5 | 1. Добавьте в программу вычисляющую выражения обработку ошибок, в том числе: 6 | * ошибки разбора выражений; 7 | * ошибки вычисления выражений. 8 | 2. Для выражения `1000000*x*x*x*x*x/(x-1)` вывод программы должен иметь следующий вид: 9 | ``` 10 | x f 11 | 0 0 12 | 1 division by zero 13 | 2 32000000 14 | 3 121500000 15 | 4 341333333 16 | 5 overflow 17 | 6 overflow 18 | 7 overflow 19 | 8 overflow 20 | 9 overflow 21 | 10 overflow 22 | ``` 23 | Результат division by zero (overflow) означает, что в процессе вычисления произошло деление на ноль (переполнение). 24 | 3. При выполнении задания следует обратить внимание на дизайн и обработку исключений. 25 | 4. Человеко-читаемые сообщения об ошибках должны выводится на консоль. 26 | 5. Программа не должна «вылетать» с исключениями (как стандартными, так и добавленными). 27 | 28 | Модификации 29 | * *Базовая* 30 | * Класс `ExpressionParser` должен реализовывать интерфейс 31 | [Parser](java/expression/exceptions/Parser.java) 32 | * Классы `CheckedAdd`, `CheckedSubtract`, `CheckedMultiply`, 33 | `CheckedDivide` и `CheckedNegate` должны реализовывать интерфейс 34 | [TripleExpression](java/expression/TripleExpression.java) 35 | * Нельзя использовать типы `long` и `double` 36 | * Нельзя использовать методы классов `Math` и `StrictMath` 37 | * [Исходный код тестов](java/expression/exceptions/ExceptionsTest.java) 38 | * *Простая* 39 | * Дополнительно реализовать унарные операции: 40 | * `log2` — логарифм по уснованию 2, `log2 10` равно 3; 41 | * `pow2` — два в степени, `pow2 4` равно 16. 42 | * [Исходный код тестов](java/expression/exceptions/ExceptionsPowLog2Test.java) 43 | * *Простая* 44 | * Дополнительно реализовать унарные операции: 45 | * `abs` — модуль числа, `abs -5` равно 5; 46 | * `sqrt` — квадратный корень, `sqrt 24` равно 4. 47 | * [Исходный код тестов](java/expression/exceptions/ExceptionsAbsSqrtTest.java) 48 | * *Сложная* 49 | * Реализовать операции простой модификации. 50 | * Дополнительно реализовать бинарные операции (минимальный приоритет): 51 | * `min` — минимум, `2 min 3` равно 2; 52 | * `max` — максимум, `2 max 3` равно 3. 53 | * [Исходный код тестов](java/expression/exceptions/ExceptionsMinMaxTest.java) 54 | 55 | 56 | Домашнее задание 11. Разбор выражений 57 | ---- 58 | 59 | 1. Доработайте предыдущее домашнее задание, так что бы выражение строилось по записи вида: 60 | 61 | x * (x - 2)*x + 1 62 | 63 | 2. В записи выражения могут встречаться: умножение `*`, деление `/`, сложение `+`, вычитание `-`, унарный минус `-`, целочисленные константы (в десятичной системе счисления, которые помещаются в 32-битный знаковый целочисленный тип), круглые скобки, переменные (`x`) и произвольное число пробельных символов в любом месте (но не внутри констант). 64 | 3. Приоритет операторов, начиная с наивысшего 65 | * унарный минус; 66 | * умножение и деление; 67 | * сложение и вычитание. 68 | 4. Разбор выражений рекомендуется производить [методом рекурсивного спуска](https://ru.wikibooks.org/wiki/%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D0%BE%D0%B2/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B2%D0%BD%D0%BE%D0%B3%D0%BE_%D1%81%D0%BF%D1%83%D1%81%D0%BA%D0%B0). Алгоритм должен работать за линейное время. 69 | 70 | Модификации 71 | * *Базовая* 72 | * Класс `ExpressionParser` должен реализовывать интерфейс 73 | [Parser](java/expression/parser/Parser.java) 74 | * Результат разбора должен реализовывать интерфейс 75 | [TripleExpression](java/expression/TripleExpression.java) 76 | * [Исходный код тестов](java/expression/parser/ParserTest.java) 77 | * *Простая* 78 | * Дополнительно реализовать бинарные операции: 79 | * `<<` — сдвиг влево, минимальный приоритет (`1 << 5 + 3` равно `1 << (5 + 3)` равно 256); 80 | * `>>` — сдвиг вправо, минимальный приоритет (`1024 >> 5 + 3` равно `1024 >> (5 + 3)` равно 4); 81 | * [Исходный код тестов](java/expression/parser/ParserShiftsTest.java) 82 | * *Сложная* 83 | * Дополнительно реализовать унарные операции (приоритет как у унарного минуса): 84 | * Дополнительно реализовать бинарные операции: 85 | * `&` — побитное И, приоритет меньше чем у `+` (`6 & 1 + 2` равно `6 & (1 + 2)` равно 2); 86 | * `^` — побитный XOR, приоритет меньше чем у `&` (`6 ^ 1 + 2` равно `6 ^ (1 + 2)` равно 5); 87 | * `|` — побитное ИЛИ, приоритет меньше чем у `^` (`6 | 1 + 2` равно `6 | (1 + 2)` равно 7); 88 | * `~` — побитное отрицание, `~-5` равно 4; 89 | * `count` — число установленных битов, `count -5` равно 31. 90 | * [Исходный код тестов](java/expression/parser/ParserBitwiseTest.java) 91 | * [Исходный код тестов](java/expression/parser/ParserNotCountTest.java) 92 | * *39 группа* 93 | * Дополнительно реализовать операции из простой и сложной модификации. 94 | 95 | Домашнее задание 10. Вычисление выражений 96 | ---- 97 | 1. Разработайте классы Const, Variable, Add, Subtract, Multiply, Divide для вычисления выражений с одной переменной. 98 | 2. Классы должны позволять составлять выражения вида 99 | ``` 100 | new Subtract( 101 | new Multiply( 102 | new Const(2), 103 | new Variable("x") 104 | ), 105 | new Const(3) 106 | ).evaluate(5) 107 | ``` 108 | 109 | 3. При вычислении такого выражения вместо каждой переменной подставляется значение, переданное в качестве параметра методу evaluate (на данном этапе имена переменных игнорируются). Таким образом, результатом вычисления приведенного примера должно стать число 7. 110 | 4. Для тестирования программы должен быть создан класс Main, который вычисляет значение выражения x2−2x+1, для x, заданного в командной строке. 111 | 5. При выполнение задания следует обратить внимание на: 112 | * Выделение общего интерфейса создаваемых классов. 113 | * Выделение абстрактного базового класса для бинарных операций. 114 | Модификации 115 | * *Базовая* 116 | * Реализовать интерфейс [Expression](java/expression/Expression.java) 117 | * [Исходный код тестов](java/expression/ExpressionTest.java) 118 | * *Простая* 119 | * Реализовать интерфейс [DoubleExpression](java/expression/DoubleExpression.java) 120 | * [Исходный код тестов](java/expression/DoubleExpressionTest.java) 121 | * *Сложная* 122 | * Реализовать интерфейсы [DoubleExpression](java/expression/DoubleExpression.java) и [TripleExpression](java/expression/TripleExpression.java) 123 | * [Исходный код тестов](java/expression/TripleExpressionTest.java) 124 | 125 | 126 | Домашнее задание 9. Очередь на связном списке 127 | ---- 128 | 1. Определите интерфейс очереди Queue и опишите его контракт. 129 | 2. Реализуйте класс LinkedQueue — очередь на связном списке. 130 | 3. Выделите общие части классов LinkedQueue и ArrayQueue в базовый класс AbstractQueue. 131 | 132 | Модификации 133 | * *Базовая* 134 | * [Исходный код тестов](java/queue/QueueTest.java) 135 | * [Откомпилированные тесты](artifacts/queue/QueueTest.jar) 136 | * *Простая* 137 | * Добавить в интерфейс очереди и реализовать метод 138 | `toArray`, возвращающий массив, 139 | содержащий элементы, лежащие в очереди в порядке 140 | от головы к хвосту 141 | * Исходная очередь должна оставаться неизменной 142 | * Дублирования кода быть не должно 143 | * [Исходный код тестов](java/queue/QueueToArrayTest.java) 144 | * [Откомпилированные тесты](artifacts/queue/QueueToArrayTest.jar) 145 | * *Сложная* 146 | * Добавить в интерфейс очереди и реализовать методы 147 | * `filter(predicate)` – создать очередь, содержащую элементы, удовлетворяющие 148 | [предикату](https://docs.oracle.com/javase/8/docs/api/java/util/function/Predicate.html) 149 | * `map(function)` – создать очередь, содержащую результаты применения 150 | [функции](https://docs.oracle.com/javase/8/docs/api/java/util/function/Function.html) 151 | * Исходная очередь должна остаться неизменной 152 | * Тип возвращаемой очереди должен соответствовать типу исходной очереди 153 | * Взаимный порядок элементов должен сохраняться 154 | * Дублирования кода быть не должно 155 | * [Исходный код тестов](java/queue/QueueFunctions.java) 156 | * [Откомпилированные тесты](artifacts/queue/QueueFunctionsTest.jar) 157 | 158 | Домашнее задание 8. Очередь на массиве 159 | ---- 160 | 1. Найдите инвариант структуры данных «[очередь](https://ru.wikipedia.org/wiki/%D0%9E%D1%87%D0%B5%D1%80%D0%B5%D0%B4%D1%8C_(%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5))». Определите функции, которые необходимы для реализации очереди. Найдите их пред- и постусловия. 161 | 2. Реализуйте классы, представляющие циклическую очередь с применением массива. 162 | * Класс ArrayQueueModule должен реализовывать один экземпляр очереди с использованием переменных класса. 163 | * Класс ArrayQueueADT должен реализовывать очередь в виде абстрактного типа данных (с явной передачей ссылки на экземпляр очереди). 164 | * Класс ArrayQueue должен реализовывать очередь в виде класса (с неявной передачей ссылки на экземпляр очереди). 165 | 3. Должны быть реализованы следующие функции (процедуры) / методы: 166 | * enqueue – добавить элемент в очередь; 167 | * element – первый элемент в очереди; 168 | * dequeue – удалить и вернуть первый элемент в очереди; 169 | * size – текущий размер очереди; 170 | * isEmpty – является ли очередь пустой; 171 | * clear – удалить все элементы из очереди. 172 | 3. Инвариант, пред- и постусловия записываются в исходном коде в виде комментариев. 173 | 4. Обратите внимание на инкапсуляцию данных и кода во всех трех реализациях. 174 | 5. Напишите тесты реализованным классам. 175 | 176 | Модификации 177 | * *Базовая* 178 | * Классы должны находиться в пакете `queue` 179 | * [Исходный код тестов](java/queue/ArrayQueueTest.java) 180 | * [Откомпилированные тесты](artifacts/queue/ArrayQueueTest.jar) 181 | * *Простая* 182 | * Реализовать метод `toArray`, возвращающий массив, 183 | содержащий элементы, лежащие в очереди в порядке 184 | от головы к хвосту. 185 | * Исходная очередь должна остаться неизменной 186 | * Дублирования кода быть не должно 187 | * [Исходный код тестов](java/queue/ArrayQueueToArrayTest.java) 188 | * [Откомпилированные тесты](artifacts/queue/ArrayQueueToArrayTest.jar) 189 | * *Сложная* 190 | * Реализовать методы 191 | * `push` – добавить элемент в начало очереди 192 | * `peek` – вернуть последний элемент в очереди 193 | * `remove` – вернуть и удалить последний элемент из очереди 194 | * [Исходный код тестов](java/queue/ArrayQueueDequeTest.java) 195 | * [Откомпилированные тесты](artifacts/queue/ArrayQueueDequeTest.jar) 196 | 197 | 198 | Домашнее задание 7. Бинарный поиск 199 | ---- 200 | 1. Реализуйте итеративный и рекурсивный варианты бинарного поиска в массиве. 201 | 2. На вход подается целое число x и массив целых чисел a, отсортированный по невозрастанию. Требуется найти минимальное значение индекса i, при котором a[i] <= x. 202 | 3. Для функций бинарного поиска и вспомогательных функций должны быть указаны, пред- и постусловия. Для реализаций методов должны быть приведены доказательства соблюдения контрактов в терминах троек Хоара. 203 | 4. Интерфейс программы. 204 | * Имя основного класса — `BinarySearch`. 205 | * Первый аргумент командной строки — число x. 206 | * Последующие аргументы командной строки — элементы массива a. 207 | 5. Пример запуска: `java BinarySearch 3 5 4 3 2 1`. Ожидаемый результат: 2. 208 | 209 | Модификации 210 | * *Базовая* 211 | * Класс `BinarySearch` должен находиться в пакете `search` 212 | * [Исходный код тестов](java/search/BinarySearchTest.java) 213 | * [Откомпилированные тесты](artifacts/search/BinarySearchTest.jar) 214 | * *Простая* 215 | * Если в массиве `a` отсутствует элемент, равный `x`, то требуется 216 | вывести индекс вставки в формате, определенном в 217 | [`Arrays.binarySearch`](http://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html#binarySearch-int:A-int-). 218 | * Класс должен иметь имя `BinarySearchMissing` 219 | * [Исходный код тестов](java/search/BinarySearchMissingTest.java) 220 | * [Откомпилированные тесты](artifacts/search/BinarySearchMissingTest.jar) 221 | * *Сложная* 222 | * Требуется вывести два числа: начало и длину диапазона элементов, 223 | равных `x`. Если таких элементов нет, то следует вывести 224 | пустой диапазон, у которого левая граница совпадает с местом 225 | вставки элемента `x`. 226 | * Не допускается использование типов `long` и `BigInteger`. 227 | * Класс должен иметь имя `BinarySearchSpan` 228 | * [Исходный код тестов](java/search/BinarySearchSpanTest.java) 229 | * [Откомпилированные тесты](artifacts/search/BinarySearchSpanTest.jar) 230 | 231 | Домашнее задание 6. Подсчет слов++ 232 | ---- 233 | * Для всех групп нужно использовать самописный `Scanner` 234 | * Группам 36-37 можно использовать по символьное чтение 235 | * Группам 38-39 нужно использовать побайтовое считывание 236 | 237 | Модификации 238 | * *LineIndex* 239 | * В выходном файле слова должны быть упорядочены в лексикографическом порядке 240 | * Вместо номеров вхождений во всем файле надо указывать 241 | `<номер строки>:<номер в строке>` 242 | * Класс должен иметь имя `WordStatLineIndex` 243 | * [Исходный код тестов](java/wordStat/WordStatLineIndexTest.java) 244 | * [Откомпилированные тесты](artifacts/wordStat/WordStatLineIndexTest.jar) 245 | 246 | 247 | 248 | 1. Разработайте класс `WordStatIndex`, который будет подсчитывать статистику встречаемости слов во входном файле. 249 | 2. Словом называется неперывная последовательность букв, апострофов и тире (Unicode category Punctuation, Dash). Для подсчета статистики, слова приводятся к нижнему регистру. 250 | 3. Выходной файл должен содержать все различные слова, встречающиеся во входном файле, в порядке их появения. Для каждого слова должна быть выведена одна строка, содежащая слово, число его вхождений во входной файл и номера вхождений этого слова среди всех слов во входном файле. 251 | 4. Имена входного и выходного файла задаются в качестве аргументов командной строки. Кодировка файлов: UTF-8. 252 | 5. Программа должна работать за линейное от размера входного файлам время. 253 | 6. Для реализации программы используйте `Collections Framework`. 254 | 7. Примеры работы программы: 255 | ``` 256 | Входной файл: 257 | To be, or not to be, that is the question: 258 | Выходной файл: 259 | to 2 1 5 260 | be 2 2 6 261 | or 1 3 262 | not 1 4 263 | that 1 7 264 | is 1 8 265 | the 1 9 266 | question 1 10 267 | Входной файл: 268 | Monday's child is fair of face. 269 | Tuesday's child is full of grace. 270 | Выходной файл: 271 | monday's 1 1 272 | child 2 2 8 273 | is 2 3 9 274 | fair 1 4 275 | of 2 5 11 276 | face 1 6 277 | tuesday's 1 7 278 | full 1 10 279 | grace 1 12 280 | Входной файл: 281 | Шалтай-Болтай 282 | Сидел на стене. 283 | Шалтай-Болтай 284 | Свалился во сне. 285 | Выходной файл: 286 | шалтай-болтай 2 1 5 287 | сидел 1 2 288 | на 1 3 289 | стене 1 4 290 | свалился 1 6 291 | во 1 7 292 | сне 1 8 293 | ``` 294 | 295 | Исходный код тестов: 296 | 297 | * [WordStatIndexTest.java](java/wordStat/WordStatIndexTest.java) 298 | * [WordStatIndexChecker.java](java/wordStat/WordStatIndexChecker.java) 299 | 300 | Откомпилированные тесты: [WordStatIndexTest.jar](artifacts/wordStat/WordStatIndexTest.jar) 301 | 302 | 303 | Домашнее задание 5. Быстрый реверс 304 | ---- 305 | * Для групп 36-39 надо написать `Scanner` используя побайтовое считывание, то есть нельзя использовать `BufferedReader` и аналоги! 306 | * Для групп 38-39 запрешено использовать регулярные выражения, функцию `split`, класс `StringTokenizer` и аналоги. 307 | 308 | Модификации 309 | * *Минимум* 310 | * Рассмотрим входные данные как (не полностью определенную) матрицу, 311 | вместо каждого числа выведите минимум из чисел в его столбце и строке. 312 | * Сравнить время работы вашего сканера и встроенного в java 313 | * Класс должен иметь имя `ReverseMin` 314 | * [Исходный код тестов](java/reverse/ReverseMinFastTest.java) 315 | * [Откомпилированные тесты](artifacts/reverse/ReverseMinFastTest.jar) 316 | * *Сумма* 317 | * Рассмотрим входные данные как (не полностью определенную) матрицу, 318 | вместо каждого числа выведите сумму чисел в его столбце и строке. 319 | * Класс должен иметь имя `ReverseSum` 320 | * [Исходный код тестов](java/reverse/ReverseSumFastTest.java) 321 | * [Откомпилированные тесты](artifacts/reverse/ReverseSumFastTest.jar) 322 | 323 | 324 | 1. Реализуйте свой аналог класса `Scanner`. Разработайте класс Reverse, читающий числа из стандартного входа, и выводящий их на стандартный вывод в обратном порядке. 325 | 2. Примените разработанный `Scanner` для решения задания "Реверc". 326 | 3. Модифицируйте решени задания "Реверc" так, что бы оно работало за линейное время. 327 | Исходный код тестов: 328 | 329 | * [ReverseFastTest.java](java/reverse/ReverseFastTest.java) 330 | * [ReverseChecker.java](java/reverse/ReverseChecker.java) 331 | 332 | Откомпилированные тесты: [ReverseFastTest.jar](artifacts/reverse/ReverseFastTest.jar) 333 | 334 | 335 | 336 | 337 | Домашнее задание 4. Подсчет слов 338 | ---- 339 | Модификации 340 | * *Words* 341 | * В выходном файле слова должны быть упорядочены в лексикографическом порядке 342 | * Класс должен иметь имя `WordStatWords` 343 | * [Исходный код тестов](java/wordStat/WordStatWordsTest.java) 344 | * [Откомпилированные тесты](artifacts/wordStat/WordStatWordsTest.jar) 345 | 346 | 1. Разработайте класс `WordStatInput`, который будет подсчитывать статистику встречаемости слов во входном файле. 347 | 2. Словом называется неперывная последовательность букв, апострофов и тире (Unicode category Punctuation, Dash). Для подсчета статистики, слова приводятся к нижнему регистру. 348 | 3. Выходной файл должен содержать все различные слова, встречающиеся во входном файле, в порядке их появения. Для каждого слова должна быть выведена одна строка, содежащая слово и число его вхождений во входной файл. 349 | 4. Имена входного и выходного файла задаются в качестве аргументов командной строки. Кодировка файлов: UTF-8. 350 | 5. Примеры работы программы: 351 | ``` 352 | Входной файл: 353 | To be, or not to be, that is the question: 354 | Выходной файл: 355 | to 2 356 | be 2 357 | or 1 358 | not 1 359 | that 1 360 | is 1 361 | the 1 362 | question 1 363 | Входной файл: 364 | Monday's child is fair of face. 365 | Tuesday's child is full of grace. 366 | Выходной файл: 367 | monday's 1 368 | child 2 369 | is 2 370 | fair 1 371 | of 2 372 | face 1 373 | tuesday's 1 374 | full 1 375 | grace 1 376 | Входной файл: 377 | Шалтай-Болтай 378 | Сидел на стене. 379 | Шалтай-Болтай 380 | Свалился во сне. 381 | Выходной файл: 382 | шалтай-болтай 2 383 | сидел 1 384 | на 1 385 | стене 1 386 | свалился 1 387 | во 1 388 | сне 1 389 | ``` 390 | 391 | Исходный код тестов: 392 | 393 | * [WordStatInputTest.java](java/wordStat/WordStatInputTest.java) 394 | * [WordStatChecker.java](java/wordStat/WordStatChecker.java) 395 | 396 | Откомпилированные тесты: [WordStatInputTest.jar](artifacts/wordStat/WordStatInputTest.jar) 397 | 398 | 399 | Домашнее задание 3. Сумма чисел в файле 400 | ---- 401 | Модификации 402 | * *Abc* 403 | * На вход подаются числа, представленные буквами. 404 | Нулю соответствует буква `a`, единице – `b` и так далее 405 | * Ввод регистронезависим 406 | * Класс должен иметь имя `SumAbcFile` 407 | * [Исходный код тестов](java/sum/SumAbcFileTest.java) 408 | * [Откомпилированные тесты](artifacts/sum/SumAbcFileTest.jar) 409 | * *Hex* 410 | * На вход подаются десятичные и шестнадцатеричные числа 411 | * Шестнадцатеричные числа имеют префикс `0x` 412 | * Ввод регистронезависим 413 | * Класс должен иметь имя `SumHexFile` 414 | * [Исходный код тестов](java/sum/SumHexFileTest.java) 415 | * [Откомпилированные тесты](artifacts/sum/SumHexFileTest.jar) 416 | 417 | 1. Разработайте класс `SumFile`, записывающий сумму чисел из входного файла в выходной файл. 418 | 2. Числа во входном файле разделены переводами строк и/или пробельными символами. 419 | 3. Имена входного и выходного файла задаются в качестве аргументов командной строки. 420 | 4. Примеры работы программы: 421 | ``` 422 | Входной файл: 423 | 1 2 3 424 | Выходной файл: 425 | 6 426 | Входной файл: 427 | 1 2 -3 428 | Выходной файл: 429 | 0 430 | Входной файл: 431 | 1 2 432 | 3 433 | Выходной файл: 434 | 6 435 | ``` 436 | 5. При выполнении задания можно считать что для представления входных данных и промежуточных результатов достаточен тип `int`. 437 | 6. В этом и последующих домашних заданиях, метод main не должен выбрасывать никаких исключений при любых (в том числе некорректных) входных данных. 438 | 7. В этом и последующих домашних заданиях, все ресурсы должны закрываться при любых (в том числе некорректных) входных данных. 439 | Исходный код тестов: 440 | 441 | * [SumFileTest.java](java/sum/SumFileTest.java) 442 | * [SumFileChecker.java](java/sum/SumFileChecker.java) 443 | 444 | Откомпилированные тесты: [SumFileTest.jar](artifacts/sum/SumFileTest.jar) 445 | 446 | 447 | ## Домашнее задание 2. Реверс 448 | Модификации 449 | * *Транспозиция* 450 | * Рассмотрим входные данные как (не полностью определенную) матрицу, 451 | выведите ее в транспонированном виде 452 | * Класс должен иметь имя `ReverseTranspose` 453 | * [Исходный код тестов](java/reverse/ReverseTransposeTest.java) 454 | * [Откомпилированные тесты](artifacts/reverse/ReverseTransposeTest.jar) 455 | * *Максимум* 456 | * Рассмотрим входные данные как (не полностью определенную) матрицу, 457 | вместо каждого числа выведите максимум из чисел в его столбце и строке. 458 | * Класс должен иметь имя `ReverseMax` 459 | * [Исходный код тестов](java/reverse/ReverseMaxTest.java) 460 | * [Откомпилированные тесты](artifacts/reverse/ReverseMaxTest.jar) 461 | 462 | 463 | 464 | 1. Разработайте класс `Reverse`, читающий числа из стандартного входа, и выводящий их на стандартный вывод в обратном порядке. 465 | 2. В каждой строке входа содержится некоторое количество целых чисел (может быть 0). Числа разделены пробелами. Каждое число помещается в тип `int`. 466 | 3. Порядок строк в выходе должен быть обратным по сравнению с порядком строк во входе. Порядок чисел в каждой строки так же должен быть обратным к порядку чисел во входе. 467 | 4. Примеры работы программы: 468 | ``` 469 | Вход: 470 | 1 2 471 | 3 472 | Выход: 473 | 3 474 | 2 1 475 | Вход: 476 | 1 477 | 478 | 2 -3 479 | Выход: 480 | -3 2 481 | 482 | 1 483 | ``` 484 | Исходный код тестов: 485 | 486 | * [ReverseTest.java](java/reverse/ReverseTest.java) 487 | * [ReverseChecker.java](java/reverse/ReverseChecker.java) 488 | 489 | Откомпилированные тесты: [ReverseTest.jar](artifacts/reverse/ReverseTest.jar) 490 | 491 | 492 | ## Домашнее задание 1. Сумма чисел 493 | 494 | * *SumHex* 495 | * Входные данные помещаются в тип `int` либо десятичные, либо шестнадцатиричное начинается с `0x` 496 | * Класс должен иметь имя `SumHex` 497 | * Нельзя использоваться классы `Long` и `BigInteger` 498 | * [Исходный код тестов](java/sum/SumHexTest.java) 499 | * [Откомпилированные тесты](artifacts/sum/SumHexTest.jar) 500 | 501 | * *BigIntegerDigit* 502 | * Входные данные помещаются в тип [BigInteger](https://docs.oracle.com/javase/8/docs/api/java/math/BigInteger.html) 503 | * Класс должен иметь имя `SumBigInteger` 504 | * Числа имеют вид `[знак]цифры` 505 | * [Исходный код тестов](java/sum/SumBigIntegerDigitTest.java) 506 | * [Откомпилированные тесты](artifacts/sum/SumBigIntegerDigitTest.jar) 507 | 508 | 509 | 1. Разработайте класс `Sum`, который при запуске из командной строки будет складывать переданные в качестве аргументов целые числа и выводить их сумму на консоль. 510 | 2. Примеры запуска программы: 511 | ``` 512 | java Sum 1 2 3 513 | Результат: 6 514 | java Sum 1 2 -3 515 | Результат: 0 516 | java Sum "1 2 3" 517 | Результат: 6 518 | java Sum "1 2" " 3" 519 | Результат: 6 520 | ``` 521 | Аргументы могут содержать цифры и произвольные [пробельные символы](https://docs.oracle.com/javase/8/docs/api/java/lang/Character.html#isWhitespace-char-). 522 | 3. При выполнении задания можно считать что для представления входных данных и промежуточных результатов достаточен тип `int`. 523 | 4. При выполнении задания полезно ознакомиться с документацией к классам [String](http://download.oracle.com/javase/8/docs/api/java/lang/String.html) и [Integer](http://download.oracle.com/javase/8/docs/api/java/lang/Integer.html). 524 | 525 | Для того, чтобы протестировать исходную программу: 526 | 527 | 1. Скачайте откомпилированные тесты ([SumTest.jar](artifacts/sum/SumTest.jar)) 528 | 2. Откомпилируйте `Sum.java` 529 | 3. Проверьте, что создался `Sum.class` 530 | 4. В каталоге, в котором находится `Sum.class` выполните команду 531 | ``` 532 | java -jar <путь к SumTest.jar> 533 | ``` 534 | * Например, если `SumTest.jar` находится в текущем каталоге, выполните команду 535 | ``` 536 | java -jar SumTest.jar 537 | ``` 538 | 539 | Исходный код тестов: 540 | 541 | * [SumTest.java](java/sum/SumTest.java) 542 | * [SumChecker.java](java/sum/SumChecker.java) 543 | * [SChecker.java](java/sum/SChecker.java) 544 | * [Базовые классы](java/base/) 545 | -------------------------------------------------------------------------------- /artifacts/queue/ArrayQueueDequeTest.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vedernikov/itmo-java-2018/c5b248b610329c7153e0bbacc48f772249ff0823/artifacts/queue/ArrayQueueDequeTest.jar -------------------------------------------------------------------------------- /artifacts/queue/ArrayQueueTest.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vedernikov/itmo-java-2018/c5b248b610329c7153e0bbacc48f772249ff0823/artifacts/queue/ArrayQueueTest.jar -------------------------------------------------------------------------------- /artifacts/queue/ArrayQueueToArrayTest.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vedernikov/itmo-java-2018/c5b248b610329c7153e0bbacc48f772249ff0823/artifacts/queue/ArrayQueueToArrayTest.jar -------------------------------------------------------------------------------- /artifacts/queue/QueueFunctionsTest.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vedernikov/itmo-java-2018/c5b248b610329c7153e0bbacc48f772249ff0823/artifacts/queue/QueueFunctionsTest.jar -------------------------------------------------------------------------------- /artifacts/queue/QueueTest.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vedernikov/itmo-java-2018/c5b248b610329c7153e0bbacc48f772249ff0823/artifacts/queue/QueueTest.jar -------------------------------------------------------------------------------- /artifacts/queue/QueueToArrayTest.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vedernikov/itmo-java-2018/c5b248b610329c7153e0bbacc48f772249ff0823/artifacts/queue/QueueToArrayTest.jar -------------------------------------------------------------------------------- /artifacts/reverse/ReverseFastTest.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vedernikov/itmo-java-2018/c5b248b610329c7153e0bbacc48f772249ff0823/artifacts/reverse/ReverseFastTest.jar -------------------------------------------------------------------------------- /artifacts/reverse/ReverseMaxTest.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vedernikov/itmo-java-2018/c5b248b610329c7153e0bbacc48f772249ff0823/artifacts/reverse/ReverseMaxTest.jar -------------------------------------------------------------------------------- /artifacts/reverse/ReverseMinFastTest.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vedernikov/itmo-java-2018/c5b248b610329c7153e0bbacc48f772249ff0823/artifacts/reverse/ReverseMinFastTest.jar -------------------------------------------------------------------------------- /artifacts/reverse/ReverseSumFastTest.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vedernikov/itmo-java-2018/c5b248b610329c7153e0bbacc48f772249ff0823/artifacts/reverse/ReverseSumFastTest.jar -------------------------------------------------------------------------------- /artifacts/reverse/ReverseTest.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vedernikov/itmo-java-2018/c5b248b610329c7153e0bbacc48f772249ff0823/artifacts/reverse/ReverseTest.jar -------------------------------------------------------------------------------- /artifacts/reverse/ReverseTransposeTest.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vedernikov/itmo-java-2018/c5b248b610329c7153e0bbacc48f772249ff0823/artifacts/reverse/ReverseTransposeTest.jar -------------------------------------------------------------------------------- /artifacts/search/BinarySearchMissingTest.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vedernikov/itmo-java-2018/c5b248b610329c7153e0bbacc48f772249ff0823/artifacts/search/BinarySearchMissingTest.jar -------------------------------------------------------------------------------- /artifacts/search/BinarySearchSpanTest.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vedernikov/itmo-java-2018/c5b248b610329c7153e0bbacc48f772249ff0823/artifacts/search/BinarySearchSpanTest.jar -------------------------------------------------------------------------------- /artifacts/search/BinarySearchTest.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vedernikov/itmo-java-2018/c5b248b610329c7153e0bbacc48f772249ff0823/artifacts/search/BinarySearchTest.jar -------------------------------------------------------------------------------- /artifacts/sum/SumAbcFileTest.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vedernikov/itmo-java-2018/c5b248b610329c7153e0bbacc48f772249ff0823/artifacts/sum/SumAbcFileTest.jar -------------------------------------------------------------------------------- /artifacts/sum/SumAbcTest.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vedernikov/itmo-java-2018/c5b248b610329c7153e0bbacc48f772249ff0823/artifacts/sum/SumAbcTest.jar -------------------------------------------------------------------------------- /artifacts/sum/SumBigIntegerDigitTest.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vedernikov/itmo-java-2018/c5b248b610329c7153e0bbacc48f772249ff0823/artifacts/sum/SumBigIntegerDigitTest.jar -------------------------------------------------------------------------------- /artifacts/sum/SumFileTest.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vedernikov/itmo-java-2018/c5b248b610329c7153e0bbacc48f772249ff0823/artifacts/sum/SumFileTest.jar -------------------------------------------------------------------------------- /artifacts/sum/SumHexFileTest.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vedernikov/itmo-java-2018/c5b248b610329c7153e0bbacc48f772249ff0823/artifacts/sum/SumHexFileTest.jar -------------------------------------------------------------------------------- /artifacts/sum/SumHexTest.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vedernikov/itmo-java-2018/c5b248b610329c7153e0bbacc48f772249ff0823/artifacts/sum/SumHexTest.jar -------------------------------------------------------------------------------- /artifacts/sum/SumTest.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vedernikov/itmo-java-2018/c5b248b610329c7153e0bbacc48f772249ff0823/artifacts/sum/SumTest.jar -------------------------------------------------------------------------------- /artifacts/wordStat/WordStatCountTest.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vedernikov/itmo-java-2018/c5b248b610329c7153e0bbacc48f772249ff0823/artifacts/wordStat/WordStatCountTest.jar -------------------------------------------------------------------------------- /artifacts/wordStat/WordStatIndexTest.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vedernikov/itmo-java-2018/c5b248b610329c7153e0bbacc48f772249ff0823/artifacts/wordStat/WordStatIndexTest.jar -------------------------------------------------------------------------------- /artifacts/wordStat/WordStatInputTest.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vedernikov/itmo-java-2018/c5b248b610329c7153e0bbacc48f772249ff0823/artifacts/wordStat/WordStatInputTest.jar -------------------------------------------------------------------------------- /artifacts/wordStat/WordStatLineIndexTest.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vedernikov/itmo-java-2018/c5b248b610329c7153e0bbacc48f772249ff0823/artifacts/wordStat/WordStatLineIndexTest.jar -------------------------------------------------------------------------------- /artifacts/wordStat/WordStatWordsTest.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vedernikov/itmo-java-2018/c5b248b610329c7153e0bbacc48f772249ff0823/artifacts/wordStat/WordStatWordsTest.jar -------------------------------------------------------------------------------- /java/base/Asserts.java: -------------------------------------------------------------------------------- 1 | package base; 2 | 3 | import java.util.Locale; 4 | import java.util.Objects; 5 | 6 | /** 7 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 8 | */ 9 | public class Asserts { 10 | static { 11 | Locale.setDefault(Locale.US); 12 | } 13 | 14 | public static void assertEquals(final String message, final Object expected, final Object actual) { 15 | assertTrue(String.format("%s:%n expected `%s`,%n actual `%s`", message, expected, actual), Objects.equals(expected, actual)); 16 | } 17 | 18 | public static void assertTrue(final String message, final boolean value) { 19 | if (!value) { 20 | throw new AssertionError(message); 21 | } 22 | } 23 | 24 | public static void assertEquals(final String message, final int expected, final int actual) { 25 | assertTrue(String.format("%s: Expected %d, found %d", message, expected, actual), actual == expected); 26 | } 27 | 28 | public static void assertEquals(final String message, final double precision, final double expected, final double actual) { 29 | assertTrue( 30 | String.format("%s: Expected %.12f, found %.12f", message, expected, actual), 31 | Math.abs(actual - expected) < precision || 32 | Math.abs(actual - expected) < precision * Math.abs(actual) || 33 | (Double.isNaN(actual) || Double.isInfinite(actual)) && 34 | (Double.isNaN(expected) || Double.isInfinite(expected)) 35 | ); 36 | } 37 | 38 | public static void checkAssert(final Class c) { 39 | if (!c.desiredAssertionStatus()) { 40 | throw new AssertionError("You should enable assertions by running 'java -ea " + c.getName() + "'"); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /java/base/MainChecker.java: -------------------------------------------------------------------------------- 1 | package base; 2 | 3 | import java.io.*; 4 | import java.lang.reflect.InvocationTargetException; 5 | import java.lang.reflect.Method; 6 | import java.net.URL; 7 | import java.net.URLClassLoader; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | /** 12 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 13 | */ 14 | public class MainChecker extends Randomized { 15 | public static final String ENCODING = "utf8"; 16 | private final Method method; 17 | protected final TestCounter counter = new TestCounter(); 18 | 19 | public MainChecker(final String className) { 20 | try { 21 | final URL url = new File(".").toURI().toURL(); 22 | final Class clazz = new URLClassLoader(new URL[]{url}).loadClass(className); 23 | // clazz.newInstance(); 24 | method = clazz.getMethod("main", String[].class); 25 | } catch (final Exception e) { 26 | throw new AssertionError("Could not found main(String[]) in class " + className, e); 27 | } 28 | } 29 | 30 | public List run(final String... input) { 31 | counter.nextTest(); 32 | System.err.format("Running test %02d: java %s \"%s\"\n", counter.getTest(), method.getDeclaringClass().getName(), join(input)); 33 | final ByteArrayOutputStream out = new ByteArrayOutputStream(); 34 | final PrintStream oldOut = System.out; 35 | try { 36 | System.setOut(new PrintStream(out, false, ENCODING)); 37 | method.invoke(null, new Object[]{input}); 38 | final BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(out.toByteArray()), ENCODING)); 39 | final List result = new ArrayList<>(); 40 | while (true) { 41 | final String line = reader.readLine(); 42 | if (line == null) { 43 | if (result.isEmpty()) { 44 | result.add(""); 45 | } 46 | return result; 47 | } 48 | result.add(line.trim()); 49 | } 50 | } catch (final InvocationTargetException e) { 51 | throw new AssertionError(e.getCause()); 52 | } catch (final Exception e) { 53 | throw new AssertionError(e); 54 | } finally { 55 | System.setOut(oldOut); 56 | } 57 | } 58 | 59 | private String join(final String[] input) { 60 | final StringBuilder sb = new StringBuilder(); 61 | for (final String s : input) { 62 | if (sb.length() > 0) { 63 | sb.append("\" \""); 64 | } 65 | sb.append(s); 66 | } 67 | return sb.toString(); 68 | } 69 | 70 | public void checkEquals(final List expected, final List actual) { 71 | for (int i = 0; i < Math.min(expected.size(), actual.size()); i++) { 72 | final String exp = expected.get(i); 73 | final String act = actual.get(i); 74 | if (!exp.equalsIgnoreCase(act)) { 75 | Asserts.assertEquals("Line " + (i + 1), exp, act); 76 | return; 77 | } 78 | } 79 | Asserts.assertEquals("Number of lines", expected.size(), actual.size()); 80 | counter.passed(); 81 | } 82 | 83 | public void printStatus() { 84 | counter.printStatus(getClass()); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /java/base/MainFilesChecker.java: -------------------------------------------------------------------------------- 1 | package base; 2 | 3 | import java.io.IOException; 4 | import java.nio.file.Files; 5 | import java.nio.file.Path; 6 | import java.nio.file.Paths; 7 | import java.util.List; 8 | 9 | /** 10 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 11 | */ 12 | public class MainFilesChecker extends MainChecker { 13 | public MainFilesChecker(final String className) { 14 | super(className); 15 | } 16 | 17 | private Path getFile(final String suffix) { 18 | return Paths.get(String.format("test%d.%s", counter.getTest() + 1, suffix)); 19 | } 20 | 21 | protected List runFiles(final List input) { 22 | try { 23 | final Path inf = getFile("in"); 24 | final Path ouf = getFile("out"); 25 | Files.write(inf, input); 26 | run(inf.toString(), ouf.toString()); 27 | final List output = Files.readAllLines(ouf); 28 | Files.delete(inf); 29 | Files.delete(ouf); 30 | return output; 31 | } catch (IOException e) { 32 | throw new AssertionError(e); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /java/base/MainStdChecker.java: -------------------------------------------------------------------------------- 1 | package base; 2 | 3 | import java.io.*; 4 | import java.util.List; 5 | 6 | /** 7 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 8 | */ 9 | public class MainStdChecker extends MainChecker { 10 | 11 | public MainStdChecker(final String className) { 12 | super(className); 13 | } 14 | 15 | protected List runStd(final List input) { 16 | final InputStream oldIn = System.in; 17 | final ByteArrayOutputStream baos = new ByteArrayOutputStream(); 18 | try (final PrintWriter writer = new PrintWriter(baos)) { 19 | input.forEach(writer::println); 20 | } 21 | 22 | try { 23 | System.setIn(new ByteArrayInputStream(baos.toByteArray())); 24 | return run(); 25 | } finally { 26 | System.setIn(oldIn); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /java/base/Pair.java: -------------------------------------------------------------------------------- 1 | package base; 2 | 3 | import java.util.Map; 4 | 5 | /** 6 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 7 | */ 8 | public class Pair { 9 | public final F first; 10 | public final S second; 11 | 12 | public Pair(final F first, final S second) { 13 | this.first = first; 14 | this.second = second; 15 | } 16 | 17 | public static Pair of(final F first, final S second) { 18 | return new Pair<>(first, second); 19 | } 20 | 21 | public static Pair of(final Map.Entry e) { 22 | return of(e.getKey(), e.getValue()); 23 | } 24 | 25 | @Override 26 | public boolean equals(final Object o) { 27 | if (this == o) return true; 28 | if (o == null || getClass() != o.getClass()) return false; 29 | 30 | final Pair pair = (Pair) o; 31 | 32 | return first.equals(pair.first) && second.equals(pair.second); 33 | } 34 | 35 | @Override 36 | public int hashCode() { 37 | int result = first.hashCode(); 38 | result = 31 * result + second.hashCode(); 39 | return result; 40 | } 41 | 42 | @Override 43 | public String toString() { 44 | return first + ": " + second; 45 | } 46 | 47 | public F getFirst() { 48 | return first; 49 | } 50 | 51 | public S getSecond() { 52 | return second; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /java/base/Randomized.java: -------------------------------------------------------------------------------- 1 | package base; 2 | 3 | import java.util.List; 4 | import java.util.Random; 5 | 6 | /** 7 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 8 | */ 9 | public class Randomized { 10 | public static final String ENGLISH = "abcdefghijklmnopqrstuvwxyz"; 11 | public static final String RUSSIAN = "абвгдеежзийклмнопрстуфхцчшщъыьэюя"; 12 | public static final String GREEK = "αβγŋδεζηθικλμνξοπρτυφχψω"; 13 | 14 | public final Random random = new Random(8045702385702345702L); 15 | 16 | public String randomString(final String chars) { 17 | return randomChar(chars) + (random.nextBoolean() ? "" : randomString(chars)); 18 | } 19 | 20 | public char randomChar(final String chars) { 21 | return chars.charAt(random.nextInt(chars.length())); 22 | } 23 | 24 | public String randomString(final String chars, final int length) { 25 | final StringBuilder string = new StringBuilder(); 26 | for (int i = 0; i < length; i++) { 27 | string.append(randomChar(chars)); 28 | } 29 | return string.toString(); 30 | } 31 | 32 | public String randomString(final String chars, final int minLength, int maxLength) { 33 | return randomString(chars, randomInt(minLength, maxLength + 1)); 34 | } 35 | 36 | public int randomInt(final int min, final int max) { 37 | return random.nextInt(max - min) + min; 38 | } 39 | 40 | @SafeVarargs 41 | public final T randomItem(final T... items) { 42 | return items[random.nextInt(items.length)]; 43 | } 44 | 45 | public final T randomItem(final List items) { 46 | return items.get(random.nextInt(items.size())); 47 | } 48 | 49 | public Random getRandom() { 50 | return random; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /java/base/TestCounter.java: -------------------------------------------------------------------------------- 1 | package base; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.net.URI; 6 | import java.net.URISyntaxException; 7 | import java.net.URL; 8 | import java.text.SimpleDateFormat; 9 | import java.util.Date; 10 | import java.util.jar.JarEntry; 11 | import java.util.jar.JarFile; 12 | 13 | /** 14 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 15 | */ 16 | public class TestCounter { 17 | private long start = System.currentTimeMillis(); 18 | private int total = 0; 19 | private int passed = 0; 20 | 21 | public void nextTest() { 22 | total++; 23 | } 24 | 25 | public int getTest() { 26 | return total; 27 | } 28 | 29 | public void passed() { 30 | passed++; 31 | } 32 | 33 | public void printStatus(final Class aClass) { 34 | System.err.println("==========================================="); 35 | System.err.format("Test run: %d, passed: %d, failed: %d%n", total, passed, total - passed); 36 | System.err.format("Finished in %d ms%n", System.currentTimeMillis() - start); 37 | if (total != passed) { 38 | System.err.println("TESTS FAILED"); 39 | System.exit(1); 40 | } 41 | System.err.println("Version: " + getVersion(aClass)); 42 | } 43 | 44 | 45 | public static String getVersion(final Class clazz) { 46 | try { 47 | ClassLoader cl = clazz.getClassLoader(); 48 | URL url = cl.getResource(clazz.getName().replace('.', '/') + ".class"); 49 | if (url == null) { 50 | return "(no manifest)"; 51 | } else { 52 | String path = url.getPath(); 53 | String jarExt = ".jar"; 54 | int index = path.indexOf(jarExt); 55 | SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss"); 56 | if (index != -1) { 57 | String jarPath = path.substring(0, index + jarExt.length()); 58 | File file = new File(jarPath); 59 | String jarVersion = file.getName(); 60 | try (JarFile jarFile = new JarFile(new File(new URI(jarPath)))) { 61 | JarEntry entry = jarFile.getJarEntry("META-INF/MANIFEST.MF"); 62 | return sdf.format(new Date(entry.getTime())); 63 | } 64 | } else { 65 | return sdf.format(new Date(new File(path).lastModified())); 66 | } 67 | } 68 | } catch (IOException | URISyntaxException e) { 69 | return "error: " + e.toString(); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /java/expression/BaseTest.java: -------------------------------------------------------------------------------- 1 | package expression; 2 | 3 | import base.Asserts; 4 | import base.TestCounter; 5 | 6 | import java.util.*; 7 | import java.util.stream.Collectors; 8 | import java.util.stream.Stream; 9 | 10 | /** 11 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 12 | */ 13 | public abstract strictfp class BaseTest extends Asserts { 14 | public final Random random = new Random(7240958270458L); 15 | 16 | protected final TestCounter counter = new TestCounter(); 17 | 18 | protected BaseTest() { 19 | Locale.setDefault(Locale.US); 20 | 21 | checkAssert(getClass()); 22 | } 23 | 24 | public static String repeat(final String s, final int n) { 25 | return Stream.generate(() -> s).limit(n).collect(Collectors.joining()); 26 | } 27 | 28 | public T random(final List variants) { 29 | return variants.get(random.nextInt(variants.size())); 30 | } 31 | 32 | public int randomInt(final int n) { 33 | return random.nextInt(n); 34 | } 35 | 36 | public void run() { 37 | System.out.println("=== Testing " + getClass().getSimpleName()); 38 | test(); 39 | counter.printStatus(getClass()); 40 | } 41 | 42 | protected abstract void test(); 43 | 44 | @SafeVarargs 45 | public static List list(final T... items) { 46 | return new ArrayList<>(Arrays.asList(items)); 47 | } 48 | 49 | public static void addRange(final List values, final int d, final int c) { 50 | for (int i = -d; i <= d; i++) { 51 | values.add(c + i); 52 | } 53 | } 54 | 55 | public static final class Op { 56 | public final String name; 57 | public final T f; 58 | 59 | private Op(final String name, final T f) { 60 | this.name = name; 61 | this.f = f; 62 | } 63 | } 64 | 65 | public static Op op(final String name, final T f) { 66 | return new Op<>(name, f); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /java/expression/DoubleExpression.java: -------------------------------------------------------------------------------- 1 | package expression; 2 | 3 | /** 4 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 5 | */ 6 | public strictfp interface DoubleExpression { 7 | double evaluate(double x); 8 | } 9 | -------------------------------------------------------------------------------- /java/expression/DoubleExpressionTest.java: -------------------------------------------------------------------------------- 1 | package expression; 2 | 3 | /** 4 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 5 | */ 6 | public class DoubleExpressionTest extends ExpressionTest { 7 | public static void main(final String[] args) { 8 | new DoubleExpressionTest().run(); 9 | } 10 | 11 | @Override 12 | protected void test() { 13 | super.test(); 14 | 15 | testExpression("10", new Const(10), x -> 10); 16 | testExpression("x", new Variable("x"), x -> x); 17 | testExpression("x+2", new Add(new Variable("x"), new Const(2)), x -> x + 2); 18 | testExpression("2-x", new Subtract(new Const(2), new Variable("x")), x -> 2 - x); 19 | testExpression("3*x", new Multiply(new Const(3), new Variable("x")), x -> 3*x); 20 | testExpression("x/-2", new Divide(new Variable("x"), new Const(-2)), x -> -x / 2); 21 | testExpression( 22 | "x*x+(x-1)/10", 23 | new Add( 24 | new Multiply(new Variable("x"), new Variable("x")), 25 | new Divide(new Subtract(new Variable("x"), new Const(1)), new Const(10)) 26 | ), 27 | x -> x * x + (x - 1) / 10 28 | ); 29 | testExpression("x*-1_000_000_000", new Multiply(new Variable("x"), new Const(-1_000_000_000)), x -> x * -1_000_000_000.0); 30 | testExpression("10/x", new Divide(new Const(10), new Variable("x")), x -> 10.0 / x); 31 | testExpression("x/x", new Divide(new Variable("x"), new Variable("x")), x -> x / x); 32 | } 33 | 34 | private static void testExpression(final String description, final DoubleExpression actual, final DoubleExpression expected) { 35 | System.out.println("Testing " + description); 36 | for (int i = 0; i < 10; i++) { 37 | check(i, actual, expected); 38 | check(-i, actual, expected); 39 | } 40 | } 41 | 42 | private static void check(final int x, final DoubleExpression actual, final DoubleExpression expected) { 43 | assertEquals(String.format("f(%d)", x), expected.evaluate(x), actual.evaluate(x)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /java/expression/Expression.java: -------------------------------------------------------------------------------- 1 | package expression; 2 | 3 | /** 4 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 5 | */ 6 | public interface Expression { 7 | int evaluate(int x); 8 | } 9 | -------------------------------------------------------------------------------- /java/expression/ExpressionTest.java: -------------------------------------------------------------------------------- 1 | package expression; 2 | 3 | /** 4 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 5 | */ 6 | public class ExpressionTest extends BaseTest { 7 | public static void main(final String[] args) { 8 | new ExpressionTest().run(); 9 | } 10 | 11 | @Override 12 | protected void test() { 13 | testExpression("10", new Const(10), x -> 10); 14 | testExpression("x", new Variable("x"), x -> x); 15 | testExpression("x+2", new Add(new Variable("x"), new Const(2)), x -> x + 2); 16 | testExpression("2-x", new Subtract(new Const(2), new Variable("x")), x -> 2 - x); 17 | testExpression("3*x", new Multiply(new Const(3), new Variable("x")), x -> 3*x); 18 | testExpression("x/-2", new Divide(new Variable("x"), new Const(-2)), x -> -x / 2); 19 | testExpression( 20 | "x*x+(x-1)/10", 21 | new Add( 22 | new Multiply(new Variable("x"), new Variable("x")), 23 | new Divide(new Subtract(new Variable("x"), new Const(1)), new Const(10)) 24 | ), 25 | x -> x * x + (x - 1) / 10 26 | ); 27 | testExpression("x*-1_000_000_000", new Multiply(new Variable("x"), new Const(-1_000_000_000)), x -> x * -1_000_000_000); 28 | testExpression("10/x", new Divide(new Const(10), new Variable("x")), x -> 10 / x); 29 | testExpression("x/x", new Divide(new Variable("x"), new Variable("x")), x -> x / x); 30 | } 31 | 32 | private void testExpression(final String description, final Expression actual, final Expression expected) { 33 | System.out.println("Testing " + description); 34 | for (int i = 0; i < 10; i++) { 35 | counter.nextTest(); 36 | assertEquals(String.format("f(%d)", i), evaluate(expected, i), evaluate(actual, i)); 37 | counter.passed(); 38 | } 39 | } 40 | 41 | private static Integer evaluate(final Expression expression, final int x) { 42 | try { 43 | return expression.evaluate(x); 44 | } catch (final ArithmeticException e) { 45 | return null; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /java/expression/TripleExpression.java: -------------------------------------------------------------------------------- 1 | package expression; 2 | 3 | /** 4 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 5 | */ 6 | public interface TripleExpression { 7 | int evaluate(int x, int y, int z); 8 | } 9 | -------------------------------------------------------------------------------- /java/expression/TripleExpressionTest.java: -------------------------------------------------------------------------------- 1 | package expression; 2 | 3 | /** 4 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 5 | */ 6 | public class TripleExpressionTest extends ExpressionTest { 7 | public static void main(final String[] args) { 8 | new TripleExpressionTest().run(); 9 | } 10 | 11 | @Override 12 | protected void test() { 13 | super.test(); 14 | 15 | testExpression("10", new Const(10), (x, y, z) -> 10); 16 | testExpression("x", new Variable("x"), (x, y, z) -> x); 17 | testExpression("y", new Variable("y"), (x, y, z) -> y); 18 | testExpression("z", new Variable("z"), (x, y, z) -> z); 19 | testExpression("x+2", new Add(new Variable("x"), new Const(2)), (x, y, z) -> x + 2); 20 | testExpression("2-y", new Subtract(new Const(2), new Variable("y")), (x, y, z) -> 2 - y); 21 | testExpression("3*z", new Multiply(new Const(3), new Variable("z")), (x, y, z) -> 3 * z); 22 | testExpression("x/-2", new Divide(new Variable("x"), new Const(-2)), (x, y, z) -> -x / 2); 23 | testExpression( 24 | "x*y+(z-1)/10", 25 | new Add( 26 | new Multiply(new Variable("x"), new Variable("y")), 27 | new Divide(new Subtract(new Variable("z"), new Const(1)), new Const(10)) 28 | ), 29 | (x, y, z) -> x * y + (z - 1) / 10 30 | ); 31 | } 32 | 33 | private static void testExpression(final String description, final TripleExpression actual, final TripleExpression expected) { 34 | System.out.println("Testing " + description); 35 | for (int i = 0; i < 10; i++) { 36 | for (int j = 0; j < 10; j++) { 37 | for (int k = 0; k < 10; k++) { 38 | assertEquals(String.format("f(%d, %d, %d)", i, j, k), expected.evaluate(i, j, k), actual.evaluate(i, j, k)); 39 | } 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /java/expression/exceptions/ExceptionsAbsSqrtTest.java: -------------------------------------------------------------------------------- 1 | package expression.exceptions; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 7 | */ 8 | public class ExceptionsAbsSqrtTest extends ExceptionsTest { 9 | public static final Reason SQRT = new Reason("sqrt"); 10 | 11 | protected ExceptionsAbsSqrtTest() { 12 | unary.add(op("abs", Math::abs)); 13 | unary.add(op("sqrt", this::sqrt)); 14 | 15 | tests.addAll(Arrays.asList( 16 | op("abs -4", (x, y, z) -> 4), 17 | op("abs-5", (x, y, z) -> 5), 18 | op("abs " + Integer.MIN_VALUE, (x, y, z) -> error(OVERFLOW)), 19 | op("sqrt 4", (x, y, z) -> 2), 20 | op("sqrt 8", (x, y, z) -> 2), 21 | op("sqrt x * y * z", (x, y, z) -> sqrt(x) * y * z), 22 | op("sqrt(x * y * z)", (x, y, z) -> sqrt(x * y * z)) 23 | )); 24 | parsingTest.addAll(Arrays.asList( 25 | op("hello", "hello"), 26 | op("abs", "abs"), 27 | op("abs()", "abs()"), 28 | op("abs(1, 2)", "abs(1, 2)"), 29 | op("abb 1", "abb 1"), 30 | op("abs *", "abs *"), 31 | op("absx", "absx"), 32 | op("absx 10", "absx 10") 33 | )); 34 | } 35 | 36 | private long sqrt(final long a) { 37 | return lift(a >= 0 ? (long) Math.sqrt(a) : error(SQRT)).getRight(); 38 | } 39 | 40 | public static void main(final String[] args) { 41 | new ExceptionsAbsSqrtTest().run(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /java/expression/exceptions/ExceptionsMinMaxTest.java: -------------------------------------------------------------------------------- 1 | package expression.exceptions; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 7 | */ 8 | public class ExceptionsMinMaxTest extends ExceptionsAbsSqrtTest { 9 | protected ExceptionsMinMaxTest() { 10 | levels.add(0, list( 11 | op("min", Math::min), 12 | op("max", Math::max) 13 | )); 14 | 15 | tests.addAll(Arrays.asList( 16 | op("6 - 10 min-3", (x, y, z) -> -4), 17 | op("6 - 10 min-5", (x, y, z) -> -5), 18 | op("2 min 3", (x, y, z) -> 2), 19 | op("4 min 3 min 2", (x, y, z) -> 2), 20 | op("20 min 3 * 3", (x, y, z) -> 9), 21 | op("x min (y * z)", (x, y, z) -> Math.min(x, y * z)), 22 | op("2 min x + 1", (x, y, z) -> Math.min(2, x + 1)), 23 | op("-1 min (3 min x)", (x, y, z) -> Math.min(-1, x)), 24 | op("8 max 2", (x, y, z) -> 8), 25 | op("x max y", (x, y, z) -> Math.max(x, y)), 26 | op("5max y", (x, y, z) -> Math.max(5, y)) 27 | )); 28 | parsingTest.addAll(Arrays.asList( 29 | op("max", "max"), 30 | op("max1", "max1"), 31 | op("max 1", "max 1"), 32 | op("1 max", "1 max"), 33 | op("5max5", "5max5"), 34 | op("1 mxx 1", "1 mxx 1"), 35 | op("1 * max 2", "1 * max 2"), 36 | op("1 max * 3", "1 max * 3") 37 | )); 38 | } 39 | 40 | 41 | public static void main(final String[] args) { 42 | new ExceptionsMinMaxTest().run(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /java/expression/exceptions/ExceptionsPowLog2Test.java: -------------------------------------------------------------------------------- 1 | package expression.exceptions; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 7 | */ 8 | public class ExceptionsPowLog2Test extends ExceptionsTest { 9 | public static final Reason NEG_LOG = new Reason("Logarithm of negative value"); 10 | 11 | protected ExceptionsPowLog2Test() { 12 | unary.add(op("log2", ExceptionsPowLog2Test::log2)); 13 | unary.add(op("pow2", ExceptionsPowLog2Test::pow2)); 14 | 15 | tests.addAll(Arrays.asList( 16 | op("log2 10", (x, y, z) -> 3), 17 | op("log2 -4", (x, y, z) -> error(NEG_LOG)), 18 | op("log2-5", (x, y, z) -> error(NEG_LOG)), 19 | op("pow2 4", (x, y, z) -> 16), 20 | op("pow2 8", (x, y, z) -> 256), 21 | op("pow2 x * y * z", (x, y, z) -> pow2(x) * y * z), 22 | op("pow2(x * y * z)", (x, y, z) -> pow2(x * y * z)) 23 | )); 24 | parsingTest.addAll(Arrays.asList( 25 | op("hello", "hello"), 26 | op("log2()", "log2()"), 27 | op("log2(1, 2)", "log2(1, 2)"), 28 | op("lgg 1", "lgg 1"), 29 | op("log2 *", "log2 *"), 30 | op("log2x", "log2x") 31 | )); 32 | } 33 | 34 | private static long pow2(final long a) { 35 | return 0 <= a && a <= 31 ? (long) Math.pow(2, a) : error(OVERFLOW); 36 | } 37 | 38 | private static long log2(final long a) { 39 | return a <= 0 ? error(NEG_LOG) : (long) (Math.log(a) / Math.log(2)); 40 | } 41 | 42 | public static void main(final String[] args) { 43 | new ExceptionsPowLog2Test().run(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /java/expression/exceptions/ExceptionsTest.java: -------------------------------------------------------------------------------- 1 | package expression.exceptions; 2 | 3 | import expression.parser.Either; 4 | import expression.TripleExpression; 5 | import expression.Variable; 6 | import expression.parser.ParserTest; 7 | 8 | import java.util.ArrayList; 9 | import java.util.Arrays; 10 | import java.util.List; 11 | import java.util.function.LongBinaryOperator; 12 | 13 | /** 14 | * @author Niyaz Nigmatullin 15 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 16 | */ 17 | public class ExceptionsTest extends ParserTest { 18 | private final static int D = 5; 19 | private final static List OVERFLOW_VALUES = new ArrayList<>(); 20 | private final char[] CHARS = "AZ+-*%()[]<>".toCharArray(); 21 | 22 | public static final Variable VX = new Variable("x"); 23 | public static final Variable VY = new Variable("y"); 24 | public static final Reason OVERFLOW = new Reason("Overflow"); 25 | 26 | static { 27 | addRange(OVERFLOW_VALUES, D, Integer.MIN_VALUE + D); 28 | addRange(OVERFLOW_VALUES, D, Integer.MIN_VALUE / 2); 29 | addRange(OVERFLOW_VALUES, D, (int) -Math.sqrt(Integer.MAX_VALUE)); 30 | addRange(OVERFLOW_VALUES, D, 0); 31 | addRange(OVERFLOW_VALUES, D, (int) Math.sqrt(Integer.MAX_VALUE)); 32 | addRange(OVERFLOW_VALUES, D, Integer.MAX_VALUE / 2); 33 | addRange(OVERFLOW_VALUES, D, Integer.MAX_VALUE - D); 34 | } 35 | 36 | protected final List> parsingTest = new ArrayList<>(Arrays.asList( 37 | op("No first argument", "* y * z"), 38 | op("No middle argument", "x * * z"), 39 | op("No last argument", "x * y * "), 40 | op("No first argument'", "1 + (* y * z) + 2"), 41 | op("No middle argument'", "1 + (x * / 9) + 3"), 42 | op("No last argument'", "1 + (x * y - ) + 3"), 43 | op("No opening parenthesis", "x * y)"), 44 | op("No closing parenthesis", "(x * y"), 45 | op("Start symbol", "@x * y"), 46 | op("Middle symbol", "x @ * y"), 47 | op("End symbol", "x * y@"), 48 | op("Constant overflow 1", Integer.MIN_VALUE - 1L + ""), 49 | op("Constant overflow 2", Integer.MAX_VALUE + 1L + "") 50 | )); 51 | 52 | public static void main(final String[] args) { 53 | new ExceptionsTest().run(); 54 | } 55 | 56 | private void testParsingErrors() { 57 | for (final Op op : parsingTest) { 58 | try { 59 | new ExpressionParser().parse(op.f); 60 | assert false : "Successfully parsed " + op.f; 61 | } catch (final Exception e) { 62 | System.out.format("%-30s %s%n", op.name, e.getClass().getSimpleName() + ": " + e.getMessage()); 63 | } 64 | } 65 | } 66 | 67 | protected static void testOverflow() { 68 | testOverflow((a, b) -> a + b, "+", new CheckedAdd(VX, VY)); 69 | testOverflow((a, b) -> a - b, "-", new CheckedSubtract(VX, VY)); 70 | testOverflow((a, b) -> a * b, "*", new CheckedMultiply(VX, VY)); 71 | testOverflow((a, b) -> b == 0 ? Long.MAX_VALUE : a / b, "/", new CheckedDivide(VX, VY)); 72 | testOverflow((a, b) -> -b, "<- ignore first argument, unary -", new CheckedNegate(VY)); 73 | } 74 | 75 | protected static void testOverflow(final LongBinaryOperator f, final String op, final TripleExpression expression) { 76 | for (final int a : OVERFLOW_VALUES) { 77 | for (final int b : OVERFLOW_VALUES) { 78 | final long expected = f.applyAsLong(a, b); 79 | try { 80 | final int actual = expression.evaluate(a, b, 0); 81 | assert actual == expected : a + " " + op + " " + b + " == " + actual; 82 | } catch (final Exception e) { 83 | if (Integer.MIN_VALUE <= expected && expected <= Integer.MAX_VALUE) { 84 | throw new AssertionError("Unexpected error in " + a + " " + op + " " + b, e); 85 | } 86 | } 87 | } 88 | } 89 | } 90 | 91 | @Override 92 | protected void test() { 93 | testOverflow(); 94 | super.test(); 95 | testParsingErrors(); 96 | } 97 | 98 | protected TripleExpression parse(final String expression, final boolean reparse) { 99 | final Parser parser = new ExpressionParser(); 100 | if (expression.length() > 10) { 101 | loop: for (final char ch : CHARS) { 102 | for (int i = 0; i < 10; i++) { 103 | final int index = 1 + randomInt(expression.length() - 2); 104 | int pi = index - 1; 105 | while (Character.isWhitespace(expression.charAt(pi))) { 106 | pi--; 107 | } 108 | int ni = index; 109 | while (Character.isWhitespace(expression.charAt(ni))) { 110 | ni++; 111 | } 112 | final char pc = expression.charAt(pi); 113 | final char nc = expression.charAt(ni); 114 | if ("-(*".indexOf(nc) < 0 && nc != ch && pc != ch && !Character.isLetterOrDigit(nc)) { 115 | final String input = expression.substring(0, index) + ch + expression.substring(index); 116 | try { 117 | counter.nextTest(); 118 | parser.parse(input); 119 | throw new AssertionError("Parsing error expected for " + expression.substring(0, index) + "" + ch + "<-- ERROR_INSERTED>" + expression.substring(index)); 120 | } catch (final Exception e) { 121 | // Ok 122 | counter.passed(); 123 | } 124 | continue loop; 125 | } 126 | } 127 | } 128 | } 129 | counter.nextTest(); 130 | try { 131 | final TripleExpression parse = parser.parse(expression); 132 | counter.passed(); 133 | return parse; 134 | } catch (final Exception e) { 135 | throw new AssertionError("Parser failed", e); 136 | } 137 | } 138 | 139 | @Override 140 | protected Either lift(final long value) { 141 | return value < Integer.MIN_VALUE || Integer.MAX_VALUE < value 142 | ? Either.left(OVERFLOW) 143 | : super.lift(value); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /java/expression/exceptions/Parser.java: -------------------------------------------------------------------------------- 1 | package expression.exceptions; 2 | 3 | import expression.TripleExpression; 4 | 5 | /** 6 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 7 | */ 8 | public interface Parser { 9 | TripleExpression parse(String expression) throws /* Change me */ Exception; 10 | } 11 | -------------------------------------------------------------------------------- /java/expression/parser/Either.java: -------------------------------------------------------------------------------- 1 | package expression.parser; 2 | 3 | import java.util.function.Function; 4 | 5 | /** 6 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 7 | */ 8 | public interface Either { 9 | Either flatMapRight(final Function> f); 10 | 11 | boolean isRight(); 12 | 13 | L getLeft(); 14 | R getRight(); 15 | 16 | static Either right(final R value) { 17 | return new Either() { 18 | 19 | @Override 20 | public Either flatMapRight(final Function> f) { 21 | return f.apply(value); 22 | } 23 | 24 | @Override 25 | public boolean isRight() { 26 | return true; 27 | } 28 | 29 | @Override 30 | public L getLeft() { 31 | return null; 32 | } 33 | 34 | @Override 35 | public R getRight() { 36 | return value; 37 | } 38 | }; 39 | } 40 | 41 | static Either left(final L value) { 42 | return new Either() { 43 | 44 | @Override 45 | public Either flatMapRight(final Function> f) { 46 | return left(value); 47 | } 48 | 49 | @Override 50 | public boolean isRight() { 51 | return false; 52 | } 53 | 54 | @Override 55 | public L getLeft() { 56 | return value; 57 | } 58 | 59 | @Override 60 | public R getRight() { 61 | return null; 62 | } 63 | }; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /java/expression/parser/Parser.java: -------------------------------------------------------------------------------- 1 | package expression.parser; 2 | 3 | import expression.TripleExpression; 4 | 5 | /** 6 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 7 | */ 8 | public interface Parser { 9 | TripleExpression parse(String expression); 10 | } 11 | -------------------------------------------------------------------------------- /java/expression/parser/ParserBitwiseTest.java: -------------------------------------------------------------------------------- 1 | package expression.parser; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @author Georgiy Korneev 7 | */ 8 | public class ParserBitwiseTest extends ParserTest { 9 | protected ParserBitwiseTest() { 10 | levels.add(0, list(op("&", (a, b) -> a & b))); 11 | levels.add(0, list(op("^", (a, b) -> a ^ b))); 12 | levels.add(0, list(op("|", (a, b) -> a | b))); 13 | 14 | tests.addAll(Arrays.asList( 15 | op("6 & 1 + 2", (x, y, z) -> 2L), 16 | op("6 ^ 1 + 2", (x, y, z) -> 5L), 17 | op("6 | 1 + 2", (x, y, z) -> 7L), 18 | op("x & y", (x, y, z) -> x & y), 19 | op("x | y", (x, y, z) -> x | y), 20 | op("x ^ y", (x, y, z) -> x ^ y), 21 | op("x | z & y", (x, y, z) -> x | z & y), 22 | op("x ^ z & y", (x, y, z) -> x ^ z & y), 23 | op("x | z ^ y", (x, y, z) -> x | z ^ y), 24 | op("x & y + z", (x, y, z) -> x & y + z), 25 | op("x ^ y - z", (x, y, z) -> x ^ y - z), 26 | op("x | y + z", (x, y, z) -> x | y + z), 27 | op("(- - - x^1883669513)|(- x^1681810605)", (x, y, z) -> (- - - x^1883669513)|(- x^1681810605)) 28 | )); 29 | } 30 | 31 | public static void main(final String[] args) { 32 | new ParserBitwiseTest().run(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /java/expression/parser/ParserNotCountTest.java: -------------------------------------------------------------------------------- 1 | package expression.parser; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @author Georgiy Korneev 7 | */ 8 | public class ParserNotCountTest extends ParserBitwiseTest { 9 | protected ParserNotCountTest() { 10 | unary.add(op("~", a -> ~a)); 11 | unary.add(op("count", ParserNotCountTest::count)); 12 | 13 | tests.addAll(Arrays.asList( 14 | op("~-5", (x, y, z) -> 4), 15 | op("~(x - y)", (x, y, z) -> ~(x - y)), 16 | op("x-~-y", (x, y, z) -> x - ~(-y)), 17 | op("~-x", (x, y, z) -> ~(-x)), 18 | op("~(x+y)", (x, y, z) -> ~(x + y)), 19 | op("count 5", (x, y, z) -> 2), 20 | op("count -5", (x, y, z) -> 31), 21 | op("count (x - y)", (x, y, z) -> count(x - y)), 22 | op("x -count y", (x, y, z) -> x - count(y)), 23 | op("count -x", (x, y, z) -> count(-x)), 24 | op("count(x+y)", (x, y, z) -> count(x + y)) 25 | )); 26 | } 27 | 28 | public static long count(final long a) { 29 | return Integer.bitCount((int) a); 30 | } 31 | 32 | public static void main(final String[] args) { 33 | new ParserNotCountTest().run(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /java/expression/parser/ParserShiftsTest.java: -------------------------------------------------------------------------------- 1 | package expression.parser; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @author Georgiy Korneev 7 | */ 8 | public class ParserShiftsTest extends ParserTest { 9 | protected ParserShiftsTest() { 10 | levels.add(0, list( 11 | op("<<", (a, b) -> (int) a << (int) b), 12 | op(">>", (a, b) -> (int) a >> (int) b) 13 | )); 14 | 15 | tests.addAll(Arrays.asList( 16 | op("1 << 5 + 3", (x, y, z) -> 256L), 17 | op("x + y << z", (x, y, z) -> (int) (x + y) << (int) z), 18 | op("x * y << z", (x, y, z) -> (int) (x * y) << (int) z), 19 | op("x << y << z", (x, y, z) -> (int) x << (int) y << (int) z), 20 | op("1024 >> 5 + 3", (x, y, z) -> 4L), 21 | op("x + y >> z", (x, y, z) -> x + y >> z), 22 | op("x * y >> z", (x, y, z) -> x * y >> z), 23 | op("x >> y >> z", (x, y, z) -> x >> y >> z) 24 | )); 25 | } 26 | 27 | public static void main(final String[] args) { 28 | new ParserShiftsTest().run(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /java/expression/parser/ParserTest.java: -------------------------------------------------------------------------------- 1 | package expression.parser; 2 | 3 | import expression.BaseTest; 4 | import expression.CommonExpression; 5 | import expression.TripleExpression; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | import java.util.function.BiFunction; 10 | import java.util.function.LongBinaryOperator; 11 | import java.util.function.LongSupplier; 12 | import java.util.function.LongUnaryOperator; 13 | 14 | /** 15 | * @author Niyaz Nigmatullin 16 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 17 | */ 18 | public class ParserTest extends BaseTest { 19 | private final static int D = 5; 20 | 21 | private final static List TEST_VALUES = new ArrayList<>(); 22 | static { 23 | addRange(TEST_VALUES, D, D); 24 | addRange(TEST_VALUES, D, -D); 25 | } 26 | 27 | 28 | protected final List> unary = new ArrayList<>(); 29 | protected final List>> levels = new ArrayList<>(); 30 | protected List> tests; 31 | 32 | protected ParserTest() { 33 | unary.add(op("-", a -> -a)); 34 | 35 | levels.add(list( 36 | op("+", (a, b) -> a + b), 37 | op("-", (a, b) -> a - b) 38 | )); 39 | levels.add(list( 40 | op("*", (a, b) -> a * b), 41 | op("/", (a, b) -> b == 0 ? error(DBZ) : a / b) 42 | )); 43 | 44 | tests = list( 45 | op("10", (x, y, z) -> 10L), 46 | op("x", (x, y, z) -> x), 47 | op("y", (x, y, z) -> y), 48 | op("z", (x, y, z) -> z), 49 | op("x+2", (x, y, z) -> x + 2), 50 | op("2-y", (x, y, z) -> 2 - y), 51 | op(" 3* z ", (x, y, z) -> 3 * z), 52 | op("x/ - 2", (x, y, z) -> -x / 2), 53 | op("x*y+(z-1 )/10", (x, y, z) -> x * y + (int) (z - 1) / 10), 54 | op("-(-(-\t\t-5 + 16 *x*y) + 1 * z) -(((-11)))", (x, y, z) -> -(-(5 + 16 * x * y) + z) + 11), 55 | op("" + Integer.MAX_VALUE, (x, y, z) -> (long) Integer.MAX_VALUE), 56 | op("" + Integer.MIN_VALUE, (x, y, z) -> (long) Integer.MIN_VALUE), 57 | op("x--y--z", (x, y, z) -> x + y + z), 58 | op("((2+2))-0/(--2)*555", (x, y, z) -> 4L), 59 | op("x-x+y-y+z-(z)", (x, y, z) -> 0L), 60 | op(repeat("(", 500) + "x + y + (-10*-z)" + repeat(")", 500), (x, y, z) -> x + y + 10 * z), 61 | op("x / y / z", (x, y, z) -> y == 0 || z == 0 ? error(DBZ) : (int) x / (int) y / z) 62 | ); 63 | } 64 | 65 | public static void main(final String[] args) { 66 | new ParserTest().run(); 67 | } 68 | 69 | @Override 70 | protected void test() { 71 | for (final Op test : tests) { 72 | System.out.println("Testing: " + test.name); 73 | final TripleExpression expression = parse(test.name, true); 74 | for (final Integer x : TEST_VALUES) { 75 | for (final Integer y : TEST_VALUES) { 76 | for (final Integer z : TEST_VALUES) { 77 | check(new int[]{x, y, z}, expression, eval(() -> test.f.evaluate(x, y, z))); 78 | } 79 | } 80 | } 81 | } 82 | 83 | testRandom(1, 2000, (v, i) -> generate(v, i / 5 + 2)); 84 | testRandom(2, 777, (v, i) -> genExpression(1, i / 25 / levels.size() + 1, v, 0)); 85 | } 86 | 87 | private Either eval(final LongSupplier supplier) { 88 | try { 89 | return lift(supplier.getAsLong()); 90 | } catch (final ExpException e) { 91 | return Either.left(e.reason); 92 | } 93 | } 94 | 95 | protected TripleExpression parse(final String expression, final boolean reparse) { 96 | try { 97 | final ExpressionParser parser = new ExpressionParser(); 98 | if (reparse) { 99 | counter.nextTest(); 100 | parser.parse(expression); 101 | counter.passed(); 102 | } 103 | counter.nextTest(); 104 | final CommonExpression result = parser.parse(expression); 105 | counter.passed(); 106 | return result; 107 | } catch (final Exception e) { 108 | throw new AssertionError("Parser failed", e); 109 | } 110 | } 111 | 112 | protected void testRandom(final int seq, final int n, final BiFunction f) { 113 | System.out.println("Testing random tests #" + seq); 114 | for (int i = 0; i < n; i++) { 115 | if (i % 100 == 0) { 116 | System.out.println("Completed " + i + " out of " + n); 117 | } 118 | final int[] vars = new int[]{random.nextInt(), random.nextInt(), random.nextInt()}; 119 | 120 | final Test test = f.apply(vars, i); 121 | try { 122 | check(vars, parse(test.expr, false), test.answer); 123 | } catch (final Throwable e) { 124 | System.out.println("Failed test: " + test.expr); 125 | throw e; 126 | } 127 | } 128 | } 129 | 130 | private void check(final int[] vars, final TripleExpression expression, final Either answer) { 131 | counter.nextTest(); 132 | try { 133 | final int actual = expression.evaluate(vars[0], vars[1], vars[2]); 134 | assert answer.isRight() : String.format("Error expected for x=%d, y=%d, z=%d", vars[0], vars[1], vars[2]); 135 | assertEquals(String.format("f(%d, %d, %d)\n%s", vars[0], vars[1], vars[2], expression), (int) answer.getRight(), actual); 136 | } catch (final Exception e) { 137 | if (answer.isRight()) { 138 | throw new AssertionError(String.format("No error expected for x=%d, y=%d, z=%d", vars[0], vars[1], vars[2]), e); 139 | } 140 | } 141 | counter.passed(); 142 | } 143 | 144 | private Test generate(final int[] vars, final int depth) { 145 | if (depth == 0) { 146 | return constOrVariable(vars); 147 | } 148 | final int operator = randomInt(6); 149 | if (operator <= 0) { 150 | return genP(vars, depth); 151 | } else if (operator <= 1) { 152 | return unary(genP(vars, depth)); 153 | } else { 154 | return binary(random(levels), genP(vars, depth), genP(vars, depth)); 155 | } 156 | } 157 | 158 | private Test genP(final int[] vars, final int depth) { 159 | return p(generate(vars, randomInt(depth))); 160 | } 161 | 162 | private Test constOrVariable(final int[] vars) { 163 | if (random.nextBoolean()) { 164 | final int id = randomInt(3); 165 | return new Test("xyz".charAt(id) + "", Either.right(vars[id])); 166 | } else { 167 | final int value = random.nextInt(); 168 | return new Test(value + "", Either.right(value)); 169 | } 170 | } 171 | 172 | private Test genExpression(final int depth, final int coefficient, final int[] vars, final int level) { 173 | if (level == levels.size()) { 174 | return genFactor(depth, coefficient, vars); 175 | } else if (makeNewBranch(depth, coefficient)) { 176 | return binary(levels.get(level), genExpression(depth + 1, coefficient, vars, level), genExpression(depth, coefficient, vars, level + 1)); 177 | } else { 178 | return genExpression(depth, coefficient, vars, level + 1); 179 | } 180 | } 181 | 182 | private Test genFactor(final int depth, final int coefficient, final int[] vars) { 183 | if (makeNewBranch(depth, coefficient)) { 184 | return unary(genFactor(depth + 1, coefficient, vars)); 185 | } else { 186 | return genValue(depth, coefficient, vars); 187 | } 188 | } 189 | 190 | private static Test p(final Test t) { 191 | return new Test("(" + t.expr + ")", t.answer); 192 | } 193 | 194 | private Test binary(final List> ops, final Test t1, final Test t2) { 195 | final Op op = random(ops); 196 | return new Test( 197 | t1.expr + " " + op.name + " " + t2.expr, 198 | t1.answer.flatMapRight(a -> t2.answer.flatMapRight(b -> eval(() -> op.f.applyAsLong(a, b)))) 199 | ); 200 | } 201 | 202 | private Test unary(final Test arg) { 203 | final Op op = random(unary); 204 | return new Test(op.name + " " + arg.expr, arg.answer.flatMapRight(a -> eval(() -> op.f.applyAsLong(a)))); 205 | } 206 | 207 | private Test genValue(final int depth, final int coefficient, final int[] vars) { 208 | if (makeNewBranch(depth, coefficient)) { 209 | return p(genExpression(depth + 1, coefficient, vars, 0)); 210 | } else { 211 | return constOrVariable(vars); 212 | } 213 | } 214 | 215 | private boolean makeNewBranch(final int depth, final int coefficient) { 216 | return randomInt(depth + coefficient) < coefficient; 217 | } 218 | 219 | protected Either lift(final long value) { 220 | return Either.right((int) value); 221 | } 222 | 223 | protected static class Test { 224 | final String expr; 225 | final Either answer; 226 | 227 | Test(final String expr, final Either answer) { 228 | this.expr = expr; 229 | this.answer = answer; 230 | } 231 | } 232 | 233 | protected static class Reason { 234 | private final String description; 235 | 236 | public Reason(final String description) { 237 | this.description = description; 238 | } 239 | } 240 | 241 | public static final Reason DBZ = new Reason("Division by zero"); 242 | 243 | public interface TExpression { 244 | long evaluate(long x, long y, long z); 245 | } 246 | 247 | public static class ExpException extends RuntimeException { 248 | private final Reason reason; 249 | 250 | public ExpException(final Reason reason) { 251 | super(reason.description); 252 | this.reason = reason; 253 | } 254 | } 255 | 256 | public static long error(final Reason reason) { 257 | throw new ExpException(reason); 258 | } 259 | } 260 | -------------------------------------------------------------------------------- /java/queue/ArrayQueueDequeTest.java: -------------------------------------------------------------------------------- 1 | package queue; 2 | 3 | import java.net.MalformedURLException; 4 | import java.util.Deque; 5 | 6 | /** 7 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 8 | */ 9 | public class ArrayQueueDequeTest extends ArrayQueueTest { 10 | public ArrayQueueDequeTest() { 11 | super(QueueDeque::new); 12 | } 13 | 14 | public static void main(final String[] args) { 15 | new ArrayQueueDequeTest().test(); 16 | } 17 | 18 | @Override 19 | protected void add(final Deque deque, final QueueDeque queue, final Object element) { 20 | if (random.nextBoolean()) { 21 | super.add(deque, queue, element); 22 | } else { 23 | deque.addFirst(element); 24 | queue.push(element); 25 | } 26 | } 27 | 28 | @Override 29 | protected void check(final Deque deque, final QueueDeque queue) { 30 | if (random.nextBoolean()) { 31 | super.check(deque, queue); 32 | } else { 33 | assertEquals("peek()", deque.getLast(), queue.peek()); 34 | } 35 | } 36 | 37 | @Override 38 | protected void remove(final Deque deque, final QueueDeque queue) { 39 | if (random.nextBoolean()) { 40 | super.remove(deque, queue); 41 | } else { 42 | assertEquals("remove()", deque.removeLast(), queue.remove()); 43 | } 44 | } 45 | 46 | static class QueueDeque extends ArrayQueueTest.Queue { 47 | private final ZMethod push; 48 | private final ZMethod peek; 49 | private final ZMethod remove; 50 | 51 | public QueueDeque(final String className, final Mode mode) throws MalformedURLException, NoSuchMethodException, ClassNotFoundException { 52 | super(className, mode); 53 | push = findMethod("push", Object.class); 54 | peek = findMethod("peek"); 55 | remove = findMethod("remove"); 56 | } 57 | 58 | public void push(final Object element) { 59 | push.invoke(element); 60 | } 61 | 62 | public Object peek() { 63 | return peek.invoke(); 64 | } 65 | 66 | public Object remove() { 67 | return remove.invoke(); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /java/queue/ArrayQueueTest.java: -------------------------------------------------------------------------------- 1 | package queue; 2 | 3 | import base.Asserts; 4 | import base.TestCounter; 5 | 6 | import java.io.File; 7 | import java.lang.reflect.Method; 8 | import java.lang.reflect.Modifier; 9 | import java.net.MalformedURLException; 10 | import java.net.URL; 11 | import java.net.URLClassLoader; 12 | import java.util.ArrayDeque; 13 | import java.util.Deque; 14 | import java.util.Random; 15 | 16 | /** 17 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 18 | */ 19 | public class ArrayQueueTest extends Asserts { 20 | private final QueueFactory factory; 21 | private final TestCounter counter = new TestCounter(); 22 | 23 | private static final Object[] ELEMENTS = new Object[]{ 24 | "Hello", 25 | "world", 26 | 1, 2, 3, 27 | new Object() 28 | }; 29 | 30 | protected final Random random = new Random(2474258720358724587L); 31 | 32 | public ArrayQueueTest(final QueueFactory factory) { 33 | Asserts.checkAssert(getClass()); 34 | this.factory = factory; 35 | } 36 | 37 | public static void main(final String[] args) { 38 | new ArrayQueueTest<>(Queue::new).test(); 39 | } 40 | 41 | protected void test() { 42 | test("ArrayQueue", 2, Mode.values()); 43 | } 44 | 45 | protected void test(final String className, final int step, final Mode... modes) { 46 | for (final Mode mode : modes) { 47 | System.err.printf("Running %s for %s in %s mode%n", getClass().getName(), className, mode); 48 | test(className, mode, step); 49 | } 50 | counter.printStatus(getClass()); 51 | } 52 | 53 | private void test(final String className, final Mode mode, final int step) { 54 | testEmpty(create(className, mode)); 55 | testSingleton(create(className, mode)); 56 | testClear(create(className, mode)); 57 | for (int i = 0; i <= 10; i += step) { 58 | testRandom(create(className, mode), 100_000, (double) i / 10); 59 | } 60 | } 61 | 62 | protected T create(final String className, final Mode mode) { 63 | try { 64 | return factory.create(className, mode); 65 | } catch (MalformedURLException | NoSuchMethodException | ClassNotFoundException e) { 66 | throw new AssertionError("Cannot create Queue (" + className + "): " + e.getMessage()); 67 | } 68 | } 69 | 70 | protected void testEmpty(final T queue) { 71 | nextTest("testEmpty"); 72 | assertSize(0, queue); 73 | counter.passed(); 74 | } 75 | 76 | protected void testSingleton(final T queue) { 77 | nextTest("testSingleton"); 78 | assertSize(0, queue); 79 | final String value = "value"; 80 | queue.enqueue(value); 81 | assertSize(1, queue); 82 | assertEquals("element()", value, queue.element()); 83 | assertEquals("dequeue()", value, queue.dequeue()); 84 | assertSize(0, queue); 85 | counter.passed(); 86 | } 87 | 88 | private void nextTest(final String name) { 89 | System.err.println("=== " + name); 90 | counter.nextTest(); 91 | } 92 | 93 | protected void testClear(final T queue) { 94 | nextTest("testClear"); 95 | assertSize(0, queue); 96 | 97 | final String value = "value"; 98 | queue.enqueue(value); 99 | queue.enqueue(value); 100 | queue.clear(); 101 | assertSize(0, queue); 102 | 103 | final String value1 = "value1"; 104 | queue.enqueue(value1); 105 | assertEquals("deque()", value1, queue.dequeue()); 106 | counter.passed(); 107 | } 108 | 109 | protected void testRandom(final T queue, final int operations, final double addFreq) { 110 | nextTest("testRandom, add frequency = " + addFreq); 111 | final Deque deque = new ArrayDeque<>(); 112 | int ops = 0; 113 | for (int i = 0; i < operations; i++) { 114 | if (deque.isEmpty() || random.nextDouble() < addFreq) { 115 | add(deque, queue, randomElement()); 116 | } else { 117 | remove(deque, queue); 118 | } 119 | checkAndSize(deque, queue); 120 | if (ops++ >= deque.size() && random.nextDouble() < 0.25) { 121 | ops -= deque.size(); 122 | linearTest(deque, queue); 123 | } 124 | } 125 | linearTest(deque, queue); 126 | while (!deque.isEmpty()) { 127 | remove(deque, queue); 128 | checkAndSize(deque, queue); 129 | } 130 | counter.passed(); 131 | } 132 | 133 | private void checkAndSize(final Deque deque, final T queue) { 134 | if (!deque.isEmpty() && random.nextBoolean()) { 135 | check(deque, queue); 136 | } 137 | assertSize(deque.size(), queue); 138 | } 139 | 140 | protected void remove(final Deque deque, final T queue) { 141 | assertEquals("dequeue()", deque.removeFirst(), queue.dequeue()); 142 | } 143 | 144 | protected void check(final Deque deque, final T queue) { 145 | assertEquals("element()", deque.element(), queue.element()); 146 | } 147 | 148 | protected void add(final Deque deque, final T queue, final Object element) { 149 | deque.addLast(element); 150 | queue.enqueue(element); 151 | } 152 | 153 | protected void linearTest(final Deque deque, final T queue) { 154 | // Do nothing by default 155 | } 156 | 157 | protected Object randomElement() { 158 | return ELEMENTS[random.nextInt(ELEMENTS.length)]; 159 | } 160 | 161 | protected void assertSize(final int size, final T queue) { 162 | assertEquals("size()", size, queue.size()); 163 | assert queue.size() == size : "Expected size() " + size + ", found " + queue.size(); 164 | assert (size == 0) == queue.isEmpty() : "Expected isEmpty() " + (size == 0) + ", found " + queue.isEmpty(); 165 | } 166 | 167 | enum Mode { 168 | MODULE("Module") { 169 | @Override 170 | public ZMethod getMethod(final Object instance, final String name, final Class... args) throws NoSuchMethodException { 171 | return checkStatic(true, new ZMethod<>(instance, name, args)); 172 | } 173 | }, 174 | ADT("ADT") { 175 | @Override 176 | public ZMethod getMethod(final Object instance, final String name, final Class... args) throws NoSuchMethodException { 177 | final Object[] a = new Object[args.length + 1]; 178 | a[0] = instance; 179 | final Class[] result = new Class[args.length + 1]; 180 | result[0] = instance.getClass(); 181 | System.arraycopy(args, 0, result, 1, args.length); 182 | 183 | return checkStatic(true, new ZMethod(instance, name, result) { 184 | @Override 185 | protected T invoke(final Object... args) { 186 | if (args.length == 1) { 187 | a[1] = args[0]; 188 | } 189 | return super.invoke(a); 190 | } 191 | }); 192 | } 193 | }, 194 | CLASS("") { 195 | @Override 196 | public ZMethod getMethod(final Object instance, final String name, final Class... args) throws NoSuchMethodException { 197 | return checkStatic(false, new ZMethod<>(instance, name, args)); 198 | } 199 | }; 200 | 201 | private final String suffix; 202 | 203 | Mode(final String suffix) { 204 | this.suffix = suffix; 205 | } 206 | 207 | private static ZMethod checkStatic(final boolean isStatic, final ZMethod method) { 208 | if (isStatic != Modifier.isStatic(method.method.getModifiers())) { 209 | throw new AssertionError("Method " + method.method.getName() + " in " + method.method.getDeclaringClass() + (isStatic ? " must" : " must not") + " be static"); 210 | } 211 | return method; 212 | } 213 | 214 | public abstract ZMethod getMethod(Object instance, String name, Class... args) throws NoSuchMethodException; 215 | } 216 | 217 | protected static class ZMethod { 218 | private final Object instance; 219 | private final Method method; 220 | 221 | public ZMethod(final Object instance, final String name, final Class... args) throws NoSuchMethodException { 222 | this.instance = instance; 223 | method = instance.getClass().getMethod(name, args); 224 | } 225 | 226 | protected T invoke(final Object... args) { 227 | try { 228 | @SuppressWarnings("unchecked") 229 | final T result = (T) method.invoke(instance, args); 230 | return result; 231 | } catch (final Exception e) { 232 | throw new AssertionError("Error calling method " + method.getName(), e); 233 | } 234 | } 235 | } 236 | 237 | public interface QueueFactory { 238 | T create(String className, Mode mode) throws MalformedURLException, NoSuchMethodException, ClassNotFoundException; 239 | } 240 | 241 | static class Queue { 242 | private final ZMethod enqueue; 243 | private final ZMethod element; 244 | private final ZMethod dequeue; 245 | private final ZMethod size; 246 | private final ZMethod isEmpty; 247 | private final ZMethod clear; 248 | private final Mode mode; 249 | protected final Object instance; 250 | 251 | public Queue(final String name, final Mode mode) throws MalformedURLException, NoSuchMethodException, ClassNotFoundException { 252 | this(createInstance(name, mode), mode); 253 | } 254 | 255 | public Queue(final Object instance, final Mode mode) throws NoSuchMethodException { 256 | this.mode = mode; 257 | this.instance = instance; 258 | 259 | enqueue = findMethod("enqueue", Object.class); 260 | element = findMethod("element"); 261 | dequeue = findMethod("dequeue"); 262 | size = findMethod("size"); 263 | isEmpty = findMethod("isEmpty"); 264 | clear = findMethod("clear"); 265 | } 266 | 267 | private static Object createInstance(final String name, final Mode mode) throws MalformedURLException, ClassNotFoundException { 268 | final String className = "queue." + name + mode.suffix; 269 | final URL url = new File(".").toURI().toURL(); 270 | final Class clazz = new URLClassLoader(new URL[]{url}).loadClass(className); 271 | try { 272 | return clazz.newInstance(); 273 | } catch (final Exception e) { 274 | throw new AssertionError("Cannot create instance of " + className, e); 275 | } 276 | } 277 | 278 | protected ZMethod findMethod(final String name, final Class... args) throws NoSuchMethodException { 279 | return mode.getMethod(instance, name, args); 280 | } 281 | 282 | public void enqueue(final Object element) { 283 | enqueue.invoke(element); 284 | } 285 | 286 | public Object element() { 287 | return element.invoke(); 288 | } 289 | 290 | public Object dequeue() { 291 | return dequeue.invoke(); 292 | } 293 | 294 | public int size() { 295 | return size.invoke(); 296 | } 297 | 298 | public boolean isEmpty() { 299 | return isEmpty.invoke(); 300 | } 301 | 302 | public void clear() { 303 | clear.invoke(); 304 | } 305 | } 306 | } 307 | -------------------------------------------------------------------------------- /java/queue/ArrayQueueToArrayTest.java: -------------------------------------------------------------------------------- 1 | package queue; 2 | 3 | import java.net.MalformedURLException; 4 | import java.util.Arrays; 5 | import java.util.Deque; 6 | 7 | /** 8 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 9 | */ 10 | public class ArrayQueueToArrayTest extends ArrayQueueTest { 11 | public ArrayQueueToArrayTest() { 12 | super(ToArrayQueue::new); 13 | } 14 | 15 | public static void main(final String[] args) { 16 | new ArrayQueueToArrayTest().test(); 17 | } 18 | 19 | @Override 20 | protected void linearTest(final Deque expected, final ToArrayQueue actual) { 21 | assertEquals("toArray()", Arrays.asList(expected.toArray()), Arrays.asList(actual.toArray())); 22 | } 23 | 24 | static class ToArrayQueue extends ArrayQueueTest.Queue { 25 | private final ZMethod toArray; 26 | 27 | public ToArrayQueue(final String className, final Mode mode) throws MalformedURLException, NoSuchMethodException, ClassNotFoundException { 28 | super(className, mode); 29 | toArray = findMethod("toArray"); 30 | } 31 | 32 | public Object[] toArray() { return toArray.invoke(); } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /java/queue/QueueFunctionsTest.java: -------------------------------------------------------------------------------- 1 | package queue; 2 | 3 | import java.net.MalformedURLException; 4 | import java.util.Arrays; 5 | import java.util.Deque; 6 | import java.util.function.Function; 7 | import java.util.function.Predicate; 8 | import java.util.stream.Stream; 9 | 10 | /** 11 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 12 | */ 13 | public class QueueFunctionsTest extends QueueTest { 14 | public QueueFunctionsTest() { 15 | super(QueueFunctions::new); 16 | } 17 | 18 | public static void main(final String[] args) { 19 | new QueueFunctionsTest().test(); 20 | } 21 | 22 | @Override 23 | protected QueueFunctions create(final String className, final Mode mode) { 24 | return QueueTest.check(super.create(className, mode)); 25 | } 26 | 27 | @Override 28 | protected void linearTest(final Deque deque, final QueueFunctions queue) { 29 | if (random.nextBoolean()) { 30 | final Predicate predicate = Predicate.isEqual(randomElement()); 31 | assertEquals("filter()", deque.stream().filter(predicate), queue.filter(predicate)); 32 | } else { 33 | final Function f = random.nextBoolean() ? String::valueOf : Object::hashCode; 34 | assertEquals("map()", deque.stream().map(f), queue.map(f)); 35 | } 36 | } 37 | 38 | private static void assertEquals(final String message, final Stream expected, final Queue actual) { 39 | assertEquals(message, Arrays.asList(expected.toArray()), Arrays.asList(toArray(actual))); 40 | } 41 | 42 | private static Object[] toArray(final Queue queue) { 43 | final Object[] result = new Object[queue.size()]; 44 | for (int i = 0; i < result.length; i++) { 45 | result[i] = queue.dequeue(); 46 | } 47 | return result; 48 | } 49 | 50 | static class QueueFunctions extends ArrayQueueTest.Queue { 51 | private final ZMethod filter; 52 | private final ZMethod map; 53 | 54 | public QueueFunctions(final String className, final Mode mode) throws MalformedURLException, NoSuchMethodException, ClassNotFoundException { 55 | super(className, mode); 56 | filter = findMethod("filter", Predicate.class); 57 | map = findMethod("map", Function.class); 58 | } 59 | 60 | public Queue filter(final Predicate p) { 61 | return wrap(filter.invoke(p)); 62 | } 63 | 64 | public Queue map(final Function f) { 65 | return wrap(map.invoke(f)); 66 | } 67 | 68 | private Queue wrap(final Object instance) { 69 | assertEquals("queue type", this.instance.getClass().getName(), instance.getClass().getName()); 70 | try { 71 | return new Queue(instance, Mode.CLASS); 72 | } catch (final NoSuchMethodException e) { 73 | throw new AssertionError(e); 74 | } 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /java/queue/QueueTest.java: -------------------------------------------------------------------------------- 1 | package queue; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 7 | */ 8 | public class QueueTest extends ArrayQueueTest { 9 | public QueueTest(final QueueFactory factory) { 10 | super(factory); 11 | } 12 | 13 | public static void main(final String[] args) { 14 | new QueueTest<>(Queue::new).test(); 15 | } 16 | 17 | public void test() { 18 | test("LinkedQueue", 2, Mode.CLASS); 19 | test("ArrayQueue", 2, Mode.CLASS); 20 | } 21 | 22 | @Override 23 | protected T create(final String className, final Mode mode) { 24 | return check(super.create(className, mode)); 25 | } 26 | 27 | protected static T check(final T queue) { 28 | final Class type = queue.instance.getClass(); 29 | assertTrue(type + " should extend AbstractQueue", "queue.AbstractQueue".equals(type.getSuperclass().getName())); 30 | assertTrue(type + " should implement interface Queue", implementsQueue(type) || implementsQueue(type.getSuperclass())); 31 | return queue; 32 | } 33 | 34 | private static boolean implementsQueue(final Class clazz) { 35 | return Arrays.stream(clazz.getInterfaces()).map(Class::getName).anyMatch("queue.Queue"::equals); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /java/queue/QueueToArrayTest.java: -------------------------------------------------------------------------------- 1 | package queue; 2 | 3 | /** 4 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 5 | */ 6 | public class QueueToArrayTest extends ArrayQueueToArrayTest { 7 | public static void main(final String[] args) { 8 | new QueueToArrayTest().test(); 9 | } 10 | 11 | @Override 12 | protected ToArrayQueue create(final String className, final Mode mode) { 13 | return QueueTest.check(super.create(className, mode)); 14 | } 15 | 16 | public void test() { 17 | test("LinkedQueue", 2, Mode.CLASS); 18 | test("ArrayQueue", 2, Mode.CLASS); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /java/reverse/ReverseChecker.java: -------------------------------------------------------------------------------- 1 | package reverse; 2 | 3 | import base.MainStdChecker; 4 | 5 | import java.util.*; 6 | import java.util.stream.Collectors; 7 | import java.util.stream.IntStream; 8 | 9 | /** 10 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 11 | */ 12 | public class ReverseChecker extends MainStdChecker { 13 | public ReverseChecker(final String className) { 14 | super(className); 15 | } 16 | 17 | public void test(final int[][] input, final int[][] output) { 18 | checkEquals(toLines(output), runStd(toLines(input))); 19 | } 20 | 21 | private List toLines(final int[][] input) { 22 | if (input.length == 0) { 23 | return Collections.singletonList(""); 24 | } 25 | return Arrays.stream(input) 26 | .map(row -> Arrays.stream(row).mapToObj(Integer::toString).collect(Collectors.joining(" "))) 27 | .collect(Collectors.toList()); 28 | } 29 | 30 | public int[][] random(final int[] profile) { 31 | final int col = random.nextInt(Arrays.stream(profile).max().orElse(0)); 32 | final int row = random.nextInt(profile.length); 33 | final int m = random.nextInt(5) - 2; 34 | final int[][] ints = Arrays.stream(profile).mapToObj(random::ints).map(IntStream::toArray).toArray(int[][]::new); 35 | Arrays.stream(ints).filter(r -> col < r.length).forEach(r -> r[col] = Math.abs(r[col]) / 2 * m); 36 | ints[row] = Arrays.stream(ints[row]).map(Math::abs).map(v -> v / 2 * m).toArray(); 37 | return ints; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /java/reverse/ReverseFastTest.java: -------------------------------------------------------------------------------- 1 | package reverse; 2 | 3 | /** 4 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 5 | */ 6 | public class ReverseFastTest { 7 | public static void main(String... args) { 8 | new ReverseTest(1000_000).run(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /java/reverse/ReverseMaxTest.java: -------------------------------------------------------------------------------- 1 | package reverse; 2 | 3 | import java.util.Arrays; 4 | import java.util.stream.IntStream; 5 | 6 | /** 7 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 8 | */ 9 | public class ReverseMaxTest extends ReverseTest { 10 | public ReverseMaxTest(final int maxSize) { 11 | super("ReverseMax", maxSize); 12 | } 13 | 14 | public static void main(String... args) { 15 | new ReverseMaxTest(MAX_SIZE).run(); 16 | } 17 | 18 | @Override 19 | protected int[][] transform(final int[][] ints) { 20 | final int[] rt = Arrays.stream(ints) 21 | .map(Arrays::stream) 22 | .map(IntStream::max) 23 | .mapToInt(i -> i.orElse(0)) 24 | .toArray(); 25 | final int[] ct = new int[Arrays.stream(ints).mapToInt(r -> r.length).max().orElse(0)]; 26 | Arrays.fill(ct, Integer.MIN_VALUE); 27 | Arrays.stream(ints).forEach(row -> IntStream.range(0, row.length).forEach(i -> ct[i] = Math.max(ct[i], row[i]))); 28 | return IntStream.range(0, ints.length) 29 | .mapToObj(r -> IntStream.range(0, ints[r].length).map(c -> Math.max(rt[r], ct[c])).toArray()) 30 | .toArray(int[][]::new); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /java/reverse/ReverseMinFastTest.java: -------------------------------------------------------------------------------- 1 | package reverse; 2 | 3 | /** 4 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 5 | */ 6 | public class ReverseMinFastTest { 7 | public static void main(String... args) { 8 | new ReverseMinTest(1000_000).run(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /java/reverse/ReverseMinTest.java: -------------------------------------------------------------------------------- 1 | package reverse; 2 | 3 | import java.util.Arrays; 4 | import java.util.stream.IntStream; 5 | 6 | /** 7 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 8 | */ 9 | public class ReverseMinTest extends ReverseTest { 10 | public ReverseMinTest(final int maxSize) { 11 | super("ReverseMin", maxSize); 12 | } 13 | 14 | public static void main(String... args) { 15 | new ReverseMinTest(MAX_SIZE).run(); 16 | } 17 | 18 | @Override 19 | protected int[][] transform(final int[][] ints) { 20 | final int[] rt = Arrays.stream(ints) 21 | .map(Arrays::stream) 22 | .map(IntStream::min) 23 | .mapToInt(i -> i.orElse(0)) 24 | .toArray(); 25 | final int[] ct = new int[Arrays.stream(ints).mapToInt(r -> r.length).max().orElse(0)]; 26 | Arrays.fill(ct, Integer.MAX_VALUE); 27 | Arrays.stream(ints).forEach(row -> IntStream.range(0, row.length).forEach(i -> ct[i] = Math.min(ct[i], row[i]))); 28 | return IntStream.range(0, ints.length) 29 | .mapToObj(r -> IntStream.range(0, ints[r].length).map(c -> Math.min(rt[r], ct[c])).toArray()) 30 | .toArray(int[][]::new); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /java/reverse/ReverseSumFastTest.java: -------------------------------------------------------------------------------- 1 | package reverse; 2 | 3 | /** 4 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 5 | */ 6 | public class ReverseSumFastTest { 7 | public static void main(String... args) { 8 | new ReverseSumTest(1000_000).run(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /java/reverse/ReverseSumTest.java: -------------------------------------------------------------------------------- 1 | package reverse; 2 | 3 | import java.util.Arrays; 4 | import java.util.stream.IntStream; 5 | 6 | /** 7 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 8 | */ 9 | public class ReverseSumTest extends ReverseTest { 10 | public ReverseSumTest(final int maxSize) { 11 | super("ReverseSum", maxSize); 12 | } 13 | 14 | public static void main(String... args) { 15 | new ReverseSumTest(MAX_SIZE).run(); 16 | } 17 | 18 | @Override 19 | protected int[][] transform(final int[][] ints) { 20 | final int[] rt = Arrays.stream(ints) 21 | .map(Arrays::stream) 22 | .mapToInt(IntStream::sum) 23 | .toArray(); 24 | final int[] ct = new int[Arrays.stream(ints).mapToInt(r -> r.length).max().orElse(0)]; 25 | Arrays.stream(ints).forEach(row -> IntStream.range(0, row.length).forEach(i -> ct[i] += row[i])); 26 | return IntStream.range(0, ints.length) 27 | .mapToObj(r -> IntStream.range(0, ints[r].length).map(c -> rt[r] + ct[c] - ints[r][c]).toArray()) 28 | .toArray(int[][]::new); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /java/reverse/ReverseTest.java: -------------------------------------------------------------------------------- 1 | package reverse; 2 | 3 | import java.util.Arrays; 4 | import java.util.stream.IntStream; 5 | 6 | /** 7 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 8 | */ 9 | public class ReverseTest { 10 | public static final int MAX_SIZE = 10_000; 11 | private final ReverseChecker checker; 12 | private final int maxSize; 13 | 14 | public ReverseTest(final int maxSize) { 15 | this("Reverse", maxSize); 16 | } 17 | 18 | protected ReverseTest(final String className, final int maxSize) { 19 | checker = new ReverseChecker(className); 20 | this.maxSize = maxSize; 21 | } 22 | 23 | public static void main(String... args) { 24 | new ReverseTest("Reverse", MAX_SIZE).run(); 25 | } 26 | 27 | protected void run() { 28 | test(new int[][]{ 29 | {1} 30 | }); 31 | test(new int[][]{ 32 | {1, 2}, 33 | {3} 34 | }); 35 | test(new int[][]{ 36 | {1, 2, 3}, 37 | {4, 5}, 38 | {6} 39 | }); 40 | test(new int[][]{ 41 | {1, 2, 3}, 42 | {}, 43 | {4, 5}, 44 | {6} 45 | }); 46 | test(new int[][]{ 47 | {1, 2, 3}, 48 | {-4, -5}, 49 | {6} 50 | }); 51 | test(new int[][]{ 52 | {1, -2, 3}, 53 | {}, 54 | {4, -5}, 55 | {6} 56 | }); 57 | test(new int[][]{ 58 | {1, -2, 3}, 59 | {}, 60 | {-4, -5}, 61 | {6} 62 | }); 63 | test(new int[][]{ 64 | {}, 65 | }); 66 | test(new int[][]{ 67 | {}, 68 | {}, 69 | {}, 70 | }); 71 | testRandom(tweakProfile(constProfile(10, 10), new int[][]{})); 72 | testRandom(tweakProfile(constProfile(100, 100), new int[][]{})); 73 | testRandom(randomProfile(100, maxSize)); 74 | testRandom(randomProfile(maxSize / 10, maxSize)); 75 | testRandom(randomProfile(maxSize, maxSize)); 76 | testRandom(tweakProfile(constProfile(maxSize, 0), new int[][]{new int[]{maxSize, 0}})); 77 | testRandom(tweakProfile(randomProfile(maxSize, maxSize), new int[][]{new int[]{maxSize, 0}})); 78 | testRandom(tweakProfile(constProfile(maxSize, 0), new int[][]{new int[]{maxSize / 2, maxSize / 2 - 1}})); 79 | testRandom(tweakProfile(constProfile(maxSize, 1), new int[][]{new int[]{maxSize / 3, maxSize / 3, maxSize * 2 / 3}})); 80 | checker.printStatus(); 81 | } 82 | 83 | protected int[] randomProfile(final int length, final int values) { 84 | final int[] profile = new int[length]; 85 | for (int i = 0; i < values; i++) { 86 | profile[checker.randomInt(0, length - 1)]++; 87 | } 88 | return profile; 89 | } 90 | 91 | protected void testRandom(final int[] profile) { 92 | test(checker.random(profile)); 93 | } 94 | 95 | public static int[] constProfile(final int length, final int value) { 96 | final int[] profile = new int[length]; 97 | Arrays.fill(profile, value); 98 | return profile; 99 | } 100 | 101 | public static int[] tweakProfile(final int[] profile, final int[][] mods) { 102 | for (int[] mod : mods) { 103 | Arrays.stream(mod).skip(1).forEach(i -> profile[i] = mod[0]); 104 | } 105 | return profile; 106 | } 107 | 108 | protected void test(final int[][] ints) { 109 | checker.test(ints, transform(ints)); 110 | } 111 | 112 | protected int[][] transform(final int[][] ints) { 113 | return IntStream.range(1, ints.length + 1) 114 | .mapToObj(i -> ints[ints.length - i]) 115 | .map(is -> IntStream.range(1, is.length + 1).map(i -> is[is.length - i]).toArray()) 116 | .toArray(int[][]::new); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /java/reverse/ReverseTransposeTest.java: -------------------------------------------------------------------------------- 1 | package reverse; 2 | 3 | import java.util.Arrays; 4 | import java.util.stream.IntStream; 5 | 6 | /** 7 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 8 | */ 9 | public class ReverseTransposeTest extends ReverseTest { 10 | public ReverseTransposeTest(final int maxSize) { 11 | super("ReverseTranspose", maxSize); 12 | } 13 | 14 | public static void main(String... args) { 15 | new ReverseTransposeTest(MAX_SIZE).run(); 16 | } 17 | 18 | @Override 19 | protected int[][] transform(final int[][] ints) { 20 | return IntStream.range(0, Arrays.stream(ints).mapToInt(r -> r.length).max().orElse(0)) 21 | .mapToObj(c -> Arrays.stream(ints).filter(r -> r.length > c).mapToInt(r -> r[c]).toArray()) 22 | .toArray(int[][]::new); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /java/search/BinarySearchBaseTest.java: -------------------------------------------------------------------------------- 1 | package search; 2 | 3 | import base.MainChecker; 4 | 5 | import java.util.Arrays; 6 | import java.util.Collections; 7 | import java.util.stream.Collectors; 8 | import java.util.stream.IntStream; 9 | 10 | /** 11 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 12 | */ 13 | public class BinarySearchBaseTest { 14 | public static void test(final String className, final Solver solver) { 15 | final MainChecker checker = new MainChecker("search." + className); 16 | 17 | test(checker, solver, 0); 18 | test(checker, solver, 0, 0); 19 | for (final int size : new int[]{5, 4, 2, 1, 0, 10, 100}) { 20 | final int[] a = new int[size]; 21 | for (final int max : new int[]{5, 4, 2, 1, 0, 10, 100, Integer.MAX_VALUE / 2}) { 22 | for (int i = 0; i < size; i++) { 23 | a[i] = checker.random.nextInt(max * 2 + 1) - max; 24 | } 25 | Arrays.sort(a); 26 | for (int i = 0; i < size / 2; i++) { 27 | final int t = a[i]; 28 | a[i] = a[size - i - 1]; 29 | a[size - i - 1] = t; 30 | } 31 | for (int i = 0; i < size; i++) { 32 | test(checker, solver, a[i], a); 33 | if (i != 0) { 34 | test(checker, solver, (a[i - 1] + a[i]) / 2, a); 35 | } 36 | } 37 | test(checker, solver, Integer.MIN_VALUE, a); 38 | test(checker, solver, Integer.MAX_VALUE, a); 39 | } 40 | } 41 | checker.printStatus(); 42 | } 43 | 44 | private static void test(final MainChecker checker, final Solver solver, final int x, final int... a) { 45 | checker.checkEquals( 46 | Collections.singletonList(Arrays.stream(solver.solve(x, a)).mapToObj(Long::toString).collect(Collectors.joining(" "))), 47 | checker.run(IntStream.concat(IntStream.of(x), IntStream.of(a)).mapToObj(Integer::toString).toArray(String[]::new)) 48 | ); 49 | } 50 | 51 | interface Solver { 52 | long[] solve(final int x, final int... a); 53 | } 54 | 55 | public static long[] longs(final long... longs) { 56 | return longs; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /java/search/BinarySearchMissingTest.java: -------------------------------------------------------------------------------- 1 | package search; 2 | 3 | /** 4 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 5 | */ 6 | public class BinarySearchMissingTest extends BinarySearchBaseTest { 7 | public static void main(final String... args) { 8 | test("BinarySearchMissing", (x, a) -> { 9 | for (int i = 0; i < a.length; i++) { 10 | if (a[i] == x) { 11 | return longs(i); 12 | } 13 | if (x > a[i]) { 14 | return longs(-1 - i); 15 | } 16 | } 17 | return longs(-1 - a.length); 18 | }); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /java/search/BinarySearchSpanTest.java: -------------------------------------------------------------------------------- 1 | package search; 2 | 3 | /** 4 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 5 | */ 6 | public class BinarySearchSpanTest extends BinarySearchBaseTest { 7 | public static void main(final String... args) { 8 | test("BinarySearchSpan", (x, a) -> { 9 | for (int i = 0; i < a.length; i++) { 10 | if (a[i] == x) { 11 | int j = i; 12 | while (j < a.length && a[j] == x) { 13 | j++; 14 | } 15 | return longs(i, j - i); 16 | } 17 | if (x > a[i]) { 18 | return longs(i, 0); 19 | } 20 | } 21 | return longs(a.length, 0); 22 | }); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /java/search/BinarySearchTest.java: -------------------------------------------------------------------------------- 1 | package search; 2 | 3 | /** 4 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 5 | */ 6 | public class BinarySearchTest extends BinarySearchBaseTest { 7 | public static void main(final String... args) { 8 | test("BinarySearch", (x, a) -> { 9 | for (int i = 0; i < a.length; i++) { 10 | if (a[i] <= x) { 11 | return longs(i); 12 | } 13 | } 14 | return longs(a.length); 15 | }); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /java/sum/SChecker.java: -------------------------------------------------------------------------------- 1 | package sum; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 7 | */ 8 | public interface SChecker { 9 | void test(Number result, String... input); 10 | 11 | void printStatus(); 12 | 13 | Random getRandom(); 14 | 15 | String randomString(final String chars); 16 | } 17 | -------------------------------------------------------------------------------- /java/sum/SumAbcFileTest.java: -------------------------------------------------------------------------------- 1 | package sum; 2 | 3 | /** 4 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 5 | */ 6 | public class SumAbcFileTest { 7 | public static void main(final String... args) { 8 | new SumAbcTest(new SumFileChecker("SumAbcFile")).run(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /java/sum/SumAbcTest.java: -------------------------------------------------------------------------------- 1 | package sum; 2 | 3 | import java.util.stream.Collectors; 4 | 5 | /** 6 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 7 | */ 8 | public class SumAbcTest extends SumTest { 9 | public SumAbcTest(final SChecker checker) { 10 | super(checker); 11 | } 12 | 13 | public static void main(final String... args) { 14 | new SumAbcTest(new SumChecker("SumAbc")).run(); 15 | } 16 | 17 | @Override 18 | protected void test() { 19 | test(1, "b"); 20 | test(6, "b", "C", "d"); 21 | test(1, " b"); 22 | test(1, "b "); 23 | test(1, "\tb\t"); 24 | test(12345, "\tabcdef\t"); 25 | test(1368, " abcd efg hij "); 26 | test(60, "Aba", "acA", "aDa"); 27 | 28 | test(12345678, "bcdefghi"); 29 | test(20541014, "CafeBabe"); 30 | test(34031445, "DeadBeef"); 31 | 32 | test(-1, "-b"); 33 | test(-6, "-b", "-c", "-d"); 34 | test(-12345, "\t-abCDef\t"); 35 | test(-60, " -ABA -aca -ADA "); 36 | test(1, "+b"); 37 | test(6, "+b", "+c", "+d"); 38 | test(12345, "\t+abCDef\t"); 39 | test(60, " +ABA +aca +ADA "); 40 | test(0); 41 | test(0, " "); 42 | test(Integer.MAX_VALUE, toString(Integer.MAX_VALUE)); 43 | test(Integer.MIN_VALUE, toString(Integer.MIN_VALUE)); 44 | 45 | randomTest(10, 100); 46 | randomTest(10, Integer.MAX_VALUE); 47 | randomTest(100, Integer.MAX_VALUE); 48 | } 49 | 50 | @Override 51 | protected String toString(final Number number) { 52 | return number.toString().chars() 53 | .map("+-0123456789"::indexOf) 54 | .map("+-abcdefghij"::charAt) 55 | .mapToObj(ch -> "" + (char) ch) 56 | .collect(Collectors.joining()); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /java/sum/SumBigIntegerDigitTest.java: -------------------------------------------------------------------------------- 1 | package sum; 2 | 3 | /** 4 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 5 | */ 6 | public class SumBigIntegerDigitTest extends SumBigIntegerTest { 7 | public SumBigIntegerDigitTest(final SChecker checker) { 8 | super(checker); 9 | } 10 | 11 | public static void main(final String... args) { 12 | new SumBigIntegerDigitTest(new SumChecker("SumBigInteger")).run(); 13 | } 14 | 15 | @Override 16 | protected void test() { 17 | test(1, "1"); 18 | test(6, "1", "2", "3"); 19 | test(1, " 1"); 20 | test(1, "1 "); 21 | test(1, "\u00a01\u00a0"); 22 | test(12345, "\u00a012345\u00a0"); 23 | test(1368, " 123 456 789 "); 24 | test(60, "010", "020", "030"); 25 | test(-1, "-1"); 26 | test(-6, "-1", "-2", "-3"); 27 | test(-12345, "\u00a0-12345\u00a0"); 28 | test(-1368, " -123 -456 -789 "); 29 | test(1, "+1"); 30 | test(6, "+1", "+2", "+3"); 31 | test(12345, "\u00a0+12345\u00a0"); 32 | test(1368, " +123 +456 +789 "); 33 | test(0); 34 | test(0, " "); 35 | test(0, "10000000000000000000000000000000000000000 -10000000000000000000000000000000000000000"); 36 | randomTest(10, 10); 37 | randomTest(10, 100); 38 | randomTest(10, 1000); 39 | randomTest(10, 10000); 40 | randomTest(1000, 10000); 41 | } 42 | 43 | @Override 44 | protected String getSpaces() { 45 | return " abc\u2000\u2001\u2002\u2003\u00A0\u2007\u202F\u2382"; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /java/sum/SumBigIntegerTest.java: -------------------------------------------------------------------------------- 1 | package sum; 2 | 3 | import java.math.BigInteger; 4 | import java.util.Arrays; 5 | import java.util.Random; 6 | 7 | /** 8 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 9 | */ 10 | public class SumBigIntegerTest extends SumTest { 11 | public SumBigIntegerTest(final SChecker checker) { 12 | super(checker); 13 | } 14 | 15 | public static void main(final String... args) { 16 | new SumBigIntegerTest(new SumChecker("SumBigInteger")).run(); 17 | } 18 | 19 | @Override 20 | protected void test() { 21 | test(1, "1"); 22 | test(6, "1", "2", "3"); 23 | test(1, " 1"); 24 | test(1, "1 "); 25 | test(1, "\t1\t"); 26 | test(12345, "\t12345\t"); 27 | test(1368, " 123 456 789 "); 28 | test(60, "010", "020", "030"); 29 | test(-1, "-1"); 30 | test(-6, "-1", "-2", "-3"); 31 | test(-12345, "\t-12345\t"); 32 | test(-1368, " -123 -456 -789 "); 33 | test(1, "+1"); 34 | test(6, "+1", "+2", "+3"); 35 | test(12345, "\t+12345\t"); 36 | test(1368, " +123 +456 +789 "); 37 | test(0); 38 | test(0, " "); 39 | test(0, "10000000000000000000000000000000000000000 -10000000000000000000000000000000000000000"); 40 | randomTest(10, 10); 41 | randomTest(10, 100); 42 | randomTest(10, 1000); 43 | randomTest(10, 10000); 44 | randomTest(1000, 10000); 45 | } 46 | 47 | @Override 48 | protected Number sum(final Number[] values) { 49 | return Arrays.stream(values).map(v -> (BigInteger) v).reduce(BigInteger.ZERO, BigInteger::add); 50 | } 51 | 52 | @Override 53 | protected Number randomValue(final Number max, final Random random) { 54 | BigInteger v = new BigInteger(max.intValue(), random); 55 | if (random.nextBoolean()) { 56 | v = v.negate(); 57 | } 58 | return v; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /java/sum/SumChecker.java: -------------------------------------------------------------------------------- 1 | package sum; 2 | 3 | import base.MainChecker; 4 | 5 | import java.util.Collections; 6 | 7 | /** 8 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 9 | */ 10 | public class SumChecker extends MainChecker implements SChecker { 11 | public SumChecker(final String className) { 12 | super(className); 13 | } 14 | 15 | @Override 16 | public void test(final Number result, final String... input) { 17 | checkEquals(Collections.singletonList(result.toString()), run(input)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /java/sum/SumFileChecker.java: -------------------------------------------------------------------------------- 1 | package sum; 2 | 3 | import base.MainFilesChecker; 4 | 5 | import java.util.Arrays; 6 | import java.util.Collections; 7 | 8 | /** 9 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 10 | */ 11 | public class SumFileChecker extends MainFilesChecker implements SChecker { 12 | public SumFileChecker(final String className) { 13 | super(className); 14 | } 15 | 16 | public void test(final Number result, final String... input) { 17 | checkEquals(Collections.singletonList(result.toString()), runFiles(Arrays.asList(input))); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /java/sum/SumFileTest.java: -------------------------------------------------------------------------------- 1 | package sum; 2 | 3 | /** 4 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 5 | */ 6 | public class SumFileTest { 7 | public static void main(final String... args) { 8 | new SumTest(new SumFileChecker("SumFile")).run(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /java/sum/SumHexFileTest.java: -------------------------------------------------------------------------------- 1 | package sum; 2 | 3 | /** 4 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 5 | */ 6 | public class SumHexFileTest extends SumHexTest { 7 | public SumHexFileTest(final SChecker checker) { 8 | super(checker); 9 | } 10 | 11 | public static void main(final String... args) { 12 | new SumHexTest(new SumFileChecker("SumHexFile")).run(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /java/sum/SumHexTest.java: -------------------------------------------------------------------------------- 1 | package sum; 2 | 3 | /** 4 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 5 | */ 6 | public class SumHexTest extends SumTest { 7 | 8 | public SumHexTest(final SChecker checker) { 9 | super(checker); 10 | } 11 | 12 | public static void main(final String... args) { 13 | new SumHexTest(new SumChecker("SumHex")).run(); 14 | } 15 | 16 | @Override 17 | protected void test() { 18 | test(1, "1"); 19 | test(6, "1", "2", "3"); 20 | test(1, " 1"); 21 | test(1, "1 "); 22 | test(1, "\t1\t"); 23 | test(12345, "\t12345\t"); 24 | test(1368, " 123 456 789 "); 25 | test(60, "010", "020", "030"); 26 | 27 | test(1, "0x1"); 28 | test(0x1a, "0x1a"); 29 | test(0xA2, "0xA2"); 30 | test(62, " 0X0 0X1 0XF 0XF 0x0 0x1 0xF 0xf"); 31 | test(0x12345678, "0x12345678"); 32 | test(0x90abcdef, "0x90abcdef"); 33 | test(0xCafeBabe, "0xCafeBabe"); 34 | test(0xDeadBeef, "0xDeadBeef"); 35 | 36 | test(-1, "-1"); 37 | test(-6, "-1", "-2", "-3"); 38 | test(-12345, "\t-12345\t"); 39 | test(-1368, " -123 -456 -789 "); 40 | test(1, "+1"); 41 | test(6, "+1", "+2", "+3"); 42 | test(12345, "\t+12345\t"); 43 | test(1368, " +123 +456 +789 "); 44 | test(0); 45 | test(0, " "); 46 | 47 | test(Integer.MAX_VALUE, "0" + Integer.MAX_VALUE); 48 | test(Integer.MIN_VALUE, "" + Integer.MIN_VALUE); 49 | test(Integer.MAX_VALUE, "0x" + Integer.toHexString(Integer.MAX_VALUE)); 50 | test(Integer.MIN_VALUE, "0x" + Integer.toHexString(Integer.MIN_VALUE)); 51 | 52 | randomTest(10, 100); 53 | randomTest(10, Integer.MAX_VALUE); 54 | randomTest(100, Integer.MAX_VALUE); 55 | } 56 | 57 | 58 | @Override 59 | protected String toString(final Number number) { 60 | return checker.getRandom().nextBoolean() ? super.toString(number) : "0X" + Integer.toHexString(number.intValue()); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /java/sum/SumTest.java: -------------------------------------------------------------------------------- 1 | package sum; 2 | 3 | import java.util.*; 4 | import java.util.stream.Collectors; 5 | 6 | /** 7 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 8 | */ 9 | public class SumTest { 10 | protected final SChecker checker; 11 | 12 | protected SumTest(final SChecker checker) { 13 | this.checker = checker; 14 | } 15 | 16 | public static void main(final String... args) { 17 | new SumTest(new SumChecker("Sum")).run(); 18 | } 19 | 20 | public void run() { 21 | test(); 22 | checker.printStatus(); 23 | } 24 | 25 | protected void test() { 26 | test(1, "1"); 27 | test(6, "1", "2", "3"); 28 | test(1, " 1"); 29 | test(1, "1 "); 30 | test(1, "\t1\t"); 31 | test(12345, "\t12345\t"); 32 | test(60, "010", "020", "030"); 33 | test(1368, " 123 456 789 "); 34 | test(-1, "-1"); 35 | test(-6, "-1", "-2", "-3"); 36 | test(-12345, "\t-12345\t"); 37 | test(-1368, " -123 -456 -789 "); 38 | test(1, "+1"); 39 | test(6, "+1", "+2", "+3"); 40 | test(12345, "\t+12345\t"); 41 | test(1368, " +123 +456 +789 "); 42 | test(0); 43 | test(0, " "); 44 | randomTest(10, 100); 45 | randomTest(10, Integer.MAX_VALUE); 46 | randomTest(100, Integer.MAX_VALUE); 47 | } 48 | 49 | protected void test(final Number result, final String... input) { 50 | checker.test(result, input); 51 | } 52 | 53 | protected void randomTest(final int numbers, final Number max) { 54 | Number[] values = new Number[numbers]; 55 | for (int i = 0; i < values.length; i++) { 56 | values[i] = randomValue(max, checker.getRandom()); 57 | } 58 | testRandom(sum(values), values); 59 | } 60 | 61 | protected void testRandom(final Number result, final Number[] args) { 62 | final List spaced = Arrays.stream(args) 63 | .map(this::toString) 64 | .map(value -> randomSpace() + value + randomSpace()) 65 | .collect(Collectors.toList()); 66 | final List argsList = new ArrayList<>(); 67 | for (final Iterator i = spaced.listIterator(); i.hasNext(); ) { 68 | StringBuilder next = new StringBuilder(i.next()); 69 | while (i.hasNext() && checker.getRandom().nextBoolean()) { 70 | next.append(randomSpace()).append(i.next()); 71 | } 72 | argsList.add(next.toString()); 73 | } 74 | test(result, argsList.toArray(new String[0])); 75 | } 76 | 77 | private String randomSpace() { 78 | return checker.randomString(getSpaces()); 79 | } 80 | 81 | protected String getSpaces() { 82 | return " \t\n\u000B\u2029\f"; 83 | } 84 | 85 | protected String toString(Number number) { 86 | return number.toString(); 87 | } 88 | 89 | protected Number sum(Number[] values) { 90 | return Arrays.stream(values).mapToInt(Number::intValue).sum(); 91 | } 92 | 93 | protected Number randomValue(final Number max, final Random random) { 94 | return random.nextInt() % max.intValue(); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /java/wordStat/WordStatChecker.java: -------------------------------------------------------------------------------- 1 | package wordStat; 2 | 3 | import base.Asserts; 4 | import base.MainFilesChecker; 5 | import base.Pair; 6 | import base.Randomized; 7 | 8 | import java.util.Arrays; 9 | import java.util.List; 10 | import java.util.stream.Collectors; 11 | 12 | /** 13 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 14 | */ 15 | public class WordStatChecker extends MainFilesChecker { 16 | public static final String DASH = "-֊־‒–—―⸗⸚⸺〰゠︱︲﹘﹣-'"; 17 | public static final String SIMPLE_DELIMITERS = " \t"; 18 | public static final String ADVANCED_DELIMITERS = " \t!\"#$%&()*+,./0123456789:;<=>?@[\\]^_`{|}~ ¡¢£¤¥¦§¨©«¬\u00AD®¯°±²³´¶·¸¹»¼½¾¿×÷˂˃˄˅˒˓˔˕˖˗˘˙˚˛˜˝₴₵₶₷₸₹₺\u20BB\u20BC\u20BD\u20BE"; 19 | 20 | public WordStatChecker(final String className) { 21 | super(className); 22 | } 23 | 24 | @SafeVarargs 25 | public final void test(final String[] text, final Pair... expected) { 26 | final List expectedList = Arrays.stream(expected) 27 | .map(p -> p.first + " " + p.second) 28 | .collect(Collectors.toList()); 29 | Asserts.assertEquals("output", expectedList, runFiles(Arrays.asList(text))); 30 | counter.passed(); 31 | } 32 | 33 | public String[] generateWords(final int wordLength, final int totalWords, final String chars) { 34 | return generateWords(wordLength, totalWords, chars, this); 35 | } 36 | 37 | public static String[] generateWords(final int wordLength, final int totalWords, final String chars, final Randomized randomized) { 38 | final String allChars = chars + chars.toUpperCase(); 39 | final String[] words = new String[totalWords]; 40 | for (int i = 0; i < totalWords; i++) { 41 | words[i] = randomized.randomString(allChars, wordLength / 2, wordLength); 42 | } 43 | return words; 44 | } 45 | 46 | public String[][] generateTest(final int lines, final String[] words, final int wordsPerLine) { 47 | return generateTest(lines, words, wordsPerLine, this); 48 | } 49 | 50 | public static String[][] generateTest(final int lines, final String[] words, final int wordsPerLine, final Randomized randomized) { 51 | final String[][] text = new String[lines][]; 52 | for (int i = 0; i < text.length; i++) { 53 | text[i] = new String[randomized.randomInt(wordsPerLine / 2, wordsPerLine)]; 54 | for (int j = 0; j < text[i].length; j++) { 55 | text[i][j] = randomized.randomItem(words); 56 | } 57 | } 58 | return text; 59 | } 60 | 61 | String[] input(final String[][] text, final String delimiters) { 62 | final String[] input = new String[text.length]; 63 | for (int i = 0; i < text.length; i++) { 64 | String[] line = text[i]; 65 | final StringBuilder sb = new StringBuilder(randomString(delimiters)); 66 | for (String word : line) { 67 | sb.append(word).append(randomString(delimiters)); 68 | } 69 | input[i] = sb.toString(); 70 | } 71 | return input; 72 | } 73 | 74 | public void test(final String[][] text, final String delimiters, final Pair[] answer) { 75 | test(input(text, delimiters), answer); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /java/wordStat/WordStatIndexChecker.java: -------------------------------------------------------------------------------- 1 | package wordStat; 2 | 3 | import base.Asserts; 4 | import base.Pair; 5 | 6 | import java.util.Arrays; 7 | import java.util.List; 8 | import java.util.stream.Collectors; 9 | 10 | /** 11 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 12 | */ 13 | public class WordStatIndexChecker extends WordStatChecker { 14 | public WordStatIndexChecker(final String className) { 15 | super(className); 16 | } 17 | 18 | @SafeVarargs 19 | public final void testPP(final String[] text, final Pair... expected) { 20 | final List expectedList = Arrays.stream(expected) 21 | .map(p -> p.first + " " + p.second) 22 | .collect(Collectors.toList()); 23 | Asserts.assertEquals("output", expectedList, runFiles(Arrays.asList(text))); 24 | counter.passed(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /java/wordStat/WordStatIndexTest.java: -------------------------------------------------------------------------------- 1 | package wordStat; 2 | 3 | import base.Pair; 4 | import base.Randomized; 5 | 6 | import java.util.*; 7 | import java.util.stream.Collectors; 8 | import java.util.stream.IntStream; 9 | 10 | /** 11 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 12 | */ 13 | public class WordStatIndexTest { 14 | private final WordStatIndexChecker checker; 15 | 16 | public WordStatIndexTest(final String className) { 17 | checker = new WordStatIndexChecker(className); 18 | } 19 | 20 | public static void main(final String... args) { 21 | new WordStatIndexTest("WordStatIndex").run(); 22 | } 23 | 24 | protected void run() { 25 | test(); 26 | checker.printStatus(); 27 | } 28 | 29 | private void test() { 30 | testPP( 31 | "To be, or not to be, that is the question:"); 32 | testPP( 33 | "Monday's child is fair of face.", 34 | "Tuesday's child is full of grace."); 35 | testPP( 36 | "Шалтай-Болтай", 37 | "Сидел на стене.", 38 | "Шалтай-Болтай", 39 | "Свалился во сне." 40 | ); 41 | 42 | randomTest(3, 10, 10, 3, Randomized.ENGLISH, WordStatChecker.SIMPLE_DELIMITERS); 43 | randomTest(10, 3, 5, 5, Randomized.RUSSIAN, WordStatChecker.SIMPLE_DELIMITERS); 44 | randomTest(3, 10, 10, 3, Randomized.GREEK, WordStatChecker.SIMPLE_DELIMITERS); 45 | randomTest(3, 10, 10, 3, WordStatChecker.DASH, WordStatChecker.SIMPLE_DELIMITERS); 46 | randomTest(3, 10, 10, 3, Randomized.ENGLISH, WordStatChecker.ADVANCED_DELIMITERS); 47 | randomTest(10, 3, 5, 5, Randomized.RUSSIAN, WordStatChecker.ADVANCED_DELIMITERS); 48 | randomTest(3, 10, 10, 3, Randomized.GREEK, WordStatChecker.ADVANCED_DELIMITERS); 49 | randomTest(3, 10, 10, 3, WordStatChecker.DASH, WordStatChecker.ADVANCED_DELIMITERS); 50 | randomTest(100, 1000, 1000, 1000, Randomized.RUSSIAN + Randomized.ENGLISH + Randomized.GREEK + WordStatChecker.DASH, WordStatChecker.ADVANCED_DELIMITERS); 51 | } 52 | 53 | private void randomTest(final int wordLength, final int totalWords, final int wordsPerLine, final int lines, final String chars, final String delimiters) { 54 | final String[] words = checker.generateWords(wordLength, totalWords, chars); 55 | final String[][] text = checker.generateTest(lines, words, wordsPerLine); 56 | checker.testPP(checker.input(text, delimiters), answer(text)); 57 | } 58 | 59 | public void testPP(String... lines) { 60 | checker.testPP(lines, answer(Arrays.stream(lines).map(s -> s.split("[ ,.:]+")).toArray(String[][]::new))); 61 | } 62 | 63 | // Stream "magic" code. You do not expected to understand it 64 | @SuppressWarnings("unchecked") 65 | protected Pair[] answer(final String[][] text) { 66 | final List all = Arrays.stream(text) 67 | .flatMap(Arrays::stream) 68 | .map(String::toLowerCase) 69 | .collect(Collectors.toList()); 70 | return IntStream.range(0, all.size()).boxed() 71 | .collect(Collectors.toMap(all::get, Collections::singletonList, WordStatIndexTest::concat, LinkedHashMap::new)).entrySet().stream() 72 | .map(e -> Pair.of(e.getKey(), e.getValue().size() + " " + e.getValue().stream().map(i -> i + 1 + "").collect(Collectors.joining(" ")))) 73 | .toArray(i -> (Pair[]) new Pair[i]); 74 | } 75 | 76 | protected static List concat(final List as, final List bs) { 77 | final List rs = as instanceof ArrayList ? as : new ArrayList<>(as); 78 | rs.addAll(bs); 79 | return rs; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /java/wordStat/WordStatInputTest.java: -------------------------------------------------------------------------------- 1 | package wordStat; 2 | 3 | import base.Pair; 4 | import base.Randomized; 5 | 6 | import java.util.Arrays; 7 | import java.util.LinkedHashMap; 8 | import java.util.stream.Collectors; 9 | import java.util.stream.Stream; 10 | 11 | /** 12 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 13 | */ 14 | public class WordStatInputTest { 15 | private final WordStatChecker checker; 16 | 17 | public WordStatInputTest(final String className) { 18 | checker = new WordStatChecker(className); 19 | } 20 | 21 | public static void main(final String... args) { 22 | new WordStatInputTest("WordStatInput").run(); 23 | } 24 | 25 | protected void run() { 26 | test(); 27 | checker.printStatus(); 28 | } 29 | 30 | protected void test() { 31 | test( 32 | "To be, or not to be, that is the question:" 33 | ); 34 | test( 35 | "Monday's child is fair of face.", 36 | "Tuesday's child is full of grace." 37 | ); 38 | test( 39 | "Шалтай-Болтай", 40 | "Сидел на стене.", 41 | "Шалтай-Болтай", 42 | "Свалился во сне." 43 | ); 44 | test( 45 | "10 октября — Всемирный день психического здоровья", 46 | "Тема 2017 года: Психическое здоровье на рабочем месте" 47 | ); 48 | 49 | randomTest(3, 10, 10, 3, Randomized.ENGLISH, WordStatChecker.SIMPLE_DELIMITERS); 50 | randomTest(10, 3, 5, 5, Randomized.RUSSIAN, WordStatChecker.SIMPLE_DELIMITERS); 51 | randomTest(3, 10, 10, 3, Randomized.GREEK, WordStatChecker.SIMPLE_DELIMITERS); 52 | randomTest(3, 10, 10, 3, WordStatChecker.DASH, WordStatChecker.SIMPLE_DELIMITERS); 53 | randomTest(3, 10, 10, 3, Randomized.ENGLISH, WordStatChecker.ADVANCED_DELIMITERS); 54 | randomTest(10, 3, 5, 5, Randomized.RUSSIAN, WordStatChecker.ADVANCED_DELIMITERS); 55 | randomTest(3, 10, 10, 3, Randomized.GREEK, WordStatChecker.ADVANCED_DELIMITERS); 56 | randomTest(3, 10, 10, 3, WordStatChecker.DASH, WordStatChecker.ADVANCED_DELIMITERS); 57 | randomTest(100, 1000, 100, 1000, Randomized.RUSSIAN + Randomized.ENGLISH + Randomized.GREEK + WordStatChecker.DASH, WordStatChecker.ADVANCED_DELIMITERS); 58 | } 59 | 60 | private void randomTest(final int wordLength, final int totalWords, final int wordsPerLine, final int lines, final String chars, final String delimiters) { 61 | final String[] words = checker.generateWords(wordLength, totalWords, chars); 62 | final String[][] text = checker.generateTest(lines, words, wordsPerLine); 63 | checker.test(checker.input(text, delimiters), answer(text)); 64 | } 65 | 66 | public void test(final String... text) { 67 | checker.test(text, answer(Arrays.stream(text).map(s -> s.split("[ ,.:0-9]+")).toArray(String[][]::new))); 68 | } 69 | 70 | // Stream "magic" code. You do not expected to understand it 71 | @SuppressWarnings("unchecked") 72 | protected Pair[] answer(final String[][] text) { 73 | return answer(Arrays.stream(text).flatMap(Arrays::stream).filter(s -> !s.isEmpty())) 74 | .toArray(i -> (Pair[]) new Pair[i]); 75 | } 76 | 77 | // Stream "magic" code. You do not expected to understand it 78 | protected Stream> answer(final Stream input) { 79 | return input 80 | .collect(Collectors.toMap(String::toLowerCase, v -> 1, Integer::sum, LinkedHashMap::new)).entrySet().stream() 81 | .map(Pair::of); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /java/wordStat/WordStatLineIndexTest.java: -------------------------------------------------------------------------------- 1 | package wordStat; 2 | 3 | import base.Pair; 4 | 5 | import java.util.Collections; 6 | import java.util.List; 7 | import java.util.TreeMap; 8 | import java.util.stream.Collectors; 9 | import java.util.stream.IntStream; 10 | 11 | /** 12 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 13 | */ 14 | public class WordStatLineIndexTest extends WordStatIndexTest { 15 | public WordStatLineIndexTest(final String className) { 16 | super(className); 17 | } 18 | 19 | public static void main(String[] args) { 20 | new WordStatLineIndexTest("WordStatLineIndex").run(); 21 | } 22 | 23 | @Override 24 | protected List> answer(final String[][] text) { 25 | return IntStream.range(0, text.length).boxed() 26 | .flatMap( 27 | r -> IntStream.range(0, text[r].length) 28 | .mapToObj(c -> Pair.of(text[r][c].toLowerCase(), (r + 1) + ":" + (c + 1))) 29 | ).collect(Collectors.toMap(Pair::getFirst, p -> Collections.singletonList(p.getSecond()), WordStatIndexTest::concat, TreeMap::new)).entrySet().stream() 30 | .map(e -> Pair.of(e.getKey(), e.getValue().size() + " " + e.getValue().stream().map(Object::toString).collect(Collectors.joining(" ")))) 31 | .collect(Collectors.toList()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /java/wordStat/WordStatWordsTest.java: -------------------------------------------------------------------------------- 1 | package wordStat; 2 | 3 | import base.Pair; 4 | 5 | import java.util.*; 6 | import java.util.stream.Collectors; 7 | import java.util.stream.Stream; 8 | 9 | /** 10 | * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) 11 | */ 12 | public class WordStatWordsTest extends WordStatInputTest { 13 | private static final WordStatChecker CHECKER = new WordStatChecker("WordStatWords"); 14 | 15 | public WordStatWordsTest(final String className) { 16 | super(className); 17 | } 18 | 19 | public static void main(final String... args) { 20 | new WordStatWordsTest("WordStatWords").run(); 21 | } 22 | 23 | // Stream "magic" code. You do not expected to understand it 24 | protected Stream> answer(final Stream input) { 25 | return input 26 | .collect(Collectors.toMap(String::toLowerCase, v -> 1, Integer::sum)).entrySet().stream() 27 | .map(Pair::of) 28 | .sorted(Comparator.comparing(Pair::getFirst)); 29 | } 30 | } 31 | --------------------------------------------------------------------------------