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.
AutoHotkey
(AutoHotkey1.1+)
<lang AutoHotkey>MsgBox, % "The mean time is: " MeanTime(["23:00:17", "23:40:20", "00:12:45", "00:17:19"])
MeanTime(t, x=0, y=0) { c := ATan(1) / 45 for k, v in t n := StrSplit(v, ":") , r := c * (n[1] * 3600 + n[2] * 60 + n[3]) / 240 , x += Cos(r) , y += Sin(r) r := atan2(x, y) / c r := (r < 0 ? r + 360 : r) / 15 h := SubStr("00" Round(r // 1, 0), -1) s := SubStr("00" Round(Mod(m := Mod(r, 1) * 60, 1) * 60, 0), -1) m := SubStr("00" Round(m // 1, 0), -1) return, h ":" m ":" s }
atan2(x, y) {
return dllcall("msvcrt\atan2", "Double",y, "Double",x, "CDECL Double")
}</lang>atan2() is available here. Output:
The mean time is: 23:47:43
AWK
<lang AWK>#!/usr/bin/awk -f {
c = atan2(0,-1)/(12*60*60); x=0.0; y=0.0; for (i=1; i<=NF; i++) { split($i,a,":");
p = (a[1]*3600+a[2]*60+a[3])*c; x += sin(p); y += cos(p);
} p = atan2(x,y)/c; if (p<0) p += 24*60*60; print strftime("%T",p,1);
}</lang>
$ echo 23:00:17, 23:40:20, 00:12:45, 00:17:19 | awk -f mean_time_of_day.awk 23:47:43
BBC BASIC
<lang bbcbasic> nTimes% = 4
DATA 23:00:17, 23:40:20, 00:12:45, 00:17:19 DIM angles(nTimes%-1) FOR N% = 0 TO nTimes%-1 READ tim$ angles(N%) = FNtimetoangle(tim$) NEXT PRINT "Mean time is " FNangletotime(FNmeanangle(angles(), nTimes%)) END DEF FNtimetoangle(t$) LOCAL A%, I% REPEAT A% = A% * 60 + VAL(t$) I% = INSTR(t$, ":") t$ = MID$(t$, I%+1) UNTIL I% = 0 = A% / 240 - 180 DEF FNangletotime(a) LOCAL A%, I%, t$ A% = INT((a + 180) * 240 + 0.5) FOR I% = 1 TO 3 t$ = RIGHT$("0" + STR$(A% MOD 60), 2) + ":" + t$ A% DIV= 60 NEXT = LEFT$(t$) DEF FNmeanangle(angles(), N%) LOCAL I%, addsin, addcos FOR I% = 0 TO N%-1 addsin += SINRADangles(I%) addcos += COSRADangles(I%) NEXT = DEGFNatan2(addsin, addcos) DEF FNatan2(y,x) : ON ERROR LOCAL = SGN(y)*PI/2 IF x>0 THEN = ATN(y/x) ELSE IF y>0 THEN = ATN(y/x)+PI ELSE = ATN(y/x)-PI</lang>
- Output:
Mean time is 23:47:43
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
C#
<lang csharp>using System; using System.Collections.Generic; using System.Linq; using System.Text;
namespace RosettaCode {
class Program { static void Main(string[] args) { Func<TimeSpan, double> TimeToDegrees = (time) => 360 * time.Hours / 24.0 + 360 * time.Minutes / (24 * 60.0) + 360 * time.Seconds / (24 * 3600.0); Func<List<double>, double> MeanAngle = (angles) => { double y_part = 0.0d, x_part = 0.0d; int numItems = angles.Count;
for (int i = 0; i < numItems; i++) { x_part += Math.Cos(angles[i] * Math.PI / 180); y_part += Math.Sin(angles[i] * Math.PI / 180); }
return Math.Atan2(y_part / numItems, x_part / numItems) * 180 / Math.PI; }; Func<double, TimeSpan> TimeFromDegrees = (angle) => new TimeSpan( (int)(24 * 60 * 60 * angle / 360) / 3600, ((int)(24 * 60 * 60 * angle / 360) % 3600 - (int)(24 * 60 * 60 * angle / 360) % 60) / 60, (int)(24 * 60 * 60 * angle / 360) % 60); List<double> digitimes = new List<double>(); TimeSpan digitime; string input;
Console.WriteLine("Enter times, end with no input: "); do { input = Console.ReadLine(); if (!(string.IsNullOrWhiteSpace(input))) { if (TimeSpan.TryParse(input, out digitime)) digitimes.Add(TimeToDegrees(digitime)); else Console.WriteLine("Seems this is wrong input: ignoring time"); } } while (!string.IsNullOrWhiteSpace(input));
if(digitimes.Count() > 0) Console.WriteLine("The mean time is : {0}", TimeFromDegrees(360 + MeanAngle(digitimes))); } }
} </lang>
- Output:
Enter times, end with no input: 23:00:17 23:40:20 00:12:45 00:17:19 The mean time is : 23:47:43
Erlang
<lang Erlang> -module( mean_time_of_day ). -export( [from_times/1, task/0] ).
from_times( Times ) -> Seconds = [seconds_from_time(X) || X <- Times], Degrees = [degrees_from_seconds(X) || X <- Seconds], Average = mean_angle:from_degrees( Degrees ), time_from_seconds( seconds_from_degrees(Average) ).
task() -> Times = ["23:00:17", "23:40:20", "00:12:45", "00:17:19"], io:fwrite( "The mean time of ~p is: ~p~n", [Times, from_times(Times)] ).
degrees_from_seconds( Seconds ) when Seconds < (24 * 3600) -> (Seconds * 360) / (24 * 3600).
seconds_from_degrees( Degrees ) when Degrees < 0 -> seconds_from_degrees( Degrees + 360 ); seconds_from_degrees( Degrees ) when Degrees < 360 -> (Degrees * 24 * 3600) / 360.
seconds_from_time( Time ) -> {ok, [Hours, Minutes, Seconds], _Rest} = io_lib:fread( "~d:~d:~d", Time ), Hours * 3600 + Minutes * 60 + Seconds.
time_from_seconds( Seconds_float ) -> Seconds = erlang:round( Seconds_float ), Hours = Seconds div 3600, Minutes = (Seconds - (Hours * 3600)) div 60, Secs = Seconds - (Hours * 3600) - (Minutes * 60), lists:flatten( io_lib:format("~2.10.0B:~2.10.0B:~2.10.0B", [Hours, Minutes, Secs]) ). </lang>
- Output:
17> mean_time_of_day:task(). The mean time of ["23:00:17","23:40:20","00:12:45","00:17:19"] 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
Groovy
Solution: <lang groovy>import static java.lang.Math.*
final format = 'HH:mm:ss', clock = PI / 12, millisPerHr = 3600*1000 final tzOffset = new Date(0).timezoneOffset / 60 def parseTime = { time -> (Date.parse(format, time).time / millisPerHr) - tzOffset } def formatTime = { time -> new Date((time + tzOffset) * millisPerHr as int).format(format) } def mean = { list, closure -> list.sum(closure)/list.size() } def meanTime = { ... timeStrings ->
def times = timeStrings.collect(parseTime) formatTime(atan2( mean(times) { sin(it * clock) }, mean(times) { cos(it * clock) }) / clock)
}</lang>
Test: <lang groovy>println (meanTime("23:00:17", "23:40:20", "00:12:45", "00:17:19"))</lang>
Output:
23:47:43
Icon and Unicon
<lang>procedure main(A)
every put(B := [], ct2a(!A)) write(ca2t(meanAngle(B)))
end
procedure ct2a(t)
t ? {s := ((1(move(2),move(1))*60 + 1(move(2),move(1)))*60 + move(2))} return (360.0/86400.0) * s
end
procedure ca2t(a)
while a < 0 do a +:= 360.0 t := integer((86400.0/360.0)*a + 0.5) s := left(1(.t % 60, t /:= 60),2,"0") s := left(1(.t % 60, t /:= 60),2,"0")||":"||s s := left(t,2,"0")||":"||s return s
end
procedure meanAngle(A)
every (sumSines := 0.0) +:= sin(dtor(!A)) every (sumCosines := 0.0) +:= cos(dtor(!A)) return rtod(atan(sumSines/*A,sumCosines/*A))
end</lang>
Sample run:
->amtod 23:00:17 23:40:20 00:12:45 00:17:19 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>
Liberty BASIC
<lang lb> global pi pi = acs(-1)
Print "Average of:" for i = 1 to 4
read t$ print t$ a=time2angle(t$) ss=ss+sin(a) sc=sc+cos(a)
next a=atan2(ss,sc) if a<0 then a=a+2*pi print "is ";angle2time$(a)
end data "23:00:17", "23:40:20", "00:12:45", "00:17:19"
function nn$(n)
nn$=right$("0";n, 2)
end function
function angle2time$(a)
a=int(a/2/pi*24*60*60) ss=a mod 60 a=int(a/60) mm=a mod 60 hh=int(a/60) angle2time$=nn$(hh);":";nn$(mm);":";nn$(ss)
end function
function time2angle(time$)
hh=val(word$(time$,1,":")) mm=val(word$(time$,2,":")) ss=val(word$(time$,3,":")) time2angle=2*pi*(60*(60*hh+mm)+ss)/24/60/60
end function
function atan2(y, x)
On Error GoTo [DivZero] 'If y is 0 catch division by zero error atan2 = (2 * (atn((sqr((x * x) + (y * y)) - x)/ y))) exit function [DivZero] atan2 = (y=0)*(x<0)*pi
End Function </lang>
- Output:
Average of: 23:00:17 23:40:20 00:12:45 00:17:19 is 23:47:43
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
MATLAB / Octave
<lang MATLAB>function t = mean_time_of_day(t)
c = pi/(12*60*60); for k=1:length(t)
a = sscanf(t{k},'%d:%d:%d'); phi(k) = (a(1)*3600+a(2)*60+a(3));
end; d = angle(mean(exp(i*phi*c)))/(2*pi); % days if (d<0) d += 1; t = datestr(d,"HH:MM:SS");
end; </lang>
mean_time_of_day({'23:00:17', '23:40:20', '00:12:45', '00:17:19'}) ans = 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
ooRexx
<lang oorexx>/* REXX ---------------------------------------------------------------
- 25.06.2014 Walter Pachl
- --------------------------------------------------------------------*/
times='23:00:17 23:40:20 00:12:45 00:17:19' sum=0 day=86400 x=0 y=0 Do i=1 To words(times) /* loop over times */
time.i=word(times,i) /* pick a time */ alpha.i=t2a(time.i) /* convert to angle (degrees) */ /* Say time.i format(alpha.i,6,9) */ x=x+rxcalcsin(alpha.i) /* accumulate sines */ y=y+rxcalccos(alpha.i) /* accumulate cosines */ End
ww=rxcalcarctan(x/y) /* compute average angle */ ss=ww*86400/360 /* convert to seconds */ If ss<0 Then ss=ss+day /* avoid negative value */ m=ss%60 /* split into hh mm ss */ s=ss-m*60 h=m%60 m=m-h*60 Say f2(h)':'f2(m)':'f2(s) /* show the mean time */ Exit
t2a: Procedure Expose day /* convert time to angle */
Parse Arg hh ':' mm ':' ss sec=(hh*60+mm)*60+ss If sec>(day/2) Then sec=sec-day a=360*sec/day Return a
f2: return right(format(arg(1),2,0),2,0)
- requires rxmath library</lang>
- Output:
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, round(60*(60*x-60*x\1))] meanTime([[23,0,17], [23,40,20], [0,12,45], [0,17,19]])</lang>
- Output:
[23, 47, 43]
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
Racket
<lang racket>
- lang racket
(define (mean-angle/radians as)
(define n (length as)) (atan (* (/ 1 n) (for/sum ([αj as]) (sin αj))) (* (/ 1 n) (for/sum ([αj as]) (cos αj)))))
(define (mean-time times)
(define secs/day (* 60 60 24)) (define (time->deg time) (/ (for/fold ([sum 0]) ([t (map string->number (string-split time ":"))]) (+ (* 60 sum) t)) secs/day 1/360 (/ 180 pi))) (define secs (modulo (inexact->exact (round (* (mean-angle/radians (map time->deg times)) (/ 180 pi) 1/360 secs/day))) secs/day)) (let loop ([s secs] [ts '()]) (if (zero? s) (string-join ts ":") (let-values ([(q r) (quotient/remainder s 60)]) (loop q (cons (~r r #:min-width 2 #:pad-string "0") ts))))))
(mean-time '("23:00:17" "23:40:20" "00:12:45" "00:17:19")) </lang>
- Output:
"23:47:43"
REXX
<lang rexx>/* REXX ---------------------------------------------------------------
- 25.06.2014 Walter Pachl
- taken from ooRexx using my very aged sin/cos/artan functions
- --------------------------------------------------------------------*/
times='23:00:17 23:40:20 00:12:45 00:17:19' sum=0 day=86400 p=3.14159265358979323846264 x=0 y=0 Do i=1 To words(times) /* loop over times */
time.i=word(times,i) /* pick a time */ alpha.i=t2a(time.i) /* convert to angle (radians) */ /* Say time.i format(alpha.i,6,9) */ x=x+sin(alpha.i) /* accumulate sines */ y=y+cos(alpha.i) /* accumulate cosines */ End
ww=arctan(x/y) /* compute average angle */ ss=ww*86400/(2*pi) /* convert to seconds */ If ss<0 Then ss=ss+day /* avoid negative value */ m=ss%60 /* split into hh mm ss */ s=ss-m*60 h=m%60 m=m-h*60 Say f2(h)':'f2(m)':'f2(s) /* show the mean time */ Exit
t2a: Procedure Expose day pi /* convert time to angle */
Parse Arg hh ':' mm ':' ss sec=(hh*60+mm)*60+ss If sec>(day/2) Then sec=sec-day a=2*pi*sec/day Return a
f2: return right(format(arg(1),2,0),2,0)
sin: Procedure Expose pi
Parse Arg x prec=digits() Numeric Digits (2*prec) Do While x>pi x=x-pi End Do While x<-pi x=x+pi End o=x u=1 r=x Do i=3 By 2 ra=r o=-o*x*x u=u*i*(i-1) r=r+(o/u) If r=ra Then Leave End Numeric Digits prec Return r+0
cos: Procedure Expose pi
Parse Arg x prec=digits() Numeric Digits (2*prec) Numeric Fuzz 3 o=1 u=1 r=1 Do i=1 By 2 ra=r o=-o*x*x u=u*i*(i+1) r=r+(o/u) If r=ra Then Leave End Numeric Digits prec Return r+0
arctan: Procedure
Parse Arg x prec=digits() Numeric Digits (2*prec) Numeric Fuzz 3 o=x u=1 r=x k=0 Do i=3 By 2 ra=r o=-o*x*x r=r+(o/i) If r=ra Then Leave k=k+1 If k//1000=0 Then Say i left(r,40) format(abs(o/i),15,5) End Numeric Digits (prec) Return r+0</lang>
- Output:
23:47:43
Ruby
Using the methods at [angle]
<lang ruby>def time2deg(t)
raise "invalid time" unless m = t.match(/^(\d\d):(\d\d):(\d\d)$/) hh,mm,ss = m[1..3].map {|e| e.to_i} raise "invalid time" unless (0..23).include? hh and (0..59).include? mm and (0..59).include? ss (hh*3600 + mm*60 + ss) * 360 / 86400.0
end
def deg2time(d)
sec = (d % 360) * 86400 / 360.0 "%02d:%02d:%02d" % [sec/3600, (sec%3600)/60, sec%60]
end
def mean_time(times)
deg2time(mean_angle(times.map {|t| time2deg t}))
end
puts mean_time ["23:00:17", "23:40:20", "00:12:45", "00:17:19"]</lang>
- Output:
23:47:43
Scala
<lang Scala>trait MeanAnglesComputation {
import scala.math.{ atan2, cos, Pi, sin }
def meanAngle(angles: List[Double], convFactor: Double = 180.0 / Pi) = { val sums = angles.foldLeft((.0, .0))((r, c) => { val rads = c / convFactor; (r._1 + sin(rads), r._2 + cos(rads)) }) val result = atan2(sums._1, sums._2) (result + (if (result.signum == -1) 2 * Pi else 0.0)) * convFactor }
}
object MeanBatTime extends App with MeanAnglesComputation {
import java.time.LocalTime val dayInSeconds = 60 * 60 * 24
def afterMidnight(twentyFourHourTime: String) = { val t = LocalTime.parse(twentyFourHourTime)
(if (t.isBefore(LocalTime.NOON)) dayInSeconds else 0) + LocalTime.parse(twentyFourHourTime).toSecondOfDay() }
def batTimes = List("23:00:17", "23:40:20", "00:12:45", "00:17:19") def times = batTimes.map(t => (afterMidnight(t).toDouble))
assert(LocalTime.MIN.plusSeconds(meanAngle(times, dayInSeconds).round).toString == "23:47:40")
import scala.compat.Platform.currentTime println(s"Successfully completed without errors. [total ${currentTime - executionStart} ms]")
}</lang>
Tcl
<lang tcl>proc meanTime {times} {
set secsPerRad [expr {60 * 60 * 12 / atan2(0,-1)}] set sumSin [set sumCos 0.0] foreach t $times {
# Convert time to count of seconds from midnight scan $t "%02d:%02d:%02d" h m s incr s [expr {[incr m [expr {$h * 60}]] * 60}] # Feed into averaging set sumSin [expr {$sumSin + sin($s / $secsPerRad)}] set sumCos [expr {$sumCos + cos($s / $secsPerRad)}]
} # Don't need to divide by counts; atan2() cancels that out set a [expr {round(atan2($sumSin, $sumCos) * $secsPerRad)}] # Convert back to human-readable format "%02d:%02d:%02d" [expr {$a / 60 / 60 % 24}] [expr {$a / 60 % 60}] [expr {$a % 60}]
}
puts [meanTime {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
zkl
This solution is a bit greasy, combining the solution to task "Averages/Mean angle" and some on the fly time to angle and back conversions. <lang zkl>var D=Time.Date; fcn meanT(t1,t2,etc){
ts:=vm.arglist.apply(fcn(hms){ (D.toFloat(hms.split(":").xplode())*15).toRad() }); n:=ts.len(); mt:=(ts.apply("sin").sum(0.0)/n) .atan2(ts.apply("cos").sum(0.0)/n) .toDeg() /15; if(mt<0) mt+=24; //-0.204622-->23.7954 D.toHour(mt).concat(":")
}</lang> Time.Date.toFloat/toHour convert 24hr HMS to fractional time and back. Multiplying fractional time by 360/24=15 yields angle.
- Output:
meanT("23:00:17", "23:40:20", "00:12:45", "00:17:19") 23:47:43