# Angle between the hands on a clock

Given the time in 24 hour format (`2359` = `11:59pm`) return the angle between the minute and hour hands on a standard clock (on the face plane, so don't just output 0).

Angles are to be returned in the unit of your choice, should be the smallest possible, and should be a positive number (negative angle converted to a positive value), i.e. you will never have an answer greater than 180 degrees or pi radians.

Some examples to check against (in degrees)

• `0000` = `0.0`
• `0010` = `55.0`
• `0020` = `110.0`
• `0030` = `165.0`
• `0040` = `140.0`
• `0050` = `85.0`
• `0150` = `115.0`
• `0240` = `160.0`
• `0725` = `72.5`
• `1020` = `170.0`
• `1350` = `115.0`
• `1725` = `12.5`

Note: There are a few that have rounding errors, I'm not sure how that should be handled; if we should force consistency across all values.

-
The clockwise angle, or the smallest of the two? – SimpleCoder Jan 27 '11 at 22:18
@SimpleCoder: Smallest, as the question says. – Chris Jester-Young Jan 27 '11 at 22:21
`00:10` will be `0010` or `010`? – Nakilon Jan 28 '11 at 0:04
You should include some correct input/output examples including "difficult" input like `0001`, `0633`, etc... I notice that many answers actually produce incorrect results. – MtnViewMark Jan 28 '11 at 6:21
@Nakilon: Can't speak for anyone else, but in my case {1} I missed the tagging (need to establish new habits for this place), {2} golfing is why I came here, and {3} it's kind of simple for anything else, isn't it? – dmckee Jan 28 '11 at 18:44

``````q[h,i,m,n]=abs\$((600*h+60*i-110*m-11*n-312)`mod`720)-360
``````

Note: My "unit of choice" is the "half-degree", of which there are 720 to the circle. With these units, the answer to the problem is always integral! :-)

Ex.:

``````> map c \$ words "0000 0001 0010 0630 0633 2325 2345 2355 2359"
[0,11,110,30,3,335,165,55,11]
> map c \$ words "0930 1845 0315 1742 2359"
[210,135,15,162,11]
``````
-
 Half-a-degree's. Nice. – dmckee♦ Jan 28 '11 at 16:16

# Golfscript

``````2/~~\~60*+55*3600%.3600\-]{}\$~;.10/'.'@10%
``````

42 characters of code, to anyone whom that fact may concern. Outputs whole-a-degrees in float format.

-
 +1 Great program! You can save a char by assigning `3600` to a variable and reusing that. – w0lf Aug 27 '12 at 7:11

I'll make just an analyze:

1. Assuming that we've already splited incoming string into two 2-chars substring, and converted them into Integers, let them be `H` and `M`.
2. Lets measure angles in units equal to `[ 0 .. 12*60 ]` as they are the smallest we need.
Minute hand will be at `[ MA = (12 * 60) / 60 * M = 12 M ]`.
Hour hand will be at `[ H %= 12; HA = (12 * 60) / 12 * H + M = 60 H + M ]`
3. `[ MA - HA ]` will give values `[ -12*60 .. +12*60 ]`, so acording to task we need to convert them into `[ 0 .. 6*60 ]` according to this graphic.

Here we have a place for fantasy while inventing the best (the shortest) function.
For example: `[ f(x) = 180-abs(abs(x)-180) ]`

So there were three possible bugs:

1. Forgetting division hours by modulo 12, because 24 hours take two loops around clocks.
2. Forgetting, that minute hand rotates hour hand also.
3. Wrong converting-to-valid-angle function.
-
 Your logic doesn't work if the hour hand is less than 90 and the minute hand is greater 270. – Mike Bethany Jan 28 '11 at 20:39 @Mike Bethany, I don't see nothing unworking. This case will be at 4th part of graphic, where `[ MA - HA ] = [ 180 .. 360 degrees ]`. – Nakilon Jan 28 '11 at 20:45 I thought you were saying `f(x) = 360-abs(abs(x)-360)` was the solution formula for correcting the angle. – Mike Bethany Jan 28 '11 at 22:42 @Mike Bethany, oh I understood my mistake. It just belongs to Wrong converting-to-valid-angle function. ..) Fixed. – Nakilon Jan 28 '11 at 22:57

## Python

``````def hand_angle(h,m)
d=((m+h*60)*5.5)%360
return min(d, 360-d)
``````
-

## Perl, 58 characters

Perl is fun

`perl -nlE "/(..)(..)/;\$r=abs\$1%12*30-5.5*\$2;say+(\$r,360-\$r)[\$r>180]"`

-

Perl, 61 characters:

``````sub f{\$a=abs(int(\$_[0]/200)-(\$_[0]%60)/5);(\$a>6?12-\$a:\$a)*30}
``````
-
 Your answer is wrong: 1. It generates wrong results for 1059, 1058, etc. 2. 0020 should be 110 degrees, 0030 should be 165, 0040 should be 140, and 0050 should be 85. (The hour hand moves 30 degree every hour---thus, it moves half a degree every minute.) – Chris Jester-Young♦ Jan 27 '11 at 22:46

Non-golf solution:

``````def angle_24hr(time_str):
hour, minute = int(time_str[0:1]) % 12, int(time_str[2:3]) % 60
angle_dist = lambda a, b: ((a + (180 - b)) % 360) - 180
return angle_dist(((hour * 30) + (minute * 0.5)), minute * 6) * 10
``````

In a more obscure/obfuscated form (admittedly, one of my first code golfs):

``````ad=lambda a,b:((a-b+180)%360)-180;x=int;ag=lambda t:10*ad((x(t[0:1])%12)*60+x(t[2:3]),(x(t[2:3]*12)%60)*6)
``````

(what's the point of obfuscating Python?)

If it's necessary for the angles to be purely positive you can remove the -180 term.

-
Your answer is wrong: 0020 should be 110 degrees, 0030 should be 165, 0040 should be 140, and 0050 should be 85. (The hour hand moves 30 degree every hour---thus, it moves half a degree every minute.) – Chris Jester-Young Jan 27 '11 at 22:42
@Chris, why 110 degrees for 0020? Am I missing something: hour hand is at 0, minute hand is at 20*6 = 120...? – Thomas O Jan 27 '11 at 22:44
The hour hand is not at 0 when the minute hand is at 20. It's at one-third between 12 and 1. – Chris Jester-Young Jan 27 '11 at 22:47
@Chris Of course, now it seems obvious to me. Back in a sec with fixed code. – Thomas O Jan 27 '11 at 22:48
Depends on your clock. My clock only moves the hour hand on full hours. Since it wasn't specified in the question it wouldn't make much sense to do it the hard way would it? OK... I'll just admit it... I screwed up to... doh! – Mike Bethany Jan 28 '11 at 11:58

91 chars:

``````#!perl -n
(\$h,\$m)=/(..)(..)/;\$h=\$h%12+\$m/60;\$h=abs(\$h*30-\$m*6);printf'%f
',\$h>180?360-\$h:\$h
``````
-

Python, 82 characters:

``````def a(t):
o=abs(30*(int(t[:1])%12)-5.5*int(t[2:]));return o if o<=180 else 360-o
``````

With some help from the python golfing question I've brought it down to 76:

``````def a(t):
o=abs(30*(int(t[:1])%12)-5.5*int(t[2:]));return [o,360-o][o>180]
``````
-
 no need for a space itn `return [`. You should convert to a lambda function anyhow if you can (for golfing) – gnibbler♦ Jan 28 '11 at 1:24

## c99 -- 204 necessary characters (keeps getting worse as I fix bugs)

``````#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(){char b[5]={0};fgets(b,5,stdin);int a,h,m=atoi(b+2);b[2]=0;
h=(atoi(b)*60+m)%720;m*=12;a=abs((h-m)%720);a=a>360?720-a:a;printf("%i\n",a);}
``````

Discussion:

The problem turns out to be harder than it looks. The critical issue is what is meant by "smallest positive angle". I've interpreted that the mean a value between [0,180] degrees inclusive (because the problem does not specify which hand to start from when measuring).

To validate this behavior look for places when the hands pass the straight-apart position (such as around 00:33-00:35), and places where they cross-over as around 06:33.

I've also chosen to have a steadily sweeping hour hand, as most modern clocks seem to use that method.

I've suffered the usual problem with c: the preprocessor commands to get the libraries eat up a lot of characters.

``````#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(){
char b[5]={0};
fgets(b,5,stdin); /* assumes single byte charaters */
/*   printf("'%s'\n",b); */
int a,h,m=atoi(b+2); /* minutes */
b[2]=0;
h=(atoi(b)*60+m)%720;  /* hour had position in hald-degrees */
m*=12;                 /* minute hand position in half degrees */
/*   printf("%3i\t%3i\n",h,m); */
/*   printf("%i\n", h-m ); */
/*   printf("%i\n",(h-m)%720 ); */
a=abs((h-m)%720);
/*   printf("%i\n",   a ); */
a=a>360?720-a:a;
printf("%i\n",a);
}
``````

Validation:

``````\$gcc -c99 golf_clock_angle.c
\$wc golf_clock_angle.c
5  11 206 golf_clock_angle.c
\$!for
for t in \$(cat clock_test_times.txt); do echo \$t \$(echo \$t|./a.out); done
0000 0
0001 11
0002 22
0010 110
0015 165
0030 330
0033 357
0034 346
0035 335
0045 225
0630 30
0633 3
0634 14
2324 324
2325 335
2355 55
2359 11
``````
-
 Your answers are way off. For instance at `0010` the minute hand will be at 60 degrees and the hour hand will be at 5 degrees. There are 55 degrees between them. In fact a lot of your angles look doubled. – Mike Bethany Jan 29 '11 at 2:29 @Mike: Note the units. I've adopted MntViewMark's convention of expressing answers in half-degrees. – dmckee♦ Jan 29 '11 at 3:20 Ah, seems like cheating to me... let me see if I can abuse it too. ;) – Mike Bethany Jan 29 '11 at 3:55 Says "Angles are to be returned in the unit of your choice"... ;-) – MtnViewMark Feb 15 '11 at 19:29 @MntViewMark: Yep. But I'll bet Dan was thinking "degrees or radians" when he wrote that. – dmckee♦ Feb 15 '11 at 19:51

## Ruby 1.9.2p136 : 78 74

``````def a(t)m=t[2,2].to_f
180-((m*6-(m/60+t[0,2].to_f%12)*30).abs-180).abs
end
``````

Sample output:

``````["0000", "0010", "0020", "0030", "0040",
"0050", "0150", "0240", "0725", "1020",
"1350", "1725"].each do |time|
puts "#{time} = #{a(time)}"
end
# Output
0000 = 0.0
0010 = 55.0
0020 = 110.0
0030 = 165.0
0040 = 140.0
0050 = 85.0
0150 = 115.0
0240 = 160.0
0725 = 72.5
1020 = 170.0
1350 = 115.0
1725 = 12.5
``````
-
You output has the hour hand fixed on the hour marks rather than sweeping during the hour. Most answers have been assuming a uniform sweep for the hour hand. – dmckee Jan 28 '11 at 16:32
Yep, and it also doesn't work if the hour hand is at say 1 and the minute hand is at 11. I fell asleep before fixing it... – Mike Bethany Jan 28 '11 at 20:01
Fixed and updated. – Mike Bethany Jan 29 '11 at 2:10

# Mathematica

``````Grid@Prepend[
Table[{Row[{Quotient[x, 60] /. {0 -> 12}, ":", If[Mod[x, 60] < 10, "0", ""], Mod[x, 60]}],
x, N[x/2, 3], Mod[6 x, 360],
IntegerPart[Min[Abs[x/2 - Mod[6 x, 360]], 360 - Abs[x/2 - Mod[6 x, 360]]]]},
{x, 0, 12*60}], {"time", "elapsed min", "hourhand deg", "min deg", "diff deg"}]
``````

Partial output in table

Graphs

``````Plot[{ x/2, Mod[6 x, 360], Min[Abs[x/2 - Mod[6 x, 360]], 360 - Abs[x/2 - Mod[6 x, 360]]]}, {x, 0, 12*60},PlotStyle -> {Green, Blue, {Thick, Red}},AxesLabel -> {"time (hs)", "degrees"},GridLinesStyle -> Directive[Dotted, Gray],Ticks -> {Table[{60 k, k}, {k, 0, 12}], Table[30 k, {k, 0, 12}]},GridLines -> {Table[60 k, {k, 0, 12}], None}]
``````

The green line shows the angle of the hour hand, as measured in degrees from 12 o'clock, clockwise. The blue line shows the corresponding angle for the minute hand. The red curve shows the difference between the minute and hour hands in degrees; it always uses the interior angle.

-