Averages/Mean time of day

From Rosetta Code
Averages/Mean time of day is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

A particular activity of bats occurs at these times of the day:

23:00:17, 23:40:20, 00:12:45, 00:17:19

Using the idea that their are twenty four hours in a day which is analogous to their being 360 degrees in a circle, map times of day to and from angles and using the ideas of Averages/Mean angle compute and show here the average time of the nocturnal activity to an accuracy of a second of time.


OCaml

<lang ocaml>let pi_twice = 2.0 *. 3.14159_26535_89793_23846_2643 let day = float (24 * 60 * 60)

let rad_of_time t =

 t *. pi_twice /. day

let time_of_rad r =

 r *. day /. pi_twice

let mean_angle angles =

 let sum_sin = List.fold_left (fun sum a -> sum +. sin a) 0.0 angles
 and sum_cos = List.fold_left (fun sum a -> sum +. cos a) 0.0 angles in
 atan2 sum_sin sum_cos

let mean_time times =

 let angles = List.map rad_of_time times in
 let t = time_of_rad (mean_angle angles) in
 if t < 0.0 then t +. day else t

let parse_time t =

 Scanf.sscanf t "%d:%d:%d" (fun h m s -> float (s + m * 60 + h * 3600))

let round x = int_of_float (floor (x +. 0.5))

let string_of_time t =

 let t = round t in
 let h = t / 3600 in
 let rem = t mod 3600 in
 let m = rem / 60 in
 let s = rem mod 60 in
 Printf.sprintf "%d:%d:%d" h m s

let () =

 let times = ["23:00:17"; "23:40:20"; "00:12:45"; "00:17:19"] in
 Printf.printf "The mean time of [%s] is: %s\n"
   (String.concat "; " times)
   (string_of_time (mean_time (List.map parse_time times)))</lang>

Output:

The mean time of [23:00:17; 23:40:20; 00:12:45; 00:17:19] is: 23:47:43

Python

<lang python>from cmath import rect, phase from math import radians, degrees


def mean_angle(deg):

   return degrees(phase(sum(rect(1, radians(d)) for d in deg)/len(deg)))

def mean_time(times):

   t = (time.split(':') for time in times)
   seconds = ((float(s) + int(m) * 60 + int(h) * 3600) 
              for h, m, s in t)
   day = 24 * 60 * 60
   to_angles = [s * 360. / day for s in seconds]
   mean_as_angle = mean_angle(to_angles)
   mean_seconds = mean_as_angle * day / 360.
   if mean_seconds < 0:
       mean_seconds += day
   h, m = divmod(mean_seconds, 3600)
   m, s = divmod(m, 60)
   return '%02i:%02i:%02i' % (h, m, s)


if __name__ == '__main__':

   print( mean_time(["23:00:17", "23:40:20", "00:12:45", "00:17:19"]) )</lang>
Output
23:47:43