Симметрия на часах
На рекламных фотографиях часовая и минутная стрелки часов обычно устанавливаются на отметках 10 и 2 часа, таким образом, чтобы они были симметричны по отношению к вертикальной оси.
Реальные часы имеют некоторую дискретность. Например, у конкретной модели часовая стрелка может перемещаться только после окончания очередной минуты. А то и 12 минут.
Будем считать наши часы более совершенными: часовая стрелка перемещается всегда пропорционально минутной, а минутная, в свою очередь, пропорционально секундной. Соответственно, говорить о полной симметрии вряд ли уместно, углы могут незначительно отличаться.
Требуется найти все положения часовой и минутной стрелок, соответственно, с точностью до секунды, когда достигается симметрия и выбрать из них максимально симметричное относительно оси "12-6" часов.
Решений может быть представлено два:
- Простой перебор вариантов. В дальнейшем будет использоваться как "скоростемер" (бенчмарк)
- В аналитическом виде
Для участия в конкурсе нужно предложить программы для ПМК, описание и результаты расчетов. Никаких ограничения по моделям нет. Язык программирования должен быть основным входным языком для данного устройства. Допускаются также программы для эмуляторов ПМК.
Критерии оценки решения:
- Срок публикации (при наличии сокращенной опубликованной ранее программы приоритет получает автор оригинальной версии)
- Полнота решения (один или два варианта)
- Компактность (число шагов/байтов программы)
- Скорость расчета (программы для эмуляторов по этому критерию не оцениваются, необходим прогон на реальном железе)
Пример решения
Для начала мы попробуем предложить более формальную постановку задачи и наиболее простое в алгоритмическом плане решение на МК-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.Fх≥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.Fх<0 66.68 67.С/П 68.КИП2 69.ИП2
70.Fх<0 71.14 72.КИП1 73.ИП1 74.Fх<0 75.11 76.КИП0 77.ИП0 78.Fх<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 |
Что дальше?
Имеются пути оптимизации переборного алгоритма. Например, можно ограничиться перебором положений часовой стрелки, вычислять симметричное положение минутной и искать положение реальной стрелки в окрестностях этого угла. Думаю, такой алгоритм работал бы на порядки быстрее.
Решение, полученное в аналитическом виде (система уравнений и программа поиска корней) потенциально может оказаться наиболее быстрым.
blog comments powered by Disqus