JavaOpen и JavaDay в Самаре

в 12:25, , рубрики: java, javaday, oracle, задачи для программистов, конференция, Программирование, самара, турнир, метки: , , , , , , ,
JavaOpen и JavaDay в Самаре

Недавно в Самаре прошли два занимательных мероприятия: JavaOpen и JavaDay.

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

Конференция

К сожалению, удалось посетить только конференцию. Зал на 150 человек был заполнен наполовину, это при учете того, что мероприятие выпало на рабочий день. Доклады были отличные. Особенно порадовала демонстрация Java FX и Java ME Embedded на Raspberry Pi. И, конечно же, робот с Java ME Embedded на борту.

JavaOpen и JavaDay в Самаре

Материалы конференции доступны по ссылке.

Хочется отметить, что это первый JavaDay в Самаре. На местном телеканале даже показали соответствующий сюжет. Интересен тот факт, что Microsoft TechDays проходят уже достаточно давно, но уже не с тем размахом. Будем надеяться, что ИТ-мероприятия такого формата будут регулярным явлением. А Java-движение будет набирать обороты.

Ну и напоследок самое вкусное — задания турнира, любезно предоставленные их создателем — Павлом Васиным. Тексты заданий оставил без изменений. Ниже есть ответы.

Турнир

Задача турнира была выявить не просто кандидатов со знаниями математики и навыками в спортивном программировании, а людей, которые ближе к производству. Поэтому первое задание было академическим: на знание языка Java, знание хороших и особенно плохих практик при промышленной реализации задач, поддержке, объектно-ориентированном программировании и дизайне классов. Второе задание — практическое, на результат, трудоемкое и без всякого академизма. Как сделаешь, так и хорошо. Для него была разработана система подсказок. Тут задача была в том, чтобы люди сами себе поставили задачу и выбрали инструменты ее решения. При этом правильно оценили и распределили свое время, если не могут справиться или не успевают, то брали бы подсказки.

Задание 1

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

Просмотрите код, представленный на распечатке, и в таблице, шаблон которой прилагается, укажите все допущенные в данном коде ошибки, неточности, потенциальные проблемы и т.д. Чем больше вы найдете проблем — тем лучше. Каждая заложенная в код проблема, ошибка имеет определенный «вес» в баллах. Ваша задача — набрать в данном тесте максимальное количество баллов.

Проблемный код

01  public class EmployeeList extends LinkedList implements List {
02    //Часовые ставки зарплат
03    public static final Float _baseHourSalary = new Float("36.60");
04    public static final Float _high_hour_salary = _maxHourSalary / 4;
05    public static final int _maxHourSalary = _high_hour_salary > 50 ? 110 : 55;
06    public Log log = LogFactory.getLog();
07    private float[] koefs;
08  
09    public EmployeeList() {
10      LoadKoefficients();
11    }
12  
13    @Override
14    public boolean add(Object o) {
15      for (Object obj : this) {
16        if (!(obj instanceof Employee)) continue;
17        if (o.equals(obj)) return false; //Тот же работник, нельзя добавить два раза
18        if (((Employee)o).getFio() == "Иванов Афанасий Петрович" 
19                || ((Employee)o).getFio() == "Михайлова Иннеса Петровна") {
20          //Исправление бага 3244, эти люди уже давно не работают
21          return false;
22        }
23      }
24      return add(o);
25    }
26  
27    public void LoadKoefficients() {
28      float[] arr1 = KoefStorage.getKoefArray("ifns_2003_god");
29      log.debug("Коэффициенты ИФНС загружены " + arr1.toString());
30      float[] arr2 = KoefStorage.getKoefArray("ufns_2003_god");
31      koefs = new Float[2000];
32      for (int i = 0; i < arr1.length; i++) koefs[i] = arr1[i];
33      for (int i = 0; i < arr2.length; i++) koefs[i + arr1.length] = arr2[i];
34      recalculateKoeffs(); //Пересчет коэффициентов на текущий месяц
35    }
36  
37    public void recalculateKoeffs() {
38      for (int i = 0; i < koefs.length; i++) 
39          koefs[i] = koefs[i] < 0.88 ? koefs[i] / 4 : koefs[i] / 6;
40    }
41  
42    public ArrayList getSalaries(LinkedList<Employee> employee) {
43      ArrayList result = new ArrayList(5);
44      for (int i = 0; i < employee.size(); i++) {
45        Employee e = employee.get(i);
46        if (!this.contains(e)) {
47          //Если хотя бы одного человека нет. нам нужно вернуть пустой список
48          return new ArrayList(0);
49        }
50        Employee found = (Employee) this.get(this.indexOf(e));
51        result.add(
52            found.getFio() == "Брутасов Николай Павлович" //Наш директор
53                ? _maxHourSalary : _baseHourSalary);
54      }
55      return result;
56    }
57  
58    public LinkedList getSortedView() {
59      DataCollectionsHelper.sortBubble(this, new Comparator() {
60        public int compare(Object o1, Object o2) {
61          if (o1 instanceof Employee && o2 instanceof Employee) {
62            return ((Employee)o1).getTableNumber() - ((Employee)o2).getTableNumber();
63          } else return -1;
64        }
65      });
66  	  return this;
67    }
68  }

Задание 2

В одном из рассказов Конан-Дойла великий сыщик столкнулся с делом, которое стало настоящей проверкой его дедуктивного метода. Ключом к расследованию оказалась разгадка специального шифрованного языка «пляшущих человечков», с помощью которого преступники вели свою переписку. В ходе дела Шерлок Холмс, используя свой метод, смог вычислить, сколько пляшущих человечков входят в одно слово, а также определил тех из них, которые встречались наиболее часто. Разгадав значение первого слова — «С чего начинаются сообщения? Конечно же с приветствия, дорогой Ватсон! Это элементарно!» — сыщик без труда вычислил и всех остальных. После этого он смог сам поучаствовать в их переписке и разоблачить банду.

Мы предлагаем вам повторить его действия, но с помощью современной техники.

У вас имеется:
1) Компьютер, язык Java, IDE
2) Зашифрованный несложным методом отрывок художественного текста на русском языке
3) Роман «Война и мир» Л.Н. Толстого (если у вас останется много времени после расшифровки, чтобы вам было чем себя занять — можете немного почитать)
4) Набор из 3 подсказок (№1, №2, №3), которые открываются по очереди. Вскрытие каждой подсказки уменьшает возможное количество баллов, которое вы можете получить. Всего 50 баллов, вскрытие каждой подсказки уменьшает эту сумму на 10 баллов.

Зашифрованный текст

v+l9ooxrl9 3+afzr2v+ l5wxr12fzfb 3n45wa7l9d 5w3p 3e9p5v+8bv+5w 3qxm6r2qx3p 3xrn4a|ooos 3n45wa7l9d 5w3p 3xrn4a|ooos 3e9p5v+8bv+5w 3qxm6r2qx3p 3xrn4a|ooos 3n45wa7l9d 5w3p 3xrn4a|ooos 3e9p5v+8bv+5w 3qxm6r2qx 3fz 3d mlu|5whc 3fz 3z9xr|c 3e9 3l9fz+ahc 3qhv+e9e9p5v+fhd 35wd fbmlu| 3n4qhxr 3fz5wosa7 3n4v+125wxr12fzfbv+hc 3fz5wosa| 3n4v+125wxr12fzfb 3qhxr yfz5we9a| 312 3oo7|e9a|fbv+ 312xre9u|+aose9xroo 312xre9u|+aos yu|e9a|oo 3ooqhu|ooosu|+a 3|cxr yd 312 3p5xrl9e9oov+l9oofzl9xrn4xr5wu|hc 3u|u9u| 3+av+5wu|l9osp5fz+a 3+av+5wosfbfzp5xr+a 3u||cxr 3n4u|qhu|12u|8b5wfz 312 3n4u|oou|qhz9d qh|c3p 3fz 3ood oo 3xrl9 3xrp5xrl9fbfz5w 3l9u|+au|9+p5d a7 3mlp5xr5wd 3l9v+ 3p5fzqhxrfbl9xr l 3d 5wfz9+u|hc 3n4xrooxr+a 3xrl9 3e95wd fhfz5w 312 3p5v+p5xr+angooxr 3+av+|cv+8bfzl9u|3p 3n4xrooxr+a 3u|u9u| 3fbu||cxrngooxr 3 yu|5wv+5w3p 3v+ 312 3l9v+fbv+5wu| 3qhu|12xr5wa79+fzfz 3m6+afz|cqhfzqhxr12v+5w 38bv+ 3|cqhv+l9fz9+d hc 3l9d 3fz 3z9xr|c 3e9 3l9fz+ahc 3a| 35wd fbmlu| 3qhv+e9e9p5v+fhd 3n4qhxr 3v+l9l9d 3fz|cl9v+ooosu|12l9d hc 3l9xr 3n4qhxr 3v+l9l9d 3fz|cl9v+ooosu|12l9d 3qhv+e9e9p5v+8bv+ooos 3l9u| 3oov+p5ngooxr 3n4qhxre9ooxrhc 312xrngn4u|qh127|r23p 3a| 3xr 3l9u| l 3n4xrfboofz 3l9fzfbu||cxr 3l9u| 38bl9v+a73p 3v+ 312xrng12ooxrqh7|r23p 3a| 3e9u| lfbv+e9 3d n4v+5w 3e9xr 3e9ood 5wv+ 3fz 38bv+z97|5w3p 3xr 3fbu|+a 3e9xrz9fzqhv+5we9a| 3qhv+e9e9p5v+8b7|12v+oooshc 3a| 35wd fbmlu| 3qhv+e9e9p5v+fhd 3xr 3e9u|z9u|hc 3a| 3127|e9xrp5xr|cxr 3qhxre9oov+3p 3l9u||c5wd n47| l3p 3xr yu|12v+a7e9os 3fz8ba|u9l9xr 3fz 3e9xr 312p5d e9xr+a3p 3l9u| 3n4osa73p 3l9v+ 3e9p5v+fbp5fz 3l9u| 3r2xrfhd 3p 3l9xr 3p5 3 yv++av++a 3ooa|l9d e9oshc 3fz 3 yv++a7| 3l9u| 3fz8bz9u||cv+a7oo 3+au|l9a|hc 3 yv+fhu| 35wa7z9a|oo3p 3p5xr|c yv+ 3a| 3e9 3l9fz+afz 3|cd 5wa|a7hc 3e9u|qhv+c+fz+av+ 3fz8b+av+ l5wxr12l9v+ 3l9u|xr yl9xrp5qhv+ool9xr 3n4qhfz|c5wv+mlv+5wv+ 3+au|l9a| 3p5 3e9u|z9u|3p 3fz 38bfzl9v+fz yv+ 3a|p5xr125wu|12l9v+ 3ooxrfhu| 3|cxr12xrqhfz5wv+3p 3fbooxr 3xrl9v+ 312e9u||c yv+ 3qhv+ yv+ 3+au|l9a| 312fz yu|oooshc 3l9xr 312xroo 3e9 3+av+qhfzl9xr l 3n4u|ooqhxr12l9xr l 3e95wd fbv+ l 38bv+z9v+12l97| l 3127|mlu|5w 3d 3+au|l9a|3p 3xr 3p5xrooxrqhxr+a 3a| 3fz 3r2xrfbd 3qhv+e9e9p5v+8bv+oooshc 3e95wd fbv+ l 312n4xr5wl9u| 3xrz97|p5l9xr12u|l9l97| l3p 3l9xr 312e9u| 3fhu| 38bv+z9v+12l97| l3p 3fzz9xr 3+av+qhfzl9v+ 3n4u|ooqhxr12l9v+ 3z95wv+|cxr yv+qha| 3+al9u| 3e9xr12u|qhmlu|l9l9xr 3xrz95w7|e9u|5wv+3p 3p5v+p5 35wv+ yxrl9oshc 3e95wd fbfz5wxre9os 3m6ooxr 3oov+p5+w 3n4qhfzmlu|5w 3a| 3xr yl9v+fh y7| 3p5 3+av+qhfzl9u| 3n4u|ooqhxr12l9u|3p 3v+ 3xrl9v+ 3ooqhv+r2zj 3ng 3fz 3xrz95w7|e9u|5wv+hc 312xroo 3fz 312e9u|hc

Подсказка №1

Зашифрованный текст представляет собой маленький рассказ на русском языке. В нем нет переносов строк, только буквы русского алфавита (в одном регистре), знаки препинания, пробелы. Текст зашифрован методом шифротаблицы: когда каждый символ исходного текста заменяет одним или группой символов из некоторого словаря, при этом количество символов в группе одинаково для каждого кодированного символа исходного текста. У Конан-Дойла таким словарем были человечки, в нашем случае — это буквы английского алфавита, цифры, пробелы и некоторые специальные знаки.
Казалось бы, не зная ключа, по которому проводилась замена, вскрыть данный шифр невозможно… Но проблема в том, что в современных языках (в русском в том числе) разные буквы встречаются с разной частотой, какие-то часто, какие-то редко. Поэтому такие шифры поддаются т.н. «частотному анализу». При достаточно большом объеме текста частота практически однозначно определит закодированную букву. Но так как у нас зашифрован небольшой отрывок, то в нем возможны некие «перекосы» и для букв с близкими частотами останется неопределенность. Ну что тут поделаешь? Опять вспомнил Шерлока — подставлять, пробовать и пытаться разгадать какие-то характерные буквосочетания или слова, закреплять некоторые «разгаданные» буквы и пробовать снова. Каждое разгаданное слово будет сильно приближать вас к разгадке всего текста. И помните, чем удобнее вы сделаете для себя инструмент для такого анализа, тем быстрее вскроете шифр.

Подсказка №2

У вас под рукой нет таблицы частот русских букв? А на что вам Толстой? Большой текст даст вам очень точный подсчет частоты использования букв в русском языке. Только не забудьте текст предварительно обработать, а полученные частоты нормализовать.
Еще очень поможет, если вы определите самый частый, встречающийся в русском тексте символ — пробел и его частоту.
Мы договорились, что в шифротаблице каждый символ исходного текста может быть зашифрован группой символов? Как узнать ее величину? Тут можно посоветовать несколько способов: проанализировать частоты встречаемости групп символов в зашифрованном тексте простым перебором, начиная с 1. Для правильного количества частоты будут «особенными». Можно попробовать найти самую часто-встречающуюся группу символов — это будет пробел и он вам ограничит слова. Ну а по средней длине слова узнать количество букв в шифрогруппе не составит труда (снова спасибо Толстому).

Подсказка №3

Зашифрованный текст начинается со слов «АНТОН МИХАЙЛОВИЧ»
Ответы

Если задания решить не удалось или просто есть желание сверить результаты, то можно воспользоваться ответами:

Ответ на задание 1

Вначале для оценки данного задания была создана специальная таблица, но потом задание немного поменялось и таблица стала не совсем актуальной. Кроме того, ряд моментов зависит от стиля программирования и оформления в той или иной команде. Т.е. доля субъективизма имеет место быть.

Если вкратце:
За простые ошибки, вроде обнаружения зацикливания, объявления static-переменных, сравнивания строк на ==, бесконечных рекурсий и т.д. давался 1 балл.
За скрытие ошибки и производительность, вроде целочисленного деления там, где должно быть деление плавающих, или не использование Arrays.copy давалось 2-3 балла
За сложные тайм-бомбы, ошибки в дизайне класса 5 баллов.

Если развернуто (та самая таблица):

Ошибка в коде Область знаний Баллы
Класс уже extends LinkedList писать implements List необязательно Стиль 1
Константы называются не по соглашению (HIGH_HOUR_SALARY должно быть примерно так все) Стиль 1
Циклическая зависимость при объявлении константы Поверхность 1
Константы типа Float ничем необоснованы, должно быть float Поверхность 1
Конструктор new Float(«36.60») ужасен Поверхность 1
Вычисление _maxHourSalary / 4 даст не ожидаемый результат (из-за целочисленного деления), необходимо явное приведение типа _maxHourSalary к float Скрытая ошибка 3
Название метода LoadKoefficients не по соглашению (loadKoefficients должно быть) Стиль 1
Если наследуем список, то должны быть generics (генерики), без них анахронизм Стиль 2
В конструкторе используется паблик-метод, это опасно в случае наследования Скрытая ошибка 3
Методы LoadKoefficients и recalculateKoeffs бессмысленно делать пабликами, так как они явно нужны только для внутренней логики работы метода. Их публикация нарушает инкапсуляцию ООП 3
Судя по методу add у нас ошибка в дизайне класса – это вообще не список, а множество (осуществляется проверка на повторное вхождение). Дизайн класса 5
Класс ведет себя непонятно как при добавлении НЕ Employee Скрытая ошибка 3
Сравнение строк на равенство (должно быть equals) Поверхность 1
Проверка o.getFio() == осуществляется внутри цикла (ничто не мешает проверить снаружи) Поверхность 1
Порочна сама практика такого исправления «бага 3244», таким образом исправлять баги нельзя никогда Дизайн класса 3
В список есть много способов добавить элемент, но переопределен только add. Значит приведенная в переопределенном методе логика будет срабатывать не всегда, что еще хуже самой ошибочной логики Скрытая ошибка 3
Return add(o) вызывает бесконечную рекурсию. Должно быть super.add(o) Поверхность 1
«ifns_2003_god» – должно быть вынесено в константу Стиль 2
В лог дебаг хотелось передать всю распечатку массива, а не ненужный указатель. Вместо arr1.toString() надо было использовать Arrays.deepToString Логическая ошибка 2
Распечатка всего массива – дело долгое, лучше сначала проверить, включен ли вообще режим дебага Производительность 3
Массив Float[] не дает нам ничего кроме постоянных боксингов/анбоксингов. Должно быть float[] Поверхность 1
Копирование массивов нужно делать с помощью Arrays.copy Производительность 3
Почему массив именно из 2000 элементов? А что если загруженных будет больше или меньше? Логическая ошибка 2
Куча magic numbers в recalculateKoeffs Стиль 2
Слишком жестко зашита логика в классе по обработке данных, эти части логики обычно сильно изменяются, так писать классы нельзя (логика зашита в recalculateKoeffs, .getFio() == ) Дизайн класса 5
Чем обусловлена любовь к LinkedList и наследование именно от него? Какие в данном классе есть к этому предпосылки? Никаких! Дизайн класса 5
Чем вообще обусловлено наследование? Здесь оно совсем не отвечает задаче класса (нужно было использовать композицию, а не наследование) ООП 5
Нет программирование к интерфейсу (очень много ссылок на конкретные реализации ArrayList, LinkedList, которых нужно было избежать) ООП 2
new ArrayList(5) — а почему именно 5? magic number Стиль 2
Проход по списку циклом for i=0 и последующий get непроизводительный (особенно для LinkedList). Надо использовать for each Производительность 3
Возвращение пустого списка ArrayList(0), правильно использовать константу EMPTY_LIST или метод emptyList в Collections (по куче причин) Скрытая ошибка, Производительность 3
Вообще логика возврата пустого списка, если один из элементов входного списка не найден внутри крайне сомнительная и корявая Дизайн класса 3
Недокументированные public-методы. Как вообще догадаться, что эти методы делают? Стиль 2
Это получение элемента из списка ужасно this.get(this.indexOf(e)) Поверхность 1
Почему sortBubble а не Collections.sort? Поверхность 1
Анонимный компаратор создается каждый раз при вызове метода. Можно было бы записать его в поле класса, а еще лучше в статическое поле Производительность 3
Если сравниваемые элементы не Employee, то выдается меньше. Это пример непонятно какого поведения класса (не говоря уж о нарушении контракта компаратора) Логическая ошибка 3
Компаратор в виде разности имеет в себе скрытую ошибку (для слишком больших или маленьких чисел) Скрытая ошибка 3
Возвращение некого внешнего View на ваш список методом сортировки вашего списка крайне корявый дизайн класса (не говоря уж о том, что это нарушает инкапсуляцию) Дизайн класса 4
ИТОГО 95

Ответ на задание 2

АНТОН МИХАЙЛОВИЧ ПЛЮНУЛ, СКАЗАЛ «ЭХ», ОПЯТЬ ПЛЮНУЛ, ОПЯТЬ СКАЗАЛ «ЭХ», ОПЯТЬ ПЛЮНУЛ, ОПЯТЬ СКАЗАЛ «ЭХ» И УШЕЛ. И БОГ С НИМ. РАССКАЖУ ЛУЧШЕ ПРО ИЛЬЮ ПАВЛОВИЧА. ИЛЬЯ ПАВЛОВИЧ РОДИЛСЯ В ТЫСЯЧА ВОСЕМЬСОТ ВОСЕМЬДЕСЯТ ТРЕТЬЕМ ГОДУ В КОНСТАНТИНОПОЛЕ. ЕЩЕ МАЛЕНЬКИМ МАЛЬЧИКОМ ЕГО ПЕРЕВЕЗЛИ В ПЕТЕРБУРГ, И ТУТ ОН ОКОНЧИЛ НЕМЕЦКУЮ ШКОЛУ НА КИРОЧНОЙ УЛИЦЕ. ПОТОМ ОН СЛУЖИЛ В КАКОМ-ТО МАГАЗИНЕ, ПОТОМ ЕЩЕ ЧЕГО-ТО ДЕЛАЛ, А В НАЧАЛЕ РЕВОЛЮЦИИ ЭМИГРИРОВАЛ ЗА ГРАНИЦУ. НУ И БОГ С НИМ. Я ЛУЧШЕ РАССКАЖУ ПРО АННУ ИГНАТЬЕВНУ. НО ПРО АННУ ИГНАТЬЕВНУ РАССКАЗАТЬ НЕ ТАК-ТО ПРОСТО. ВО-ПЕРВЫХ, Я О НЕЙ ПОЧТИ НИЧЕГО НЕ ЗНАЮ, А ВО-ВТОРЫХ, Я СЕЙЧАС УПАЛ СО СТУЛА И ЗАБЫЛ, О ЧЕМ СОБИРАЛСЯ РАССКАЗЫВАТЬ. Я ЛУЧШЕ РАССКАЖУ О СЕБЕ. Я ВЫСОКОГО РОСТА, НЕГЛУПЫЙ, ОДЕВАЮСЬ ИЗЯЩНО И СО ВКУСОМ, НЕ ПЬЮ, НА СКАЧКИ НЕ ХОЖУ, НО К ДАМАМ ТЯНУСЬ. И ДАМЫ НЕ ИЗБЕГАЮТ МЕНЯ. ДАЖЕ ЛЮБЯТ, КОГДА Я С НИМИ ГУЛЯЮ. СЕРАФИМА ИЗМАЙЛОВНА НЕОДНОКРАТНО ПРИГЛАШАЛА МЕНЯ К СЕБЕ, И ЗИНАИДА ЯКОВЛЕВНА ТОЖЕ ГОВОРИЛА, ЧТО ОНА ВСЕГДА РАДА МЕНЯ ВИДЕТЬ. НО ВОТ С МАРИНОЙ ПЕТРОВНОЙ СЛУЧАЙ ЗАБАВНЫЙ ВЫШЕЛ У МЕНЯ, О КОТОРОМ Я И ХОЧУ РАССКАЗАТЬ. СЛУЧАЙ ВПОЛНЕ ОБЫКНОВЕННЫЙ, НО ВСЕ ЖЕ ЗАБАВНЫЙ, ИБО МАРИНА ПЕТРОВНА БЛАГОДАРЯ МНЕ СОВЕРШЕННО ОБЛЫСЕЛА, КАК ЛАДОНЬ. СЛУЧИЛОСЬ ЭТО ТАК: ПРИШЕЛ Я ОДНАЖДЫ К МАРИНЕ ПЕТРОВНЕ, А ОНА ТРАХ! — И ОБЛЫСЕЛА. ВОТ И ВСЕ.

P.S. Судя по всему, если в Самаре и был JUG, то давно не функционирует. Может ли кто-нибудь подсказать так ли это?

Автор: Twelver

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js