unv

Клавиатурные шаблоны и машина Тьюринга

Oct 06, 2008 23:55

С давних времён веду в своей программе на Java перечисления в таком стиле:

public static final int NONE = 0, ACTION_ID = 1, ADAPTER_NAME = 2, ATTR_ACCESS_TYPE = 3;
    public static final int ATTR_GROUP_ID = 4, ATTR_ID = 5, ATTR_ID_LIST = 6, ATTR_SCHEMA_ID = 7;
    public static final int ATTR_TYPE_DEF_ID = 8, ATTR_TYPE_ID = 9, COMPONENT_ID = 10, CONNECTION_TYPE = 11;
    public static final int COST = 12, DATA = 13, DEF_VALUE = 14, DESCRIPTION = 15;
    public static final int FLAGS = 16, GRANTS = 17, HEIGHT = 18, ID = 19;
    public static final int KIND = 20, LISTENER_ID = 21, LIST_VALUE_ID = 22, MASK = 23;
    public static final int NAME = 24, OBJECT_ID = 25, OBJECT_TYPE_ID = 26, OPTIONS = 27;
    ...

Ну и так далее. Поскольку в Java до версии 1.5 не было явных перечислений, их приходится эмулировать int'овыми константами.
И я предпочитаю данные константы записывать по четыре на строчку, причём со сквозной сортировкой по имени (уверен, пуристы оценят :).

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


Совет перейти на Java 1.5+ с её перечислениями (перенумерация не требуется) отвергнем сразу - требуется обратная совместимость.

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

Если не хочется делать лишнюю работу руками - думаем головой. Первое, что приходит в голову - разбить при помощи FAR'овского клавиатурного шаблона (keyboard template) каждую строчку на 4, скопировать полученное в Excel, создать там арифметическую прогрессию, скопировать полученное обратно и при помощи ещё одного клавиатурного шаблона слить всё воедино. Многовато шагов получается, да и Эксель придётся запускать - решение для не очень ленивых.

Всё-таки хочется решить задачу полностью при помощи клавиатурных шаблонов. Но как? Если первую операцию (сделать так, чтобы после вставки нового значения на каждой строчке по-прежнему было по 4 константы) реализовать несложно - выделить в конце строчки хвост начиная с запятой и перенести его на следующую строчку - то как организовать перенумерацию? Ведь клавиатурный шаблон - это просто запись последовательного нажатия клавиш на клавиатуре, в нём нет переменных, нет памяти.

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

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

Итак, мы вставили в список значение DATE:

public static final int COST = 12, DATA = 13, DATE = XX, DEF_VALUE = 14, DESCRIPTION = 15;
    public static final int FLAGS = 16, GRANTS = 17, HEIGHT = 18, ID = 19;
    public static final int KIND = 20, LISTENER_ID = 21, LIST_VALUE_ID = 22, MASK = 23;
    public static final int NAME = 24, OBJECT_ID = 25, OBJECT_TYPE_ID = 26, OPTIONS = 27;
    ...

Приводим его к четырёхконстантной форме при помощи клавиатурных шаблонов:

...
    public static final int COST = 12, DATA = 13, DATE = XX, DEF_VALUE = 14;
    public static final int DESCRIPTION = 15, FLAGS = 16, GRANTS = 17, HEIGHT = 18;
    public static final int ID = 19, KIND = 20, LISTENER_ID = 21, LIST_VALUE_ID = 22;
    public static final int MASK = 23, NAME = 24, OBJECT_ID = 25, OBJECT_TYPE_ID = 26;
    public static final int OPTIONS = 27, ...

Можно посмотреть на видео, как это делается:

image Click to view



Наша вновь вставленная константа имеет фиктивное значение XX - впоследствие мы заменим его на более подобающее 14.
Мысль следующая: начнём перенумерацию с единиц (к счастью, мы вставили значение в область двузначных чисел - с ними и будем работать), а потом перейдём к десяткам. Единицы должны циклически проходить значения от 0 до 9 (при переходе через 0 десятки увеличиваются на 1, но про это пока забываем).

Формируем циклическую последовательность для единиц, начиная с цифры, которую хотим присвоить первой константе:

...
2345678901
    public static final int COST = 12, DATA = 13, DATE = XX, DEF_VALUE = 14;
    public static final int DESCRIPTION = 15, FLAGS = 16, GRANTS = 17, HEIGHT = 18;
    public static final int ID = 19, KIND = 20, LISTENER_ID = 21, LIST_VALUE_ID = 22;
    public static final int MASK = 23, NAME = 24, OBJECT_ID = 25, OBJECT_TYPE_ID = 26;
    public static final int OPTIONS = 27, ...

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

...
    public static final int COST = 12, DATA = 13, DATE = X4, DEF_VALUE = 15;
6789012345
    public static final int DESCRIPTION = 15, FLAGS = 16, GRANTS = 17, HEIGHT = 18;
    public static final int ID = 19, KIND = 20, LISTENER_ID = 21, LIST_VALUE_ID = 22;
    public static final int MASK = 23, NAME = 24, OBJECT_ID = 25, OBJECT_TYPE_ID = 26;
    public static final int OPTIONS = 27, ...

Назначаем шаблон на желаемую клавишу - и проходимся по всем строкам - с единицами задача решена.
Видео:

image Click to view



Теперь надо подумать, что делать с десятками (заметьте - теперь у нас после 19 следует 10, а не положенное 20). Для последовательно идущих чисел цифра десятков меняется каждые 10 чисел - немного модифицируем нашу "память", повторив цифру десятков по десять раз:

...
1111111122222222223333333333
    public static final int COST = 12, DATA = 13, DATE = X4, DEF_VALUE = 15;
    public static final int DESCRIPTION = 16, FLAGS = 17, GRANTS = 18, HEIGHT = 19;
    public static final int ID = 10, KIND = 21, LISTENER_ID = 22, LIST_VALUE_ID = 23;
    public static final int MASK = 24, NAME = 25, OBJECT_ID = 26, OBJECT_TYPE_ID = 27;
    public static final int OPTIONS = 28, ...

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

...
    public static final int COST = 12, DATA = 13, DATE = 14, DEF_VALUE = 15;
1111222222222233333333331111
    public static final int DESCRIPTION = 16, FLAGS = 17, GRANTS = 18, HEIGHT = 19;
    public static final int ID = 10, KIND = 21, LISTENER_ID = 22, LIST_VALUE_ID = 23;
    public static final int MASK = 24, NAME = 25, OBJECT_ID = 26, OBJECT_TYPE_ID = 27;
    public static final int OPTIONS = 28, ...

Повторяем для оставшихся строчек - и вуаля. На самом деле, всё делается достаточно весьма быстро - за пару минут.
Видео:

image Click to view



машина тьюринга, эзотерическое программирование, far, java

Previous post Next post
Up