g | x | w | all
Bytes Lang Time Link
091Perl110127T223830ZC. K. Yo
060SmileBASIC170201T165414Z12Me21
025Dyalog APL160114T225518ZAdá
02305AB1E180802T134224ZKevin Cr
106Python110127T222620ZThomas O
082Python110128T002313ZChampo
087C# .NET Core171130T005328ZAyb4btu
050ES6160113T212831ZNeil
022TIBASIC160115T021610Zlirtosia
056Matlab/Octave160114T200058Zflawr
078C99160111T165746ZToby Spe
075JavaScript ES6160113T073914ZMwr247
080PHP160111T115239Zthisispa
156C++160111T023601Zjac4e
058Perl110407T171914Zchinese
042Golfscript110228T213712Zaaaaaaaa
nan120826T042249ZDavidC
074Ruby 1.9.2p136110128T052946ZMike Bet
204c99 204 necessary characters keeps getting worse as I fix bugs110127T230331Zdmckee -
078Haskell110128T062018ZMtnViewM

Perl, 91 chars

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

SmileBASIC, 60 bytes

INPUT T
A=ABS(T DIV 100*60-T MOD 100*11)?A/2+(360-A)*(A>360)

Dyalog APL, 34 32 27 25 characters

Full program. Prompts for 4-character string from stdin. Prints radians to stdout.

¯2○2○○360÷⍨11×60⊥⍎¨↓2 2⍴⎕

Try it online!

The angle changes linearly with the time, going through 22×360° every 1440 minutes, or 5.5°/min.

Method:

  1. Take input: 

  2. Make into 2-by-2 table: 2 2⍴

  3. Split into rows: 

  4. Evaluate each: ⍎¨

  5. Convert to minutes: 60⊥

  6. Convert to degrees and then to radians (5.5t × π/180 = 11t × π/360): ○360÷⍨11×

  7. arccos cos to invert after π/2: ¯2○2○

Test cases can be verified by converting the result into degrees:

      angle←  {¯2○2○○360÷⍨11×60⊥⍎¨↓2 2⍴⍵}
      rads2degs←{180×⍵÷○1}

      rads2degs angle ¨ '0000' '0010' '0020' '0030' '0040' '0050' '0150' '0240' '0725' '1020' '1350' '1725'
0 55 110 165 140 85 115 160 72.5 170 115 12.5

Try it online!

05AB1E, 23 bytes

2ôć12%30*s11;*αD360α)˜ß

Outputs degrees like the challenge description.

Port of @Juan's Python answer.

Try it online or verify all test cases.

Explanation:

2ô                  # Split the (implicit) input in pieces of 2
                    #  i.e. "0150" → ['01','50']
  ć                 # Head extracted
                    #  i.e. ['01','50'] → ['50'] and '01' are pushed to the stack
   12%              # Take the hours modulo 12
      30*           # Multiplied by 30
                    #  i.e. '01' → 30
  s                 # Swap so the minutes are now at the top of the stack
   11;*             # And multiple it by 5.5
                    #  i.e. ['50'] → [275.0]
       α            # Calculate the absolute difference between the two values
                    #  30 and [275.0] → [245.0]
        D           # Duplicate this value
         360α       # Calculate the absolute difference between this value and 360
                    #  i.e. [245.0] → [115.0]
             )      # Wrap the entire stack to a list
                    #  i.e. [245.0] and [115.0] → [[245.0],[115.0]]
              ˜     # Flatten this list (necessary due to the head extracted)
                    #  i.e. [[245.0],[115.0]] → [245.0,115.0]
               ß    # And take the smallest value of the two (output implicitly)
                    #  i.e. [245.0,115.0] → 115.0

Python, 106 bytes

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.

Python, 82 bytes

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]

C# (.NET Core), 87 bytes

t=>{var i=int.Parse(t);double d=i/100%12*30-i%100*5.5,r=d<0?-d:d;return r>180?360-r:r;}

Try it online!

I'm sure there are possible improvements that I have missed.

DeGolfed

t=>{
    var i = int.Parse(t);
    // The hour angles minus the minute angles
    double d = i / 100 % 12 * 30 -
               i % 100 * 5.5,
    // account for this possibly being a negative angle
           r = d < 0? -d : d;

    // Get the smaller of the two possible rotational angles
    return r > 180? 360-r : r;
}

ES6, 52 50 bytes

t=>(t=(t-t.match`..`*40)*11%720,(t>360?720-t:t)/2)

Input string, output in degrees. If half degrees is acceptable, 46 bytes:

t=>(t=(t-t.match`..`*40)*11%720,t>360?720-t:t)

Edit: Saved 2 bytes by using a template string parameter to match.

TI-BASIC, 22 bytes

expr(Ans
sin⁻¹(sin(πfPart(11/6!(Ans-40int(sub(Ans

My unit is the "πth of a revolution", equal to 2 radians. The TI-83+ was introduced in 1996, making it much older than this challenge and thus eligible.

First we evaluate the string using expr(, then:

                                 sub(Ans   input/100. Don't ask why.
                             int(sub(Ans   Number of hours
                           40              Times 40
                       Ans-                Subtract from input. This converts to minutes.
                 11/6!(                    Multiply by 11/720 since 720/11 is the period.
           fPart(                          Take fractional part
sin⁻¹(sin(π                                Map [0,½] to [0,π/2] and [½,1] to [π/2,0].

All test cases have been verified.

Matlab/Octave, 56 bytes

An anonymous function accepting a string, output is in degrees.

@(i)180-abs(mod((i-48)*[600;60;10;1],720/11)-360/11)*5.5

C99, 86 78 bytes

My units are twelfths of revolutions (so 3 corresponds to 90°)

#include<math.h>
float f(int t){return fabs(remainder((t+t%100/1.5)*.11,12));}

Equivalently, in C++14, for 76 bytes:

#include<cmath>
auto f(int t){return fabs(remainder((t+t%100/1.5)*.11,12));}

BSD and SVID platforms have remd as an alias for remainder (to save 5 more), but I'm sticking with standard C and C++.

Explanation

We convert sexagesimal seconds to centihours by adding t%100/1.5 (so 0030 becomes 0050 etc), and divide by 100 to get hours. Coincidence of hands occurs 11 times every 12 hours, so multiply by 11 and divide by 12; we take the remainder in the range [-6,+6], and return its absolute value.

Test program

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char**argv)
{
    int i;
    for (i = 1;  i < argc;  ++i)
        printf("%4s: %f\n", argv[i], f(atoi(argv[i])));
    return 0;
}

Test output:

A minimum around 12:00:

1150: 1.833333
1151: 1.650000
1152: 1.466667
1153: 1.283333
1154: 1.100000
1155: 0.916667
1156: 0.733333
1157: 0.550000
1158: 0.366667
1159: 0.183333
1200: 0.000000
1201: 0.183333
1202: 0.366667
1203: 0.550000
1204: 0.733333
1205: 0.916667
1206: 1.100000
1207: 1.283333
1208: 1.466667
1209: 1.650000
1210: 1.833333

And a maximum around 6:00:

0555: 5.083333
0556: 5.266667
0557: 5.450000
0558: 5.633333
0559: 5.816667
0600: 6.000000
0601: 5.816667
0602: 5.633333
0603: 5.450000
0604: 5.266667
0605: 5.083333

JavaScript (ES6), 75 bytes

x=>Math.min(x=((x=x.match(/\d\d/g))[0]*60+x[1]*1)*5.5%360,360-x).toFixed(1)

This question needed a JavaScript solution.

PHP, 80 Characters

<?=($i=$argv[1])&&($n=abs(($i[0].$i[1])%12*30-($i[2].$i[3])*5.5))>180?360-$n:$n;

Can be run from CLI php /script_name input

Explanation:

<?=                           // output result to console
    ($i = $argv[1]) && (      // $argv is an array containing CLI parameters (0: script name, 1: first parameter, etc.)
        $n = abs(             // absolute value to deal with negative numbers
            ($i[0] . $i[1])   // get hours - the first two characters from the input (0 and 1)
                % 12 * 30     // modulus 12 to deal with PM hours (13-23) multiplied by 360/12 = 30 degrees
            - ($i[2] . $i[3]) // get minutes - the subsequent characters from the input (2 and 3)
                * 5.5)        // multiply minutes by 5.5 (1 minute is 360/60 = 6 degrees
                              // and the hour hand moves every minute by 30/60 = 0.5 degrees which we subtract)
        ) > 180               // compare obtained result to 180
    ? 360 - $n                // if the result is greater subtract it from 360
    : $n;                     // if it's less - output as it is

Test cases (input output)

0000 0
0010 55
0155 87.5
0240 160
1234 173
2155 32.5
2222 179

C++, 175 174 166 156 Characters

#include <iostream>
#include <cmath>
int main(){int m,h;std::cin>>h;m=h%100;h=(h-m)/100;h=h>11?h=h-12:h;h=std::abs(h*60-m*11);std::cout<<std::min(720-h,h);}

Using "half degree's" as my unit of choice :D

Try it Online!

Perl, 58 characters

Perl is fun

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

Golfscript, 42 bytes

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

Outputs whole-a-degrees in float format.

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

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.

graphs

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

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 adopted MtnViewMark clever trick of using half-degrees as the base unit.

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

Readable and commented:

#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

Haskell - 78 characters

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

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]