Симметрия на часах (конкурс)

На рекламных фотографиях часовая и минутная стрелки часов обычно устанавливаются на отметках 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.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

Что дальше?

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

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

File attachments: 
Прикрепленный файлРазмер
Binary Data Файл программы для эмулятора (ClockSymmetry2.C3)4.58 KB

Комментарии

Идеально симметричное - это когда обе стрелки на 12 часах. Над остальным нужно будет подумать...

Пусть так. Один из вариантов, возможно самый точный. Всего вариантов симметрии, как я понимаю, будет 13. Т.е задача не меняется.

Ужасы прошивки 1.02. М-да, видимо, пока я сделаю эту программу, остальные уже успеют сто программ гораздо лучше написАть, потому что у меня ничего не выходит из-за свежеобнаруженных ужасающих глюков с K{x}: попробуйте 60 В| 12 % K{x}... у меня получается единица!!!
ЗЫ. Главному инженеру СЕМИКО я об этой проблеме только что отписала.
ЗЫЫ. Всей душой надеюсь, что в 1.03 сей баг исправлен...

ЗЫЫЫ. Ну почему именно я всегда страдаю от глюков K[x] и К{x}, а остальные как-то умудряются писАть свои программы и не натыкаться на эти ужасы :)))))

Патамушта мужчины сложностей не боятся! Разбери повнимательнее мои программы «Hex-1» и «Hex-2», особенно последние шаги. Увидишь, как я всё это преодолевал. Не пищща! :-)

Причём это конкурсные задания. То есть ты с ними конкурировала, по длине программы. Кстати, конкретно этот пример прошивка 1.03 не исправляет. Так что пиши в Новосибирск, пусть работают!

А как с прогоном на железе? Интересно время цикла получения очередного положения стрелок.

Ещё нет МК-152? Проблем нет. До сих пор не пришла МК-152? Удивительно.

С прогоном нет проблем. Но, как всегда, должно быть чётко указано. Что вбивать (можно даже выкладывать mkp-файл), какие числа в какие регистры загрузить, какие кнопки нажимать для запуска, из каких регистров какие результаты считывать, сколько раз и как перезапускать и т.д.

В-общем, полноценная инструкция для оператора.

И не скоро. И еще не скоро приедет. Я до летнего отпуска вряд ли закажу.

Заменить на
B^. Заменить на
B^ K[x] -
?

А как с прогоном предложенного варианта на МК-152? Какое время счета по циклу получения очередного значения?

Простенький вариант. НаписАла покамест простенькую программу - для часов с большей дискретностью: часовая стрелка перемещается раз в 12 минут, минутная - раз в минуту. Получилось 10(11) положений, вместо 12(13) у предложенных, менее дискретных часов.
Решение перебором.

Список найденных значений:

00 ч. 56 м.
01 ч. 51 м.
02 ч. 47 м.
04 ч. 37 м.
05 ч. 33 м.
06 ч. 28 м.
08 ч. 19 м.
09 ч. 14 м.
10 ч. 10 м.
11 ч. 05 м.

Указания к программе:

После выполнения программы (с нулевого адреса) в регистрах памяти 10-20 оказываются числа, которые представляют собой номер деления, на котором находится часовая стрелка (5 делений в 1 часе - 60 делений в 12 часах). Из этих номеров легко можно вычислить время в формате часы - минуты, зная, что минутная стрелка также дискретно перемещается по тем же 60ти делениям и должна быть симметрична часовой.

Текст программы (можно скопировать в компилятор МК-152 и переслать на МК-152 как файл программы):

0000 	00h 	0                	;
0001 	41h 	M 1              	;A
0002 	42h 	M 2              	;B
0003 	09h 	9                	; 
0004 	45h 	M 5              	;E
0005 	51h 	GOTO 10          	;Q
0006 	10h 	                	; 
0007 	FFh 	.DB 0FFh         	; 
0008 	FFh 	.DB 0FFh         	; 
0009 	50h 	R/S              	;P
0010 	61h 	RM 1             	;a
0011 	01h 	1                	; 
0012 	10h 	+                	; 
0013 	41h 	M 1              	;A
0014 	06h 	6                	; 
0015 	00h 	0                	;
0016 	11h 	-                	; 
0017 	5Eh 	F x=0 21         	;^
0018 	21h 	                	;!
0019 	00h 	0                	;
0020 	41h 	M 1              	;A
0021 	61h 	RM 1             	;a
0022 	01h 	1                	; 
0023 	02h 	2                	; 
0024 	13h 	/                	; 
0025 	44h 	M 4              	;D
0026 	64h 	RM 4             	;d
0027 	35h 	K FRAC           	;5
0028 	5Eh 	F x=0 39         	;^
0029 	39h 	                	;9
0030 	62h 	RM 2             	;b
0031 	01h 	1                	; 
0032 	10h 	+                	; 
0033 	42h 	M 2              	;B
0034 	06h 	6                	; 
0035 	00h 	0                	;
0036 	11h 	-                	; 
0037 	57h 	F X!=0 09        	;W
0038 	09h 	                	; 
0039 	06h 	6                	; 
0040 	00h 	0                	;
0041 	0Eh 	ENT              	; 
0042 	61h 	RM 1             	;a
0043 	11h 	-                	; 
0044 	62h 	RM 2             	;b
0045 	11h 	-                	; 
0046 	5Eh 	F x=0 10         	;^
0047 	10h 	                	; 
0048 	62h 	RM 2             	;b
0049 	B5h 	K M 5            	; 
0050 	51h 	GOTO 10          	;Q
0051 	10h 	                	; 

Вопросы 1. Как со временем счета? А если апроксимировать на цикл расчета с дискретностью до секунды?
2. Можно ли выложить текст в виде HTML (хотя это некритично, т.к. тогда надо файл прилагать)?
У меня вот что получилось

  0 1 2 3 4 5 6 7 8 9
00 ИП D F x<0 09 B↑ ИП 8 ÷ ПП 90 ИП A
10 F x≠0 43 F x<0 33 2 × B↑ ИП 4 ИП 3 -
20 × ИП B F x2 + F √ ИП B - ÷ B↑ ИП 8
30 × БП 90 ИП D F x≠0 86 ИП 3 F x2 F √ ИП 7
40 - F x<0 87 ИП B ИП A С/П П 1 П 2 F x≠0 43
50 ÷ П 8 ИП 5 ИП D + ÷ ИП 6 × П 3 ИП 4
60 - ИП 2 × ИП B + П B F Bx + 2 ÷
70 ИП 2 × ИП A + П A ИП C ИП 2 ИП 0 × -
80 П C ИП D ИП 1 - П D В/О ИП 6 ИП 9 С/П Cx
90 П 1 П 2 F x<0 50 ИП 3 БП 59 FFh FFh

Контрольная сумма ADD 6895

Контрольная сумма XOR 31

1. Время счёта - примерно 1 мин.10 сек.
2. С радостью бы приложила файл, но к комментам он не подгружается, а на основную страницу загрузить стесняюсь :))) - она всё же посвящена вашей версии программы.

Общее? Это общее время нахождения всех вариантов или только одного?
Страничка посвящена задаче, мой вариант только для затравки, потом сведу все итоги. Но файл можно выкладывать и у себя в блоге с комментариями, а здесь давать ссылку.

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

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

Ждем. Алгоритм поиска в окрестностях может дать ускорение на порядок если не больше.

Гамма - 40 шагов. Готова гамма-версия программы. Алгоритм поиска: перебор 43200 (=12*60*60) возможных положений часовой стрелки и проверка, существует ли симметричное положение минутной. Время выполнения сократилось наполовину, но это, возможно, из-за того, что я убрала графику и упростила уравнение расчёта симметричности.

Описание? Уравнения, хронометраж?

Уравнения можно посмотреть теперь в моём блоге. А что такое суть хронометраж?

Хронометраж. Сколько времени уходит на полный расчет и на 1 цикл (можно в среднем).

Полный расчёт = 34 мин.
Один цикл = 34 мин./43200(число циклов) = 34*60 сек./43200 = 0,047(2) сек.

Найденные значения при П0=0,5 теперь выложила в блоге на соотв. странице.

Программа поиска таких значений для калькулятора Assistant AC-3600:
0→H:Lbl 1:(12-H)×60⌟13→T:Int T→M:Int ((T-M)×60)→S:H◢M◢S◢H+1→H:H<12⇒Goto 1

Аналитическое решение задачки можно получить из линейного уравнения с параметром: 30*(12-N)-X/2=6*X, где N - часы от 0 до 11, а X - минуты. Левая часть 30*(12-N)-X/2 - угол в градусах между часовой стрелкой и 12 часами, а правая часть 6*X - угол в градусах между минутной стрелкой и 12 часами.

Решением уравнения является (формула): X=(720-60*N)/13.

Например, если N=10 (часовая стрелка располагается после 10 часов [между 10 и 11]), то X=120/13=9+3/13 минут (точный ответ) или 9 минут 14 секунд (приближённый ответ).

Следующая программка для HP 50g находит все решения задачки (за исключением совпадения стрелок на 12-часовой отметке):

<<
0
11
FOR
N
N
720
60
N
*
-
13
/
60
*
0
RND
60 
IDIV2
3 
->LIST
NEXT
>>

Ответы:

//{ ЧАСЫ МИНУТЫ СЕКУНДЫ }

{ 0 55 23 }

{ 1 50 46 }

{ 2 46 9 }

{ 3 41 32 }

{ 4 36 55 }

{ 5 32 18 }

{ 6 27 42 }

{ 7 23 5 }

{ 8 18 28 }

{ 9 13 51 }

{ 10 9 14 }

{ 11 4 37 }

Время счёта меньше 2 секунд.

P.S. Простите за нахальство, но приведённое в записи решение с синусами и косинусами не аналитическое, а численное.

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

.

Нет проблем, это вам спасибо за уточнения и участие в решении.