Averages/Mean time of day
You are encouraged to solve this task according to the task description, using any language you may know.
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 there are twenty-four hours in a day, which is analogous to there 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 the average time of the nocturnal activity to an accuracy of one second of time.
C
<lang c>/*29th August, 2012 Abhishek Ghosh*/
- include<stdlib.h>
- include<math.h>
- include<stdio.h>
typedef struct {
int hour, minute, second;
} digitime;
double timeToDegrees (digitime time) {
return (360 * time.hour / 24.0 + 360 * time.minute / (24 * 60.0) + 360 * time.second / (24 * 3600.0));
}
digitime timeFromDegrees (double angle) {
digitime d; double totalSeconds = 24 * 60 * 60 * angle / 360;
d.second = (int) totalSeconds % 60; d.minute = ((int) totalSeconds % 3600 - d.second) / 60; d.hour = (int) totalSeconds / 3600;
return d;
}
double meanAngle (double *angles, int size) {
double y_part = 0, x_part = 0; int i;
for (i = 0; i < size; i++) { x_part += cos (angles[i] * M_PI / 180); y_part += sin (angles[i] * M_PI / 180); }
return atan2 (y_part / size, x_part / size) * 180 / M_PI;
}
int main () {
digitime *set, meanTime; int inputs, i; double *angleSet, angleMean;
printf ("Enter number of inputs : "); scanf ("%d", &inputs); set = malloc (inputs * sizeof (digitime)); angleSet = malloc (inputs * sizeof (double)); printf ("\n\nEnter the data separated by a space between each unit : ");
for (i = 0; i < inputs; i++) { scanf ("%d:%d:%d", &set[i].hour, &set[i].minute, &set[i].second); angleSet[i] = timeToDegrees (set[i]); }
meanTime = timeFromDegrees (360 + meanAngle (angleSet, inputs));
printf ("\n\nThe mean time is : %d:%d:%d", meanTime.hour, meanTime.minute, meanTime.second); return 0;
}</lang>
- Output:
Enter number of inputs : 4 Enter the data separated by a space between each unit : 23:00:17 23:40:20 00:12:45 00:17:19 The mean time is : 23:47:43
Go
<lang go>package main
import (
"errors" "fmt" "log" "math" "time"
)
var inputs = []string{"23:00:17", "23:40:20", "00:12:45", "00:17:19"}
func main() {
tList := make([]time.Time, len(inputs)) const clockFmt = "15:04:05" var err error for i, s := range inputs { tList[i], err = time.Parse(clockFmt, s) if err != nil { log.Fatal(err) } } mean, err := meanTime(tList) if err != nil { log.Fatal(err) } fmt.Println(mean.Format(clockFmt))
}
func meanTime(times []time.Time) (mean time.Time, err error) {
if len(times) == 0 { err = errors.New("meanTime: no times specified") return } var ssum, csum float64 for _, t := range times { h, m, s := t.Clock() n := t.Nanosecond() fSec := (float64((h*60+m)*60+s) + float64(n)*1e-9) sin, cos := math.Sincos(fSec * math.Pi / (12 * 60 * 60)) ssum += sin csum += cos } if ssum == 0 && csum == 0 { err = errors.New("meanTime: mean undefined") return } _, dayFrac := math.Modf(1 + math.Atan2(ssum, csum)/(2*math.Pi)) return mean.Add(time.Duration(dayFrac * 24 * float64(time.Hour))), nil
}</lang>
- Output:
23:47:43
J
use avgAngleR
from Averages/Mean angle#J
<lang J>require 'types/datetime'
parseTimes=: ([: _&".;._2 ,&':');._2
secsFromTime=: 24 60 60 #. ] NB. convert from time to seconds
rft=: 2r86400p1 * secsFromTime NB. convert from time to radians
meanTime=: 'hh:mm:ss' fmtTime [: secsFromTime [: avgAngleR&.rft parseTimes</lang>
- Example Use:
<lang J> meanTime '23:00:17 23:40:20 00:12:45 00:17:19 ' 23:47:43</lang>
Mathematica
<lang mathematica>meanTime[list_] :=
StringJoin@ Riffle[ToString /@ Floor@{Mod[24 #, 24], Mod[24*60 #, 60], Mod[24*60*60 #, 60]} &[ Arg[Mean[ Exp[FromDigits[ToExpression@StringSplit[#, ":"], 60] & /@ list/(24*60*60) 2 Pi I]]]/(2 Pi)], ":"];
meanTime[{"23:00:17", "23:40:20", "00:12:45", "00:17:19"}]</lang>
- Output:
23:47:43
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
PARI/GP
<lang parigp>meanAngle(v)=atan(sum(i=1,#v,sin(v[i]))/sum(i=1,#v,cos(v[i])))%(2*Pi) meanTime(v)=my(x=meanAngle(2*Pi*apply(u->u[1]/24+u[2]/1440+u[3]/86400, v))*12/Pi); [x\1, 60*(x-=x\1)\1, 60*(60*x-60*x\1)] meanTime([[23,0,17], [23,40,20], [0,12,45], [0,17,19]])</lang>
- Output:
[23, 47, 43.361528520325019522213261334501251061]
Perl 6
<lang perl6>sub tod2rad($_) { [+](.comb(/\d+/) Z* 3600,60,1) * pi / 43200 }
sub rad2tod ($r) {
my $x = $r * 43200 / pi; (($x xx 3 Z/ 3600,60,1) Z% 24,60,60).fmt('%02d',':');
}
sub phase ($c) { $c.polar[1] }
sub mean-time (@t) { rad2tod phase [+] map { cis tod2rad $_ }, @t }
say mean-time($_).fmt("%s is the mean time of "), $_ for
["23:00:17", "23:40:20", "00:12:45", "00:17:19"];</lang>
- Output:
23:47:43 is the mean time of 23:00:17 23:40:20 00:12:45 00:17:19
PicoLisp
<lang PicoLisp>(load "@lib/math.l")
(de meanTime (Lst)
(let Tim (*/ (atan2 (sum '((S) (sin (*/ ($tim S) pi 43200))) Lst) (sum '((S) (cos (*/ ($tim S) pi 43200))) Lst) ) 43200 pi ) (tim$ (% (+ Tim 86400) 86400) T) ) )</lang>
- Test:
<lang PicoLisp>: (meanTime '("23:00:17" "23:40:20" "00:12:45" "00:17:19")) -> "23:47:43"</lang>
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
XPL0
<lang XPL0>include c:\cxpl\codes;
proc NumOut(N); \Display 2-digit N with leading zero int N; [if N<10 then ChOut(0, ^0); IntOut(0, N); ];
proc TimeOut(Sec); \Display real seconds as HH:MM:SS real Sec; [NumOut(fix(Sec)/3600); ChOut(0, ^:);
NumOut(rem(0)/60); ChOut(0, ^:); NumOut(rem(0));
];
func real HMS2Sec(H, M, S); \Convert hours, minutes, seconds to real seconds int H, M, S; return float(((H*60 + M)*60) + S);
func real MeanTime(A); \Return the mean of the given list of times int A; real X, Y, Sec; int I; def Pi = 3.14159265358979323846; def S2R = Pi/(12.*60.*60.); \coefficient to convert seconds to radians [X:= 0.0; Y:= 0.0; for I:= 1 to A(0) do
[Sec:= HMS2Sec(A(I,0), A(I,1), A(I,2)); X:= X + Cos(Sec*S2R); Y:= Y + Sin(Sec*S2R); ];
Sec:= ATan2(Y,X)/S2R; if Sec < 0.0 then Sec:= Sec + 24.*60.*60.; return Sec; ];
TimeOut(MeanTime([4, [23,00,17], [23,40,20], [00,12,45], [00,17,19]]))</lang>
- Output:
23:47:43