Симметрия на часах

| рубрика «Конкурсы» | автор st
Метки:

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

Реальные часы имеют некоторую дискретность. Например, у конкретной модели часовая стрелка может перемещаться только после окончания очередной минуты. А то и 12 минут.

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

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

Решений может быть представлено два:

  1. Простой перебор вариантов. В дальнейшем будет использоваться как "скоростемер" (бенчмарк)
  2. В аналитическом виде

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

Критерии оценки решения:

  1. Срок публикации (при наличии сокращенной опубликованной ранее программы приоритет получает автор оригинальной версии)
  2. Полнота решения (один или два варианта)
  3. Компактность (число шагов/байтов программы)
  4. Скорость расчета (программы для эмуляторов по этому критерию не оцениваются, необходим прогон на реальном железе)

Пример решения

Для начала мы попробуем предложить более формальную постановку задачи и наиболее простое в алгоритмическом плане решение на МК-61/52/152.

Нетрудно заметить, что за часовая стрелка поворачивается на 30° за 1 час, а минутная и секундная - на 6° за минуту и секунду, соответственно. Если задавать время в виде тройки чисел (h, m, s), где h - часы в диапазоне [0..11], m - минуты [0..59], s - секунды [0..59], тогда углы стрелок можно вычислить следующим образом:

a = 6s
b = 6m + 0,1s
c = 30h + 0,5(m + s/60)

где a, b и c - углы поворота, соответственно, секундной, минутной и часовой стрелок [0..360) относительно оси на 12 часов.

Симметрию можно определить по-разному.

Используя тригонометрию, необходимо найти значения cos b и cos c, отличающиеся на заданную погрешность. При этом sin b и sin с должны иметь разные знаки. Получаем систему уравнений:

|cos b - cos c| <= µ1
sign(sin b) = -sign(sin c)

где µ1 - абсолютная погрешность вычисления, sign() - функция определения знака действительного числа, дающая на выходе -1, 0 или 1.

Арифметическая проверка чуть более длинная:

|360 - max(b,c)| - min(b,c) <= µ2
max(b,c) > 180
min(b,c) < 180

где µ2 - абсолютная погрешность вычисления

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

Программа для МК-61/52/152 будет выглядеть следующим образом:

00.Сх   01.1    02.8    03.0    04.П5   05.1    06.1    07.ПО   08.5    09.9
10.П1   11.5    12.9    13.П2   14.ИП2  15.6    16.0    17.:    18.ИП1  19.+
20.2    21.:    22.3    23.0    24.ИП0  25.х    26.+    27.ПС   28.ИП2  29.1
30.0    31.:    32.ИП1  33.6    34.х    35.+    36.ПВ   37.ИПС  38.Кmax 39.ИП5
40.-    41.0 42.68   43.ИП5  44.-    45.К|к| 46.ипс  47./-/  48.ИПВ  49./-/
50.Кmax 51./-/  52.XY   53.FO   54.B^   55.ИП5  56.-    57.Fx<0 58.68   59.FO
60.-    61.П4   62.К|к| 63.ип3  64.-    65.<0 66.68   67.С/П  68.КИП2 69.ИП2
70.<0 71.14   72.КИП1 73.ИП1  74.<0 75.11   76.КИП0 77.ИП0  78.<0 79.08
80.С/П

В регистр П3 заносим µ2. Опытным путем выбрано значение 0,055. Меньшие значения пропускают часть решений, бОльшие дают группы аналогичных результатов с разными погрешностями.

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

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

# Час (П0) Мин (П1) Сек (П2) Угол час,° (ПС) Угол мин,° (ПВ) Разница,° (П3)
1 11 4 37 332,30833 27,7 -0,00833
2 10 9 14 304,61666 55,4 -0,01666
3 9 13 51 276,925 83,1 -0,025
4 8 18 28 249,23333 110,8 -0,03333
5 7 23 5 221,54166 138,5 -0,04166
6 6 27 42 193,85 166,2 -0,05
7 5 32 18 166,15 193,8 0,05
8 4 36 55 138,45833 221,5 0,04167
9 3 41 32 110,76666 249,2 0,03334
10 2 46 9 83,075 276,9 0,025
11 1 50 46 55,383333 304,6 0,016667
12 0 55 23 27,691666 332,3 0,008334

Что дальше?

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

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