Averages/Mean time of day: Difference between revisions
m (→{{header|C#}}: Changing the section header so that task shows up under the language properly) |
(Added Algol 68) |
||
(83 intermediate revisions by 43 users not shown) | |||
Line 1: | Line 1: | ||
{{task|Date and time}} |
{{task|Date and time}} |
||
;Task |
|||
A particular activity of bats occurs at these times of the day: |
A particular activity of bats occurs at these times of the day: |
||
:<tt>23:00:17</tt>, <tt>23:40:20</tt>, <tt>00:12:45</tt>, <tt>00:17:19</tt> |
:<tt>23:00:17</tt>, <tt>23:40:20</tt>, <tt>00:12:45</tt>, <tt>00:17:19</tt> |
||
Line 9: | Line 12: | ||
compute and show the average time of the nocturnal activity |
compute and show the average time of the nocturnal activity |
||
to an accuracy of one second of time. |
to an accuracy of one second of time. |
||
{{task heading|See also}} |
|||
{{Related tasks/Statistical measures}} |
|||
<hr> |
|||
=={{header|11l}}== |
|||
{{trans|Python}} |
|||
<syntaxhighlight lang="11l">F mean_angle(angles) |
|||
V x = sum(angles.map(a -> cos(radians(a)))) / angles.len |
|||
V y = sum(angles.map(a -> sin(radians(a)))) / angles.len |
|||
R degrees(atan2(y, x)) |
|||
F mean_time(times) |
|||
V t = (times.map(time -> time.split(‘:’))) |
|||
V seconds = (t.map(hms -> (Float(hms[2]) + Int(hms[1]) * 60 + Int(hms[0]) * 3600))) |
|||
V day = 24 * 60 * 60 |
|||
V to_angles = seconds.map(s -> s * 360.0 / @day) |
|||
V mean_as_angle = mean_angle(to_angles) |
|||
V mean_seconds = round(mean_as_angle * day / 360.0) |
|||
I mean_seconds < 0 |
|||
mean_seconds += day |
|||
V h = mean_seconds I/ 3600 |
|||
V m = mean_seconds % 3600 |
|||
V s = m % 60 |
|||
m = m I/ 60 |
|||
R ‘#02:#02:#02’.format(h, m, s) |
|||
print(mean_time([‘23:00:17’, ‘23:40:20’, ‘00:12:45’, ‘00:17:19’]))</syntaxhighlight> |
|||
{{out}} |
|||
<pre>23:47:43</pre> |
|||
=={{header|Action!}}== |
|||
Action! does not support trigonometry, therefore a simple arithmetic solution has been proposed. |
|||
{{libheader|Action! Tool Kit}} |
|||
{{libheader|Action! Real Math}} |
|||
<syntaxhighlight lang="action!">INCLUDE "H6:REALMATH.ACT" |
|||
DEFINE PTR="CARD" |
|||
TYPE Time=[BYTE s,m,h] |
|||
REAL r60 |
|||
PROC PrintB2(BYTE b) |
|||
IF b<10 THEN Put('0) FI |
|||
PrintB(b) |
|||
RETURN |
|||
PROC PrintTime(Time POINTER t) |
|||
PrintB2(t.h) Put(':) |
|||
PrintB2(t.m) Put(':) |
|||
PrintB2(t.s) |
|||
RETURN |
|||
PROC Decode(CHAR ARRAY st Time POINTER t) |
|||
CHAR ARRAY tmp |
|||
IF st(0)#8 THEN Break() FI |
|||
SCopyS(tmp,st,1,2) t.h=ValB(tmp) |
|||
SCopyS(tmp,st,4,5) t.m=ValB(tmp) |
|||
SCopyS(tmp,st,7,8) t.s=ValB(tmp) |
|||
RETURN |
|||
PROC TimeToSeconds(Time POINTER t REAL POINTER seconds) |
|||
REAL r |
|||
IntToReal(t.h,seconds) |
|||
RealMult(seconds,r60,seconds) |
|||
IntToReal(t.m,r) |
|||
RealAdd(seconds,r,seconds) |
|||
RealMult(seconds,r60,seconds) |
|||
IntToReal(t.s,r) |
|||
RealAdd(seconds,r,seconds) |
|||
RETURN |
|||
PROC SecondsToTime(REAL POINTER seconds Time POINTER t) |
|||
REAL tmp1,tmp2 |
|||
RealAssign(seconds,tmp1) |
|||
RealMod(tmp1,r60,tmp2) |
|||
t.s=RealToInt(tmp2) |
|||
RealDivInt(tmp1,r60,tmp2) |
|||
RealMod(tmp2,r60,tmp1) |
|||
t.m=RealToInt(tmp1) |
|||
RealDivInt(tmp2,r60,tmp1) |
|||
t.h=RealToInt(tmp1) |
|||
RETURN |
|||
PROC AverageTime(PTR ARRAY times BYTE count Time POINTER res) |
|||
BYTE i |
|||
Time t |
|||
REAL avg,rcount,seconds,halfDay,day |
|||
IntToReal(0,avg) |
|||
IntToReal(count,rcount) |
|||
ValR("43200",halfDay) ;seconds in the half of day |
|||
ValR("86400",day) ;seconds in the whole day |
|||
FOR i=0 TO count-1 |
|||
DO |
|||
Decode(times(i),t) |
|||
TimeToSeconds(t,seconds) |
|||
IF RealLess(seconds,halfDay) THEN |
|||
RealAdd(seconds,day,seconds) ;correction of time |
|||
FI |
|||
RealAdd(avg,seconds,avg) |
|||
OD |
|||
RealDivInt(avg,rcount,avg) |
|||
WHILE RealGreaterOrEqual(avg,day) |
|||
DO |
|||
RealSub(avg,day,avg) ;correction of time |
|||
OD |
|||
SecondsToTime(avg,res) |
|||
RETURN |
|||
PROC Main() |
|||
DEFINE COUNT="4" |
|||
PTR ARRAY times(COUNT) |
|||
Time t |
|||
Put(125) PutE() ;clear the screen |
|||
IntToReal(60,r60) |
|||
times(0)="23:00:17" times(1)="23:40:20" |
|||
times(2)="00:12:45" times(3)="00:17:19" |
|||
AverageTime(times,COUNT,t) |
|||
Print("Mean time is ") PrintTime(t) |
|||
RETURN</syntaxhighlight> |
|||
{{out}} |
|||
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Mean_time_of_day.png Screenshot from Atari 8-bit computer] |
|||
<pre> |
|||
Mean time is 23:47:40 |
|||
</pre> |
|||
=={{header|Ada}}== |
|||
<syntaxhighlight lang="ada">with Ada.Calendar.Formatting; |
|||
with Ada.Command_Line; |
|||
with Ada.Numerics.Elementary_Functions; |
|||
with Ada.Strings.Fixed; |
|||
with Ada.Text_IO; |
|||
procedure Mean_Time_Of_Day is |
|||
subtype Time is Ada.Calendar.Time; |
|||
subtype Time_Of_Day is Ada.Calendar.Day_Duration; |
|||
subtype Time_String is String (1 .. 8); -- "HH:MM:SS" |
|||
type Time_List is array (Positive range <>) of Time_String; |
|||
function Average_Time (List : Time_List) return Time_String is |
|||
function To_Time (Time_Image : Time_String) return Time |
|||
is (Ada.Calendar.Formatting.Value ("2000-01-01 " & Time_Image)); |
|||
function To_Time_Of_Day (TS : Time) return Time_Of_Day is |
|||
use Ada.Calendar.Formatting; |
|||
Hour_Part : constant Time_Of_Day := 60.0 * 60.0 * Hour (TS); |
|||
Min_Part : constant Time_Of_Day := 60.0 * Minute (TS); |
|||
Sec_Part : constant Time_Of_Day := Time_Of_Day (Second (TS)); |
|||
begin |
|||
return Hour_Part + Min_Part + Sec_Part; |
|||
end To_Time_Of_Day; |
|||
function To_Time_Image (Angle : Time_Of_Day) return Time_String |
|||
is |
|||
use Ada.Calendar.Formatting; |
|||
TOD : constant Time := Time_Of |
|||
(Year => 2000, Month => 1, Day => 1, -- Not used |
|||
Seconds => Angle); |
|||
begin |
|||
return Ada.Strings.Fixed.Tail (Image (TOD), Time_String'Length); |
|||
end To_Time_Image; |
|||
function Average_Time_Of_Day (List : Time_List) return Time_Of_Day is |
|||
use Ada.Numerics.Elementary_Functions; |
|||
Cycle : constant Float := Float (Time_Of_Day'Last); |
|||
X_Sum, Y_Sum : Float := 0.0; |
|||
Angle : Float; |
|||
begin |
|||
for Time_Stamp of List loop |
|||
Angle := Float (To_Time_Of_Day (To_Time (Time_Stamp))); |
|||
X_Sum := X_Sum + Cos (Angle, Cycle => Cycle); |
|||
Y_Sum := Y_Sum + Sin (Angle, Cycle => Cycle); |
|||
end loop; |
|||
Angle := Arctan (Y_Sum, X_Sum, Cycle => Cycle); |
|||
if Angle < 0.0 then |
|||
Angle := Angle + Cycle; |
|||
elsif Angle > Cycle then |
|||
Angle := Angle - Cycle; |
|||
end if; |
|||
return Time_Of_Day (Angle); |
|||
end Average_Time_Of_Day; |
|||
begin |
|||
return To_Time_Image (Average_Time_Of_Day (List)); |
|||
end Average_Time; |
|||
use Ada.Command_Line; |
|||
List : Time_List (1 .. Argument_Count); |
|||
begin |
|||
if Argument_Count = 0 then |
|||
raise Constraint_Error; |
|||
end if; |
|||
for A in 1 .. Argument_Count loop |
|||
List (A) := Argument (A); |
|||
end loop; |
|||
Ada.Text_IO.Put_Line (Average_Time (List)); |
|||
exception |
|||
when others => |
|||
Ada.Text_IO.Put_Line ("Usage: mean_time_of_day <time-1> ..."); |
|||
Ada.Text_IO.Put_Line (" <time-1> ... 'HH:MM:SS' format"); |
|||
end Mean_Time_Of_Day;</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
% ./mean_time_of_day 23:00:17 23:40:20 00:12:45 00:17:19 |
|||
23:47:43 |
|||
</pre> |
|||
=={{header|ALGOL 68}}== |
|||
Uses code from the Averages/Mean angle task, included here for convenience. |
|||
<syntaxhighlight lang="algol68"> |
|||
BEGIN # Mean time of day mapping time to angles # |
|||
# code from the Averages/Mean angle task - angles are in degrees # |
|||
PROC mean angle = ([]REAL angles)REAL: |
|||
( |
|||
INT size = UPB angles - LWB angles + 1; |
|||
REAL y part := 0, x part := 0; |
|||
FOR i FROM LWB angles TO UPB angles DO |
|||
x part +:= cos (angles[i] * pi / 180); |
|||
y part +:= sin (angles[i] * pi / 180) |
|||
OD; |
|||
arc tan2 (y part / size, x part / size) * 180 / pi |
|||
); |
|||
# end code from the Averages/Mean angle task # |
|||
MODE TIME = STRUCT( INT hh, mm, ss ); |
|||
OP TOANGLE = ( TIME t )REAL: ( ( ( ( ( ss OF t / 60 ) + mm OF t ) / 60 ) + hh OF t ) * 360 ) / 24; |
|||
OP TOTIME = ( REAL a )TIME: |
|||
BEGIN |
|||
REAL t := ( a * 24 ) / 360; |
|||
WHILE t < 0 DO t +:= 24 OD; |
|||
WHILE t > 24 DO t -:= 24 OD; |
|||
INT hh = ENTIER t; |
|||
t -:= hh *:= 60; |
|||
INT mm = ENTIER t; |
|||
INT ss = ENTIER ( ( t - mm ) * 60 ); |
|||
( hh, mm, ss ) |
|||
END # TOTIME # ; |
|||
PROC mean time = ( []TIME times )TIME: |
|||
BEGIN |
|||
[ LWB times : UPB times ]REAL angles; |
|||
FOR i FROM LWB times TO UPB times DO angles[ i ] := TOANGLE times[ i ] OD; |
|||
TOTIME mean angle( angles ) |
|||
END # mean time # ; |
|||
OP SHOW = ( TIME t )VOID: |
|||
BEGIN |
|||
PROC d2 = ( INT n )STRING: IF n < 10 THEN "0" ELSE "" FI + whole( n, 0 ); |
|||
print( ( d2( hh OF t ), ":", d2( mm OF t ), ":", d2( ss OF t ) ) ) |
|||
END # show time # ; |
|||
SHOW mean time( ( ( 23,00,17 ), ( 23,40,20 ), ( 00,12,45 ), ( 00,17,19 ) ) ) |
|||
END |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
23:47:43 |
|||
</pre> |
|||
=={{header|AutoHotkey}}== |
=={{header|AutoHotkey}}== |
||
{{works with| |
{{works with|AutoHotkey 1.1}} |
||
< |
<syntaxhighlight 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) { |
MeanTime(t, x=0, y=0) { |
||
c := ATan(1) / 45 |
static c := ATan(1) / 45 |
||
for k, v in t |
for k, v in t { |
||
n := StrSplit(v, ":") |
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 := atan2(x, y) / c |
||
r := (r < 0 ? r + 360 : r) / 15 |
r := (r < 0 ? r + 360 : r) / 15 |
||
Line 31: | Line 308: | ||
atan2(x, y) { |
atan2(x, y) { |
||
return dllcall("msvcrt\atan2", "Double",y, "Double",x, "CDECL Double") |
return dllcall("msvcrt\atan2", "Double",y, "Double",x, "CDECL Double") |
||
}</syntaxhighlight> |
|||
}</lang>atan2() is available [http://www.autohotkey.com/board/topic/24114-popup-calculator-expression-evaluator/ here]. |
|||
{{out}} |
{{out}} |
||
<pre>The mean time is: 23:47:43</pre> |
<pre>The mean time is: 23:47:43</pre> |
||
=={{header|AWK}}== |
=={{header|AWK}}== |
||
< |
<syntaxhighlight lang="awk">#!/usr/bin/awk -f |
||
{ |
{ |
||
c = atan2(0,-1)/(12*60*60); |
c = atan2(0,-1)/(12*60*60); |
||
Line 49: | Line 326: | ||
if (p<0) p += 24*60*60; |
if (p<0) p += 24*60*60; |
||
print strftime("%T",p,1); |
print strftime("%T",p,1); |
||
}</ |
}</syntaxhighlight> |
||
<pre>$ echo 23:00:17, 23:40:20, 00:12:45, 00:17:19 | awk -f mean_time_of_day.awk |
<pre>$ echo 23:00:17, 23:40:20, 00:12:45, 00:17:19 | awk -f mean_time_of_day.awk |
||
23:47:43</pre> |
23:47:43</pre> |
||
Line 55: | Line 332: | ||
=={{header|BBC BASIC}}== |
=={{header|BBC BASIC}}== |
||
{{works with|BBC BASIC for Windows}} |
{{works with|BBC BASIC for Windows}} |
||
< |
<syntaxhighlight lang="bbcbasic"> nTimes% = 4 |
||
DATA 23:00:17, 23:40:20, 00:12:45, 00:17:19 |
DATA 23:00:17, 23:40:20, 00:12:45, 00:17:19 |
||
Line 93: | Line 370: | ||
DEF FNatan2(y,x) : ON ERROR LOCAL = SGN(y)*PI/2 |
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</ |
IF x>0 THEN = ATN(y/x) ELSE IF y>0 THEN = ATN(y/x)+PI ELSE = ATN(y/x)-PI</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 100: | Line 377: | ||
=={{header|C}}== |
=={{header|C}}== |
||
<syntaxhighlight lang="c">#include<stdlib.h> |
|||
<lang c>/*29th August, 2012 |
|||
Abhishek Ghosh*/ |
|||
#include<stdlib.h> |
|||
#include<math.h> |
#include<math.h> |
||
#include<stdio.h> |
#include<stdio.h> |
||
Line 171: | Line 445: | ||
meanTime.second); |
meanTime.second); |
||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 180: | Line 454: | ||
The mean time is : 23:47:43 |
The mean time is : 23:47:43</pre> |
||
</pre> |
|||
---- |
---- |
||
=={{header|C sharp}}== |
=={{header|C sharp|C#}}== |
||
< |
<syntaxhighlight lang="csharp">using System; |
||
using System.Collections.Generic; |
using System.Collections.Generic; |
||
using System.Linq; |
using System.Linq; |
||
using System.Text; |
using System.Text; |
||
using static System.Math; |
|||
namespace RosettaCode |
namespace RosettaCode; |
||
class Program |
|||
{ |
{ |
||
private const int SecondsPerDay = 60 * 60 * 24; |
|||
class Program |
|||
static void Main() |
|||
{ |
{ |
||
var digitimes = new List<TimeSpan>(); |
|||
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; |
|||
Console.WriteLine("Enter times, end with no input: "); |
|||
while (true) { |
|||
string input = Console.ReadLine(); |
|||
if (string.IsNullOrWhiteSpace(input)) break; |
|||
y_part += Math.Sin(angles[i] * Math.PI / 180); |
|||
if (TimeSpan.TryParse(input, out var digitime)) { |
|||
digitimes.Add(digitime); |
|||
} else { |
|||
Console.WriteLine("Seems this is wrong input: ignoring time"); |
|||
} |
|||
} |
|||
if(digitimes.Count() > 0) |
|||
Console.WriteLine($"The mean time is : {MeanTime(digitimes)}"); |
|||
} |
|||
public static TimeSpan MeanTime(IEnumerable<TimeSpan> ts) => FromDegrees(MeanAngle(ts.Select(ToDegrees))); |
|||
return Math.Atan2(y_part / numItems, x_part / numItems) * 180 / Math.PI; |
|||
public static double ToDegrees(TimeSpan ts) => ts.TotalSeconds * 360d / SecondsPerDay; |
|||
}; |
|||
public static TimeSpan FromDegrees(double degrees) => TimeSpan.FromSeconds((int)(degrees * SecondsPerDay / 360)); |
|||
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; |
|||
public static double MeanAngle(IEnumerable<double> angles) |
|||
Console.WriteLine("Enter times, end with no input: "); |
|||
{ |
|||
var x = angles.Average(a => Cos(a * PI / 180)); |
|||
var y = angles.Average(a => Sin(a * PI / 180)); |
|||
return (Atan2(y, x) * 180 / PI + 360) % 360; |
|||
{ |
|||
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))); |
|||
} |
|||
} |
} |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 253: | Line 510: | ||
The mean time is : 23:47:43 |
The mean time is : 23:47:43 |
||
</pre> |
</pre> |
||
=={{header|C++}}== |
|||
<syntaxhighlight lang="cpp">#include <iomanip> |
|||
#include <iostream> |
|||
#include <vector> |
|||
#define _USE_MATH_DEFINES |
|||
#include <math.h> |
|||
struct Time { |
|||
int hour, minute, second; |
|||
friend std::ostream &operator<<(std::ostream &, const Time &); |
|||
}; |
|||
std::ostream &operator<<(std::ostream &os, const Time &t) { |
|||
return os << std::setfill('0') |
|||
<< std::setw(2) << t.hour << ':' |
|||
<< std::setw(2) << t.minute << ':' |
|||
<< std::setw(2) << t.second; |
|||
} |
|||
double timeToDegrees(Time &&t) { |
|||
return 360.0 * t.hour / 24.0 |
|||
+ 360.0 * t.minute / (24 * 60.0) |
|||
+ 360.0 * t.second / (24 * 3600.0); |
|||
} |
|||
Time degreesToTime(double angle) { |
|||
while (angle < 0.0) { |
|||
angle += 360.0; |
|||
} |
|||
while (angle > 360.0) { |
|||
angle -= 360.0; |
|||
} |
|||
double totalSeconds = 24.0 * 60 * 60 * angle / 360; |
|||
Time t; |
|||
t.second = (int)totalSeconds % 60; |
|||
t.minute = ((int)totalSeconds % 3600 - t.second) / 60; |
|||
t.hour = (int)totalSeconds / 3600; |
|||
return t; |
|||
} |
|||
double meanAngle(const std::vector<double> &angles) { |
|||
double yPart = 0.0, xPart = 0.0; |
|||
for (auto a : angles) { |
|||
xPart += cos(a * M_PI / 180); |
|||
yPart += sin(a * M_PI / 180); |
|||
} |
|||
return atan2(yPart / angles.size(), xPart / angles.size()) * 180 / M_PI; |
|||
} |
|||
int main() { |
|||
std::vector<double> tv; |
|||
tv.push_back(timeToDegrees({ 23, 0, 17 })); |
|||
tv.push_back(timeToDegrees({ 23, 40, 20 })); |
|||
tv.push_back(timeToDegrees({ 0, 12, 45 })); |
|||
tv.push_back(timeToDegrees({ 0, 17, 19 })); |
|||
double ma = meanAngle(tv); |
|||
auto mt = degreesToTime(ma); |
|||
std::cout << mt << '\n'; |
|||
return 0; |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>23:47:43</pre> |
|||
=={{header|Common Lisp}}== |
|||
{{trans|Echo Lisp}} |
|||
<syntaxhighlight lang="lisp">;; * Loading the split-sequence library |
|||
(eval-when (:compile-toplevel :load-toplevel :execute) |
|||
(ql:quickload '("split-sequence"))) |
|||
;; * The package definition |
|||
(defpackage :mean-time-of-day |
|||
(:use :common-lisp :iterate :split-sequence)) |
|||
(in-package :mean-time-of-day) |
|||
;; * The data |
|||
(defparameter *time-values* |
|||
'("23:00:17" "23:40:20" "00:12:45" "00:17:19")) |
|||
(defun time->radian (time) |
|||
"Returns the radian value for TIME given as a STRING like HH:MM:SS. Assuming a |
|||
valid input value." |
|||
(destructuring-bind (h m s) |
|||
(mapcar #'parse-integer (split-sequence #\: time)) |
|||
(+ (* h (/ PI 12)) (* m (/ PI 12 60)) (* s (/ PI 12 3600))))) |
|||
(defun radian->time (radian) |
|||
"Returns the corresponding time as a string like HH:MM:SS for RADIAN." |
|||
(let* ((time (if (plusp radian) |
|||
(round (/ (* 12 3600 radian) PI)) |
|||
(round (/ (* 12 3600 (+ radian (* 2 PI))) PI)))) |
|||
(h (floor time 3600)) |
|||
(m (floor (- time (* h 3600)) 60)) |
|||
(s (- time (* h 3600) (* m 60)))) |
|||
(format nil "~2,'0D:~2,'0D:~2,'0D" h m s))) |
|||
(defun make-polar (rho theta) |
|||
"Returns a complex representing the polar coordinates." |
|||
(complex (* rho (cos theta)) (* rho (sin theta)))) |
|||
(defun mean-time (times) |
|||
"Returns the mean time value within 24h of the list of TIMES given as strings |
|||
HH:MM:SS." |
|||
(radian->time (phase |
|||
(reduce #'+ (mapcar (lambda (time) |
|||
(make-polar 1 (time->radian time))) times))))) |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre>MEAN-TIME-OF-DAY> (mean-time *time-values*) |
|||
"23:47:43"</pre> |
|||
=={{header|D}}== |
=={{header|D}}== |
||
{{trans|Python}} |
{{trans|Python}} |
||
< |
<syntaxhighlight lang="d">import std.stdio, std.range, std.algorithm, std.complex, std.math, |
||
std.format, std.conv; |
std.format, std.conv; |
||
Line 294: | Line 669: | ||
void main() @safe { |
void main() @safe { |
||
["23:00:17", "23:40:20", "00:12:45", "00:17:19"].meanTime.writeln; |
["23:00:17", "23:40:20", "00:12:45", "00:17:19"].meanTime.writeln; |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>23:47:43</pre> |
<pre>23:47:43</pre> |
||
=={{header|Delphi}}== |
|||
{{libheader| System.SysUtils}} |
|||
{{libheader| System.Math}} |
|||
{{Trans|Go}} |
|||
<syntaxhighlight lang="delphi"> |
|||
program Averages_Mean_time_of_day; |
|||
{$APPTYPE CONSOLE} |
|||
uses |
|||
System.SysUtils, |
|||
System.Math; |
|||
const |
|||
Inputs: TArray<string> = ['23:00:17', '23:40:20', '00:12:45', '00:17:19']; |
|||
function ToTimes(ts: TArray<string>): TArray<TTime>; |
|||
begin |
|||
SetLength(result, length(ts)); |
|||
for var i := 0 to High(ts) do |
|||
Result[i] := StrToTime(ts[i]); |
|||
end; |
|||
function MeanTime(times: TArray<TTime>): TTime; |
|||
var |
|||
ssum, csum: TTime; |
|||
h, m, s, ms: word; |
|||
dayFrac, fsec, ssin, ccos: double; |
|||
begin |
|||
if Length(times) = 0 then |
|||
exit(0); |
|||
ssum := 0; |
|||
csum := 0; |
|||
for var t in times do |
|||
begin |
|||
DecodeTime(t, h, m, s, ms); |
|||
fsec := (h * 60 + m) * 60 + s + ms / 1000; |
|||
ssin := sin(fsec * Pi / (12 * 60 * 60)); |
|||
ccos := cos(fsec * Pi / (12 * 60 * 60)); |
|||
ssum := ssum + ssin; |
|||
csum := csum + ccos; |
|||
end; |
|||
if (ssum = 0) and (csum = 0) then |
|||
raise Exception.Create('Error MeanTime: Mean undefined'); |
|||
dayFrac := frac(1 + ArcTan2(ssum, csum) / (2 * Pi)); |
|||
fsec := dayFrac * 24 * 3600; |
|||
ms := Trunc(frac(fsec) * 1000); |
|||
s := trunc(fsec) mod 60; |
|||
m := trunc(fsec) div 60 mod 60; |
|||
h := trunc(fsec) div 3600; |
|||
Result := EncodeTime(h, m, s, ms); |
|||
end; |
|||
begin |
|||
writeln(TimeToStr(MeanTime(ToTimes(Inputs)))); |
|||
readln; |
|||
end.</syntaxhighlight> |
|||
=={{header|EasyLang}}== |
|||
{{trans|C}} |
|||
<syntaxhighlight lang=easylang> |
|||
func tm2deg t$ . |
|||
t[] = number strsplit t$ ":" |
|||
return 360 * t[1] / 24.0 + 360 * t[2] / (24 * 60.0) + 360 * t[3] / (24 * 3600.0) |
|||
. |
|||
func$ deg2tm deg . |
|||
len t[] 3 |
|||
h = floor (24 * 60 * 60 * deg / 360) |
|||
t[3] = h mod 60 |
|||
h = h div 60 |
|||
t[2] = h mod 60 |
|||
t[1] = h div 60 |
|||
for h in t[] |
|||
if h < 10 |
|||
s$ &= 0 |
|||
. |
|||
s$ &= h |
|||
s$ &= ":" |
|||
. |
|||
return substr s$ 1 8 |
|||
. |
|||
func mean ang[] . |
|||
for ang in ang[] |
|||
x += cos ang |
|||
y += sin ang |
|||
. |
|||
return atan2 (y / len ang[]) (x / len ang[]) |
|||
. |
|||
in$ = "23:00:17 23:40:20 00:12:45 00:17:19" |
|||
for s$ in strsplit in$ " " |
|||
ar[] &= tm2deg s$ |
|||
. |
|||
print deg2tm (360 + mean ar[]) |
|||
</syntaxhighlight> |
|||
=={{header|EchoLisp}}== |
|||
<syntaxhighlight lang="scheme"> |
|||
;; string hh:mm:ss to radians |
|||
(define (time->radian time) |
|||
(define-values (h m s) (map string->number (string-split time ":"))) |
|||
(+ (* h (/ PI 12)) (* m (/ PI 12 60)) (* s (/ PI 12 3600)))) |
|||
;; radians to string hh:mm;ss |
|||
(define (radian->time rad) |
|||
(when (< rad 0) (+= rad (* 2 PI))) |
|||
(define t (round (/ (* 12 3600 rad) PI))) |
|||
(define h (quotient t 3600)) |
|||
(define m (quotient (- t (* h 3600)) 60)) |
|||
(define s (- t (* 3600 h) (* 60 m))) |
|||
(string-join (map number->string (list h m s)) ":")) |
|||
(define (mean-time times) |
|||
(radian->time |
|||
(angle |
|||
(for/sum ((t times)) (make-polar 1 (time->radian t)))))) |
|||
(mean-time '{"23:00:17" "23:40:20" "00:12:45" "00:17:19"}) |
|||
→ "23:47:43" |
|||
</syntaxhighlight> |
|||
=={{header|Erlang}}== |
=={{header|Erlang}}== |
||
<syntaxhighlight lang="erlang"> |
|||
<lang Erlang> |
|||
-module( mean_time_of_day ). |
-module( mean_time_of_day ). |
||
-export( [from_times/1, task/0] ). |
-export( [from_times/1, task/0] ). |
||
Line 330: | Line 827: | ||
Secs = Seconds - (Hours * 3600) - (Minutes * 60), |
Secs = Seconds - (Hours * 3600) - (Minutes * 60), |
||
lists:flatten( io_lib:format("~2.10.0B:~2.10.0B:~2.10.0B", [Hours, Minutes, Secs]) ). |
lists:flatten( io_lib:format("~2.10.0B:~2.10.0B:~2.10.0B", [Hours, Minutes, Secs]) ). |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 336: | Line 833: | ||
The mean time of ["23:00:17","23:40:20","00:12:45","00:17:19"] is: "23:47:43" |
The mean time of ["23:00:17","23:40:20","00:12:45","00:17:19"] is: "23:47:43" |
||
</pre> |
</pre> |
||
=={{header|Euphoria}}== |
=={{header|Euphoria}}== |
||
{{works with|OpenEuphoria}} |
{{works with|OpenEuphoria}} |
||
<syntaxhighlight lang="euphoria"> |
|||
<lang Euphoria> |
|||
include std/console.e |
include std/console.e |
||
include std/math.e |
include std/math.e |
||
Line 405: | Line 900: | ||
if getc(0) then end if |
if getc(0) then end if |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 415: | Line 910: | ||
Mean Time: 23:47:43 |
Mean Time: 23:47:43 |
||
</pre> |
|||
=={{header|F_Sharp|F#}}== |
|||
<syntaxhighlight lang="fsharp">open System |
|||
open System.Numerics |
|||
let deg2rad d = d * Math.PI / 180. |
|||
let rad2deg r = r * 180. / Math.PI |
|||
let makeComplex = fun r -> Complex.FromPolarCoordinates(1., r) |
|||
// 1 msec = 10000 ticks |
|||
let time2deg = TimeSpan.Parse >> (fun ts -> ts.Ticks) >> (float) >> (*) (10e-9/24.) |
|||
let deg2time = (*) (24. * 10e7) >> (int64) >> TimeSpan |
|||
[<EntryPoint>] |
|||
let main argv = |
|||
let msg = "Average time for [" + (String.Join("; ",argv)) + "] is" |
|||
argv |
|||
|> Seq.map (time2deg >> deg2rad >> makeComplex) |
|||
|> Seq.fold (fun x y -> Complex.Add(x,y)) Complex.Zero |
|||
|> fun c -> c.Phase |> rad2deg |
|||
|> fun d -> if d < 0. then d + 360. else d |
|||
|> deg2time |> fun t -> t.ToString(@"hh\:mm\:ss") |
|||
|> printfn "%s: %s" msg |
|||
0</syntaxhighlight> |
|||
{{out}} |
|||
<pre>>RosettaCode 23:00:17 23:40:20 00:12:45 00:17:19 |
|||
Average time for [23:00:17; 23:40:20; 00:12:45; 00:17:19] is: 23:47:43</pre> |
|||
=={{header|Factor}}== |
|||
<syntaxhighlight lang="factor">USING: arrays formatting kernel math math.combinators |
|||
math.functions math.libm math.parser math.trig qw sequences |
|||
splitting ; |
|||
IN: rosetta-code.mean-time |
|||
CONSTANT: input qw{ 23:00:17 23:40:20 00:12:45 00:17:19 } |
|||
: time>deg ( hh:mm:ss -- x ) |
|||
":" split [ string>number ] map first3 |
|||
[ 15 * ] [ 1/4 * ] [ 1/240 * ] tri* + + ; |
|||
: mean-angle ( seq -- x ) |
|||
[ deg>rad ] map [ [ sin ] map-sum ] [ [ cos ] map-sum ] |
|||
[ length ] tri recip [ * ] curry bi@ fatan2 rad>deg ; |
|||
: cutf ( x -- str y ) |
|||
[ >integer number>string ] [ dup floor - ] bi ; |
|||
: mean-time ( seq -- str ) |
|||
[ time>deg ] map mean-angle [ 360 + ] when-negative 24 * |
|||
360 / cutf 60 * cutf 60 * round cutf drop 3array ":" join ; |
|||
: mean-time-demo ( -- ) |
|||
input dup mean-time "Mean time for %u is %s.\n" printf ; |
|||
MAIN: mean-time-demo</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Mean time for { "23:00:17" "23:40:20" "00:12:45" "00:17:19" } is 23:47:43. |
|||
</pre> |
|||
=={{header|Fortran}}== |
|||
{{works with|gfortran 5.1.0}} |
|||
<syntaxhighlight lang="fortran"> |
|||
program mean_time_of_day |
|||
implicit none |
|||
integer(kind=4), parameter :: dp = kind(0.0d0) |
|||
type time_t |
|||
integer(kind=4) :: hours, minutes, seconds |
|||
end type |
|||
character(len=8), dimension(4), parameter :: times = & |
|||
(/ '23:00:17', '23:40:20', '00:12:45', '00:17:19' /) |
|||
real(kind=dp), dimension(size(times)) :: angles |
|||
real(kind=dp) :: mean |
|||
angles = time_to_angle(str_to_time(times)) |
|||
mean = mean_angle(angles) |
|||
if (mean < 0) mean = 360 + mean |
|||
write(*, fmt='(I2.2, '':'', I2.2, '':'', I2.2)') angle_to_time(mean) |
|||
contains |
|||
real(kind=dp) function mean_angle(angles) |
|||
real(kind=dp), dimension(:), intent (in) :: angles |
|||
real(kind=dp) :: x, y |
|||
x = sum(sin(radians(angles)))/size(angles) |
|||
y = sum(cos(radians(angles)))/size(angles) |
|||
mean_angle = degrees(atan2(x, y)) |
|||
end function |
|||
elemental real(kind=dp) function radians(angle) |
|||
real(kind=dp), intent (in) :: angle |
|||
real(kind=dp), parameter :: pi = 4d0*atan(1d0) |
|||
radians = angle/180*pi |
|||
end function |
|||
elemental real(kind=dp) function degrees(angle) |
|||
real(kind=dp), intent (in) :: angle |
|||
real(kind=dp), parameter :: pi = 4d0*atan(1d0) |
|||
degrees = 180*angle/pi |
|||
end function |
|||
elemental type(time_t) function str_to_time(str) |
|||
character(len=*), intent (in) :: str |
|||
! Assuming time in format hh:mm:ss |
|||
read(str, fmt='(I2, 1X, I2, 1X, I2)') str_to_time |
|||
end function |
|||
elemental real(kind=dp) function time_to_angle(time) result (res) |
|||
type(time_t), intent (in) :: time |
|||
real(kind=dp) :: seconds |
|||
real(kind=dp), parameter :: seconds_in_day = 24*60*60 |
|||
seconds = time%seconds + 60*time%minutes + 60*60*time%hours |
|||
res = 360*seconds/seconds_in_day |
|||
end function |
|||
elemental type(time_t) function angle_to_time(angle) |
|||
real(kind=dp), intent (in) :: angle |
|||
real(kind=dp) :: seconds |
|||
real(kind=dp), parameter :: seconds_in_day = 24*60*60 |
|||
seconds = seconds_in_day*angle/360d0 |
|||
angle_to_time%hours = int(seconds/60d0/60d0) |
|||
seconds = mod(seconds, 60d0*60d0) |
|||
angle_to_time%minutes = int(seconds/60d0) |
|||
angle_to_time%seconds = mod(seconds, 60d0) |
|||
end function |
|||
end program |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
23:47:43 |
|||
</pre> |
|||
=={{header|FreeBASIC}}== |
|||
<syntaxhighlight lang="freebasic">' FB 1.05.0 Win64 |
|||
Const pi As Double = 3.1415926535897932 |
|||
Function meanAngle(angles() As Double) As Double |
|||
Dim As Integer length = Ubound(angles) - Lbound(angles) + 1 |
|||
Dim As Double sinSum = 0.0 |
|||
Dim As Double cosSum = 0.0 |
|||
For i As Integer = LBound(angles) To UBound(angles) |
|||
sinSum += Sin(angles(i) * pi / 180.0) |
|||
cosSum += Cos(angles(i) * pi / 180.0) |
|||
Next |
|||
Return Atan2(sinSum / length, cosSum / length) * 180.0 / pi |
|||
End Function |
|||
' time string assumed to be in format "hh:mm:ss" |
|||
Function timeToSecs(t As String) As Integer |
|||
Dim As Integer hours = Val(Left(t, 2)) |
|||
Dim As Integer mins = Val(Mid(t, 4, 2)) |
|||
Dim As Integer secs = Val(Right(t, 2)) |
|||
Return 3600 * hours + 60 * mins + secs |
|||
End Function |
|||
' 1 second of time = 360/(24 * 3600) = 1/240th degree |
|||
Function timeToDegrees(t As String) As Double |
|||
Dim secs As Integer = timeToSecs(t) |
|||
Return secs/240.0 |
|||
End Function |
|||
Function degreesToTime(d As Double) As String |
|||
If d < 0 Then d += 360.0 |
|||
Dim secs As Integer = d * 240.0 |
|||
Dim hours As Integer = secs \ 3600 |
|||
Dim mins As Integer = secs Mod 3600 |
|||
secs = mins Mod 60 |
|||
mins = mins \ 60 |
|||
Dim hBuffer As String = Right("0" + Str(hours), 2) |
|||
Dim mBuffer As String = Right("0" + Str(mins), 2) |
|||
Dim sBuffer As String = Right("0" + Str(secs), 2) |
|||
Return hBuffer + ":" + mBuffer + ":" + sBuffer |
|||
End Function |
|||
Dim tm(1 To 4) As String = {"23:00:17", "23:40:20", "00:12:45", "00:17:19"} |
|||
Dim angles(1 To 4) As Double |
|||
For i As Integer = 1 To 4 |
|||
angles(i) = timeToDegrees(tm(i)) |
|||
Next |
|||
Dim mean As Double = meanAngle(angles()) |
|||
Print "Average time is : "; degreesToTime(mean) |
|||
Print |
|||
Print "Press any key to quit" |
|||
Sleep</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Average time is : 23:47:43 |
|||
</pre> |
</pre> |
||
=={{header|Go}}== |
=={{header|Go}}== |
||
< |
<syntaxhighlight lang="go">package main |
||
import ( |
import ( |
||
Line 467: | Line 1,160: | ||
_, dayFrac := math.Modf(1 + math.Atan2(ssum, csum)/(2*math.Pi)) |
_, dayFrac := math.Modf(1 + math.Atan2(ssum, csum)/(2*math.Pi)) |
||
return mean.Add(time.Duration(dayFrac * 24 * float64(time.Hour))), nil |
return mean.Add(time.Duration(dayFrac * 24 * float64(time.Hour))), nil |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 475: | Line 1,168: | ||
=={{header|Groovy}}== |
=={{header|Groovy}}== |
||
Solution: |
Solution: |
||
< |
<syntaxhighlight lang="groovy">import static java.lang.Math.* |
||
final format = 'HH:mm:ss', clock = PI / 12, millisPerHr = 3600*1000 |
final format = 'HH:mm:ss', clock = PI / 12, millisPerHr = 3600*1000 |
||
Line 485: | Line 1,178: | ||
def times = timeStrings.collect(parseTime) |
def times = timeStrings.collect(parseTime) |
||
formatTime(atan2( mean(times) { sin(it * clock) }, mean(times) { cos(it * clock) }) / clock) |
formatTime(atan2( mean(times) { sin(it * clock) }, mean(times) { cos(it * clock) }) / clock) |
||
}</ |
}</syntaxhighlight> |
||
Test: |
Test: |
||
< |
<syntaxhighlight lang="groovy">println (meanTime("23:00:17", "23:40:20", "00:12:45", "00:17:19"))</syntaxhighlight> |
||
{{out}} |
|||
<pre>23:47:43</pre> |
|||
=={{header|Haskell}}== |
|||
<syntaxhighlight lang="haskell">import Data.Complex (cis, phase) |
|||
import Data.List.Split (splitOn) |
|||
import Text.Printf (printf) |
|||
timeToRadians :: String -> Float |
|||
timeToRadians time = |
|||
let hours:minutes:seconds:_ = splitOn ":" time |
|||
s = fromIntegral (read seconds :: Int) |
|||
m = fromIntegral (read minutes :: Int) |
|||
h = fromIntegral (read hours :: Int) |
|||
in (2*pi)*(h+ (m + s/60.0 )/60.0 )/24.0 |
|||
radiansToTime :: Float -> String |
|||
radiansToTime r = |
|||
let tau = pi*2 |
|||
(_,fDay) = properFraction (r / tau) :: (Int, Float) |
|||
fDayPositive = if fDay < 0 then 1.0+fDay else fDay |
|||
(hours, fHours) = properFraction $ 24.0 * fDayPositive |
|||
(minutes, fMinutes) = properFraction $ 60.0 * fHours |
|||
seconds = 60.0 * fMinutes |
|||
in printf "%0d" (hours::Int) ++ ":" ++ printf "%0d" (minutes::Int) ++ ":" ++ printf "%0.0f" (seconds::Float) |
|||
meanAngle :: [Float] -> Float |
|||
meanAngle = phase . sum . map cis |
|||
main :: IO () |
|||
main = putStrLn $ radiansToTime $ meanAngle $ map timeToRadians ["23:00:17", "23:40:20", "00:12:45", "00:17:19"] |
|||
</syntaxhighlight> |
|||
{{out}} |
{{out}} |
||
<pre>23:47:43</pre> |
<pre>23:47:43</pre> |
||
Line 495: | Line 1,220: | ||
=={{header|Icon}} and {{header|Unicon}}== |
=={{header|Icon}} and {{header|Unicon}}== |
||
<lang>procedure main(A) |
<syntaxhighlight lang="text">procedure main(A) |
||
every put(B := [], ct2a(!A)) |
every put(B := [], ct2a(!A)) |
||
write(ca2t(meanAngle(B))) |
write(ca2t(meanAngle(B))) |
||
Line 518: | Line 1,243: | ||
every (sumCosines := 0.0) +:= cos(dtor(!A)) |
every (sumCosines := 0.0) +:= cos(dtor(!A)) |
||
return rtod(atan(sumSines/*A,sumCosines/*A)) |
return rtod(atan(sumSines/*A,sumCosines/*A)) |
||
end</ |
end</syntaxhighlight> |
||
Sample run: |
Sample run: |
||
Line 530: | Line 1,255: | ||
=={{header|J}}== |
=={{header|J}}== |
||
use <code>avgAngleR</code> from [[Averages/Mean angle#J]] |
use <code>avgAngleR</code> from [[Averages/Mean angle#J]] |
||
< |
<syntaxhighlight lang="j">require 'types/datetime' |
||
parseTimes=: ([: _&".;._2 ,&':');._2 |
parseTimes=: ([: _&".;._2 ,&':');._2 |
||
secsFromTime=: 24 60 60 #. ] NB. convert from time to seconds |
secsFromTime=: 24 60 60 #. ] NB. convert from time to seconds |
||
rft=: 2r86400p1 * secsFromTime NB. convert from time to radians |
rft=: 2r86400p1 * secsFromTime NB. convert from time to radians |
||
meanTime=: 'hh:mm:ss' fmtTime [: secsFromTime [: avgAngleR&.rft parseTimes</ |
meanTime=: 'hh:mm:ss' fmtTime [: secsFromTime [: avgAngleR&.rft parseTimes</syntaxhighlight> |
||
{{out|Example Use}} |
{{out|Example Use}} |
||
< |
<syntaxhighlight lang="j"> meanTime '23:00:17 23:40:20 00:12:45 00:17:19 ' |
||
23:47:43</ |
23:47:43</syntaxhighlight> |
||
=={{header|Java}}== |
|||
{{trans|Kotlin}} |
|||
<syntaxhighlight lang="java">public class MeanTimeOfDay { |
|||
static double meanAngle(double[] angles) { |
|||
int len = angles.length; |
|||
double sinSum = 0.0; |
|||
for (int i = 0; i < len; i++) { |
|||
sinSum += Math.sin(angles[i] * Math.PI / 180.0); |
|||
} |
|||
double cosSum = 0.0; |
|||
for (int i = 0; i < len; i++) { |
|||
cosSum += Math.cos(angles[i] * Math.PI / 180.0); |
|||
} |
|||
return Math.atan2(sinSum / len, cosSum / len) * 180.0 / Math.PI; |
|||
} |
|||
/* time string assumed to be in format "hh:mm:ss" */ |
|||
static int timeToSecs(String t) { |
|||
int hours = Integer.parseInt(t.substring(0, 2)); |
|||
int mins = Integer.parseInt(t.substring(3, 5)); |
|||
int secs = Integer.parseInt(t.substring(6, 8)); |
|||
return 3600 * hours + 60 * mins + secs; |
|||
} |
|||
/* 1 second of time = 360/(24 * 3600) = 1/240th degree */ |
|||
static double timeToDegrees(String t) { |
|||
return timeToSecs(t) / 240.0; |
|||
} |
|||
static String degreesToTime(double d) { |
|||
if (d < 0.0) d += 360.0; |
|||
int secs = (int)(d * 240.0); |
|||
int hours = secs / 3600; |
|||
int mins = secs % 3600; |
|||
secs = mins % 60; |
|||
mins /= 60; |
|||
return String.format("%2d:%2d:%2d", hours, mins, secs); |
|||
} |
|||
public static void main(String[] args) { |
|||
String[] tm = {"23:00:17", "23:40:20", "00:12:45", "00:17:19"}; |
|||
double[] angles = new double[4]; |
|||
for (int i = 0; i < 4; i++) angles[i] = timeToDegrees(tm[i]); |
|||
double mean = meanAngle(angles); |
|||
System.out.println("Average time is : " + degreesToTime(mean)); |
|||
} |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Average time is : 23:47:43 |
|||
</pre> |
|||
=={{header|Javascript}}== |
|||
{{works with|Node.js}} |
|||
<syntaxhighlight lang="javascript">var args = process.argv.slice(2); |
|||
function time_to_seconds( hms ) { |
|||
var parts = hms.split(':'); |
|||
var h = parseInt(parts[0]); |
|||
var m = parseInt(parts[1]); |
|||
var s = parseInt(parts[2]); |
|||
if ( h < 12 ) { |
|||
h += 24; |
|||
} |
|||
var seconds = parseInt(parts[0]) * 60 * 60 + parseInt(parts[1]) * 60 + parseInt(parts[2]); |
|||
return seconds; |
|||
} |
|||
function seconds_to_time( s ) { |
|||
var h = Math.floor( s/(60 * 60) ); |
|||
if ( h < 10 ) { |
|||
h = '0' + h; |
|||
} |
|||
s = s % (60 * 60); |
|||
var m = Math.floor( s/60 ); |
|||
if ( m < 10 ) { |
|||
m = '0' + m; |
|||
} |
|||
s = s % 60 |
|||
if ( s < 10 ) { |
|||
s = '0' + s; |
|||
} |
|||
return h + ':' + m + ':' + s; |
|||
} |
|||
var sum = 0, count = 0, idx; |
|||
for (idx in args) { |
|||
var seconds = time_to_seconds( args[idx] ); |
|||
sum += seconds; |
|||
count++; |
|||
} |
|||
var seconds = Math.floor( sum / count ) |
|||
console.log( 'Mean time is ', seconds_to_time(seconds)); |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
$ node mean_time.js 23:00:17 23:40:20 00:12:45 00:17:19 |
|||
Mean time is 23:47:40</pre> |
|||
=={{header|jq}}== |
|||
{{works with|jq|1.4}} |
|||
The "mean time" of two times that differ by 12 hours (e.g. ["00:00:00", "12:00:00"]) is not very well-defined, and is accordingly computed as null here. |
|||
<syntaxhighlight lang="jq"># input: array of "h:m:s" |
|||
def mean_time_of_day: |
|||
def pi: 4 * (1|atan); |
|||
def to_radians: pi * . /(12*60*60); |
|||
def from_radians: (. * 12*60*60) / pi; |
|||
def secs2time: # produce "hh:mm:ss" string |
|||
def pad: tostring | (2 - length) * "0" + .; |
|||
"\(./60/60 % 24 | pad):\(./60 % 60 | pad):\(. % 60 | pad)"; |
|||
def round: |
|||
if . < 0 then -1 * ((- .) | round) | if . == -0 then 0 else . end |
|||
else floor as $x |
|||
| if (. - $x) < 0.5 then $x else $x+1 end |
|||
end; |
|||
map( split(":") |
|||
| map(tonumber) |
|||
| (.[0]*3600 + .[1]*60 + .[2]) |
|||
| to_radians ) |
|||
| (map(sin) | add) as $y |
|||
| (map(cos) | add) as $x |
|||
| if $x == 0 then (if $y > 3e-14 then pi/2 elif $y < -3e-14 then -(pi/2) else null end) |
|||
else ($y / $x) | atan |
|||
end |
|||
| if . == null then null |
|||
else from_radians |
|||
| if (.<0) then . + (24*60*60) else . end |
|||
| round |
|||
| secs2time |
|||
end ;</syntaxhighlight> |
|||
'''Examples''' |
|||
<syntaxhighlight lang="jq">["0:0:0", "12:0:0" ], |
|||
["0:0:0", "24:0:0" ], |
|||
["1:0:0", "1:0:0" ], |
|||
["20:0:0", "4:0:0" ], |
|||
["20:0:0", "4:0:2" ], |
|||
["23:0:0", "23:0:0" ], |
|||
["23:00:17", "23:40:20", "00:12:45", "00:17:19"] |
|||
| mean_time_of_day</syntaxhighlight> |
|||
{{out}} |
|||
<syntaxhighlight lang="sh">$ jq -r -n -f Mean_time_of_day.jq |
|||
null |
|||
00:00:00 |
|||
01:00:00 |
|||
00:00:00 |
|||
00:00:01 |
|||
23:00:00 |
|||
23:47:43</syntaxhighlight> |
|||
=={{header|Julia}}== |
|||
{{works with|Julia|0.6}} |
|||
{{trans|MATLAB}} |
|||
<syntaxhighlight lang="julia">using Statistics |
|||
function meantime(times::Array, dlm::String=":") |
|||
c = π / (12 * 60 * 60) |
|||
a = map(x -> parse.(Int, x), split.(times, dlm)) |
|||
ϕ = collect(3600t[1] + 60t[2] + t[3] for t in a) |
|||
d = angle(mean(exp.(c * im * ϕ))) / 2π # days |
|||
if d < 0 d += 1 end |
|||
# Convert to h:m:s |
|||
h = trunc(Int, d * 24) |
|||
m = trunc(Int, d * 24 * 60) - h * 60 |
|||
s = trunc(Int, d * 24 * 60 * 60) - h * 60 * 60 - m * 60 |
|||
return "$h:$m:$s" |
|||
end |
|||
times = String["23:00:17", "23:40:20", "00:12:45", "00:17:19"] |
|||
mtime = meantime(times) |
|||
println("Times:") |
|||
println.(times) |
|||
println("Mean: $mtime")</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Times: |
|||
23:00:17 |
|||
23:40:20 |
|||
00:12:45 |
|||
00:17:19 |
|||
Mean: 23:47:43</pre> |
|||
=={{header|Kotlin}}== |
|||
{{trans|FreeBASIC}} |
|||
<syntaxhighlight lang="scala">// version 1.0.6 |
|||
fun meanAngle(angles: DoubleArray): Double { |
|||
val sinSum = angles.sumByDouble { Math.sin(it * Math.PI / 180.0) } |
|||
val cosSum = angles.sumByDouble { Math.cos(it * Math.PI / 180.0) } |
|||
return Math.atan2(sinSum / angles.size, cosSum / angles.size) * 180.0 / Math.PI |
|||
} |
|||
/* time string assumed to be in format "hh:mm:ss" */ |
|||
fun timeToSecs(t: String): Int { |
|||
val hours = t.slice(0..1).toInt() |
|||
val mins = t.slice(3..4).toInt() |
|||
val secs = t.slice(6..7).toInt() |
|||
return 3600 * hours + 60 * mins + secs |
|||
} |
|||
/* 1 second of time = 360/(24 * 3600) = 1/240th degree */ |
|||
fun timeToDegrees(t: String): Double = timeToSecs(t) / 240.0 |
|||
fun degreesToTime(d: Double): String { |
|||
var dd = d |
|||
if (dd < 0.0) dd += 360.0 |
|||
var secs = (dd * 240.0).toInt() |
|||
val hours = secs / 3600 |
|||
var mins = secs % 3600 |
|||
secs = mins % 60 |
|||
mins /= 60 |
|||
return String.format("%2d:%2d:%2d", hours, mins, secs) |
|||
} |
|||
fun main(args: Array<String>) { |
|||
val tm = arrayOf("23:00:17", "23:40:20", "00:12:45", "00:17:19") |
|||
val angles = DoubleArray(4) { timeToDegrees(tm[it]) } |
|||
val mean = meanAngle(angles) |
|||
println("Average time is : ${degreesToTime(mean)}") |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Average time is : 23:47:43 |
|||
</pre> |
|||
=={{header|Liberty BASIC}}== |
=={{header|Liberty BASIC}}== |
||
<syntaxhighlight lang="lb"> |
|||
<lang lb> |
|||
global pi |
global pi |
||
pi = acs(-1) |
pi = acs(-1) |
||
Line 586: | Line 1,545: | ||
atan2 = (y=0)*(x<0)*pi |
atan2 = (y=0)*(x<0)*pi |
||
End Function |
End Function |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
Line 598: | Line 1,557: | ||
</pre> |
</pre> |
||
=={{header| |
=={{header|Lua}}== |
||
<syntaxhighlight lang="lua"> |
|||
<lang mathematica>meanTime[list_] := |
|||
local times = {"23:00:17","23:40:20","00:12:45","00:17:19"} |
|||
-- returns time converted to a radian format |
|||
local function timeToAngle(str) |
|||
local h,m,s = str:match("(..):(..):(..)") |
|||
return (h + m / 60 + s / 3600)/12 * math.pi |
|||
end |
|||
-- computes the mean of the angles inside a list |
|||
local function meanAngle(angles) |
|||
local sumSin,sumCos = 0,0 |
|||
for k,v in pairs(angles) do |
|||
sumSin = sumSin + math.sin(v) |
|||
sumCos = sumCos + math.cos(v) |
|||
end |
|||
return math.atan2(sumSin,sumCos) |
|||
end |
|||
-- converts and angle back to a time string |
|||
local function angleToTime(angle) |
|||
local abs = angle % (math.pi * 2) |
|||
local time = abs / math.pi * 12 |
|||
local h = math.floor(time) |
|||
local m = math.floor(time * 60) % 60 |
|||
local s = math.floor(time * 3600) % 60 |
|||
return string.format("%02d:%02d:%02d", h, m, s) |
|||
end |
|||
-- convert times to angles |
|||
for k,v in pairs(times) do |
|||
times[k] = timeToAngle(v) |
|||
end |
|||
print(angleToTime(meanAngle(times))) |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
23:47:43 |
|||
</pre> |
|||
=={{header|Mathematica}} / {{header|Wolfram Language}}== |
|||
<syntaxhighlight lang="mathematica">meanTime[list_] := |
|||
StringJoin@ |
StringJoin@ |
||
Riffle[ToString /@ |
Riffle[ToString /@ |
||
Line 606: | Line 1,608: | ||
Exp[FromDigits[ToExpression@StringSplit[#, ":"], 60] & /@ |
Exp[FromDigits[ToExpression@StringSplit[#, ":"], 60] & /@ |
||
list/(24*60*60) 2 Pi I]]]/(2 Pi)], ":"]; |
list/(24*60*60) 2 Pi I]]]/(2 Pi)], ":"]; |
||
meanTime[{"23:00:17", "23:40:20", "00:12:45", "00:17:19"}]</ |
meanTime[{"23:00:17", "23:40:20", "00:12:45", "00:17:19"}]</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
<pre>23:47:43</pre> |
<pre>23:47:43</pre> |
||
=={{header|MATLAB}} / {{header|Octave}}== |
=={{header|MATLAB}} / {{header|Octave}}== |
||
< |
<syntaxhighlight lang="matlab">function t = mean_time_of_day(t) |
||
c = pi/(12*60*60); |
c = pi/(12*60*60); |
||
for k=1:length(t) |
for k=1:length(t) |
||
Line 620: | Line 1,622: | ||
if (d<0) d += 1; |
if (d<0) d += 1; |
||
t = datestr(d,"HH:MM:SS"); |
t = datestr(d,"HH:MM:SS"); |
||
end; </ |
end; </syntaxhighlight> |
||
<pre>mean_time_of_day({'23:00:17', '23:40:20', '00:12:45', '00:17:19'}) |
<pre>mean_time_of_day({'23:00:17', '23:40:20', '00:12:45', '00:17:19'}) |
||
ans = 23:47:43 |
ans = 23:47:43 |
||
Line 626: | Line 1,628: | ||
=={{header|Nim}}== |
=={{header|Nim}}== |
||
{{works with|Nim|0.20.0+}} |
|||
<lang nim>import math, complex, strutils |
|||
<syntaxhighlight lang="nim">import math, complex, strutils, sequtils |
|||
proc rect(r, phi): Complex = (r * cos(phi), sin(phi)) |
|||
proc |
proc meanAngle(deg: openArray[float]): float = |
||
var c: Complex[float] |
|||
proc radians(x): float = (x * Pi) / 180.0 |
|||
proc degrees(x): float = (x * 180.0) / Pi |
|||
proc meanAngle(deg): float = |
|||
var c: Complex |
|||
for d in deg: |
for d in deg: |
||
c += rect(1.0, |
c += rect(1.0, degToRad(d)) |
||
radToDeg(phase(c / float(deg.len))) |
|||
proc meanTime(times): string = |
proc meanTime(times: openArray[string]): string = |
||
const day = 24 * 60 * 60 |
const day = 24 * 60 * 60 |
||
let |
let |
||
Line 648: | Line 1,645: | ||
ms = (angles.meanAngle * day / 360 + day) mod day |
ms = (angles.meanAngle * day / 360 + day) mod day |
||
(h,m,s) = (ms.int div 3600, (ms.int mod 3600) div 60, ms.int mod 60) |
(h,m,s) = (ms.int div 3600, (ms.int mod 3600) div 60, ms.int mod 60) |
||
align($h, 2, '0') &":"& align($m, 2, '0') &":"& align($s, 2, '0') |
align($h, 2, '0') & ":" & align($m, 2, '0') & ":" & align($s, 2, '0') |
||
echo meanTime(["23:00:17", "23:40:20", "00:12:45", "00:17:19"])</ |
echo meanTime(["23:00:17", "23:40:20", "00:12:45", "00:17:19"])</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>23:47:43</pre> |
<pre>23:47:43</pre> |
||
=={{header|Oberon-2}}== |
|||
{{works with|oo2c}} |
|||
<syntaxhighlight lang="oberon2"> |
|||
MODULE AvgTimeOfDay; |
|||
IMPORT |
|||
M := LRealMath, |
|||
T := NPCT:Tools, |
|||
Out := NPCT:Console; |
|||
CONST |
|||
secsDay = 86400; |
|||
secsHour = 3600; |
|||
secsMin = 60; |
|||
toRads = M.pi / 180; |
|||
VAR |
|||
h,m,s: LONGINT; |
|||
data: ARRAY 4 OF LONGREAL; |
|||
PROCEDURE TimeToDeg(time: STRING): LONGREAL; |
|||
VAR |
|||
parts: ARRAY 3 OF STRING; |
|||
h,m,s: LONGREAL; |
|||
BEGIN |
|||
T.Split(time,':',parts); |
|||
h := T.StrToInt(parts[0]); |
|||
m := T.StrToInt(parts[1]); |
|||
s := T.StrToInt(parts[2]); |
|||
RETURN (h * secsHour + m * secsMin + s) * 360 / secsDay; |
|||
END TimeToDeg; |
|||
PROCEDURE DegToTime(d: LONGREAL; VAR h,m,s: LONGINT); |
|||
VAR |
|||
ds: LONGREAL; |
|||
PROCEDURE Mod(x,y: LONGREAL): LONGREAL; |
|||
VAR |
|||
c: LONGREAL; |
|||
BEGIN |
|||
c := ENTIER(x / y); |
|||
RETURN x - c * y |
|||
END Mod; |
|||
BEGIN |
|||
ds := Mod(d,360.0) * secsDay / 360.0; |
|||
h := ENTIER(ds / secsHour); |
|||
m := ENTIER(Mod(ds,secsHour) / secsMin); |
|||
s := ENTIER(Mod(ds,secsMin)); |
|||
END DegToTime; |
|||
PROCEDURE Mean(g: ARRAY OF LONGREAL): LONGREAL; |
|||
VAR |
|||
i,l: LONGINT; |
|||
sumSin, sumCos: LONGREAL; |
|||
BEGIN |
|||
i := 0;l := LEN(g);sumSin := 0.0;sumCos := 0.0; |
|||
WHILE i < l DO |
|||
sumSin := sumSin + M.sin(g[i] * toRads); |
|||
sumCos := sumCos + M.cos(g[i] * toRads); |
|||
INC(i) |
|||
END; |
|||
RETURN M.arctan2(sumSin / l,sumCos / l) * 180 / M.pi; |
|||
END Mean; |
|||
BEGIN |
|||
data[0] := TimeToDeg("23:00:17"); |
|||
data[1] := TimeToDeg("23:40:20"); |
|||
data[2] := TimeToDeg("00:12:45"); |
|||
data[3] := TimeToDeg("00:17:19"); |
|||
DegToTime(Mean(data),h,m,s); |
|||
Out.String(":> ");Out.Int(h,0);Out.Char(':');Out.Int(m,0);Out.Char(':');Out.Int(s,0);Out.Ln |
|||
END AvgTimeOfDay. |
|||
</syntaxhighlight> |
|||
{{Out}} |
|||
<pre> |
|||
:> 23:47:43 |
|||
</pre> |
|||
=={{header|OCaml}}== |
=={{header|OCaml}}== |
||
< |
<syntaxhighlight lang="ocaml">let pi_twice = 2.0 *. 3.14159_26535_89793_23846_2643 |
||
let day = float (24 * 60 * 60) |
let day = float (24 * 60 * 60) |
||
Line 692: | Line 1,768: | ||
Printf.printf "The mean time of [%s] is: %s\n" |
Printf.printf "The mean time of [%s] is: %s\n" |
||
(String.concat "; " times) |
(String.concat "; " times) |
||
(string_of_time (mean_time (List.map parse_time times)))</ |
(string_of_time (mean_time (List.map parse_time times)))</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
The mean time of [23:00:17; 23:40:20; 00:12:45; 00:17:19] is: 23:47:43 |
The mean time of [23:00:17; 23:40:20; 00:12:45; 00:17:19] is: 23:47:43 |
||
=={{header|ooRexx}}== |
=={{header|ooRexx}}== |
||
< |
<syntaxhighlight lang="oorexx">/* REXX --------------------------------------------------------------- |
||
* 25.06.2014 Walter Pachl |
* 25.06.2014 Walter Pachl |
||
*--------------------------------------------------------------------*/ |
*--------------------------------------------------------------------*/ |
||
Line 732: | Line 1,808: | ||
f2: return right(format(arg(1),2,0),2,0) |
f2: return right(format(arg(1),2,0),2,0) |
||
::requires rxmath library</ |
::requires rxmath library</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>23:47:43</pre> |
<pre>23:47:43</pre> |
||
=={{header|PARI/GP}}== |
=={{header|PARI/GP}}== |
||
< |
<syntaxhighlight 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(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]])</ |
meanTime([[23,0,17], [23,40,20], [0,12,45], [0,17,19]])</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>[23, 47, 43]</pre> |
<pre>[23, 47, 43]</pre> |
||
=={{header|Perl |
=={{header|Perl}}== |
||
===Traditional=== |
|||
<lang perl6>sub tod2rad($_) { [+](.comb(/\d+/) Z* 3600,60,1) * pi / 43200 } |
|||
Using the core module <code>Math::Complex</code> to enable use of complex numbers. The <code>POSIX</code> CPAN module provides the <code>fmod</code> routine for non-integer modulus calculations. |
|||
{{trans|Raku}} |
|||
<syntaxhighlight lang="perl">use strict; |
|||
use warnings; |
|||
use POSIX 'fmod'; |
|||
use Math::Complex; |
|||
use List::Util qw(sum); |
|||
use utf8; |
|||
use constant τ => 2 * 3.1415926535; |
|||
sub rad2tod ($r) { |
|||
my $x = $r * 43200 / pi; |
|||
# time-of-day to radians |
|||
(($x xx 3 Z/ 3600,60,1) Z% 24,60,60).fmt('%02d',':'); |
|||
sub tod2rad { |
|||
($h,$m,$s) = split /:/, @_[0]; |
|||
(3600*$h + 60*$m + $s) * τ / 86400; |
|||
} |
} |
||
# radians to time-of-day |
|||
sub phase ($c) { $c.polar[1] } |
|||
sub rad2tod { |
|||
my $x = $_[0] * 86400 / τ; |
|||
sprintf '%02d:%02d:%02d', fm($x/3600,24), fm($x/60,60), fm($x,60); |
|||
} |
|||
# float modulus, normalized to positive values |
|||
sub mean-time (@t) { rad2tod phase [+] map { cis tod2rad $_ }, @t } |
|||
sub fm { |
|||
my($n,$b) = @_; |
|||
$x = fmod($n,$b); |
|||
$x += $b if $x < 0; |
|||
} |
|||
sub phase { arg($_[0]) } # aka theta |
|||
sub cis { cos($_[0]) + i*sin($_[0]) } |
|||
sub mean_time { rad2tod phase sum map { cis tod2rad $_ } @_ } |
|||
@times = ("23:00:17", "23:40:20", "00:12:45", "00:17:19"); |
|||
say mean-time($_).fmt("%s is the mean time of "), $_ for |
|||
print mean_time(@times) . " is the mean time of " . join(' ', @times) . "\n";</syntaxhighlight> |
|||
["23:00:17", "23:40:20", "00:12:45", "00:17:19"];</lang> |
|||
{{out}} |
{{out}} |
||
<pre>23:47:43 is the mean time of 23:00:17 23:40:20 00:12:45 00:17:19</pre> |
<pre>23:47:43 is the mean time of 23:00:17 23:40:20 00:12:45 00:17:19</pre> |
||
===v5.36=== |
|||
As previous, but using features from an up-to-date release of Perl, e.g. strict/warn/subroutine signatures without the <code>use</code> boilerplate. |
|||
<syntaxhighlight lang="perl">use v5.36; |
|||
use POSIX 'fmod'; |
|||
use Math::Complex; |
|||
use List::Util 'sum'; |
|||
use utf8; |
|||
use constant τ => 2 * 2 * atan2(1, 0); |
|||
sub R_to_ToD ($radians) { my $x = $radians * 86400 / τ; sprintf '%02d:%02d:%02d', fm($x/3600,24), fm($x/60,60), fm($x,60) } |
|||
sub ToD_to_R ($h,$m,$s) { (3600*$h + 60*$m + $s) * τ / 86400 } |
|||
sub fm ($n,$b) { my $x = fmod($n,$b); $x += $b if $x < 0 } |
|||
sub cis ($radians) { cos($radians) + i*sin($radians) } |
|||
sub phase ($Θ) { arg( $Θ ) } |
|||
sub mean_time(@t) { R_to_ToD phase sum map { cis ToD_to_R split ':', $_ } @t } |
|||
my @times = <23:00:17 23:40:20 00:12:45 00:17:19>; |
|||
say my $result = mean_time(@times) . ' is the mean time of ' . join ' ', @times;</syntaxhighlight> |
|||
{{out}} |
|||
<pre>23:47:43 is the mean time of 23:00:17 23:40:20 00:12:45 00:17:19</pre> |
|||
=={{header|Phix}}== |
|||
<!--<syntaxhighlight lang="phix">(phixonline)--> |
|||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">MeanAngle</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">angles</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #004080;">atom</span> <span style="color: #000000;">x</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">y</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">angles</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span> |
|||
<span style="color: #004080;">atom</span> <span style="color: #000000;">ai_rad</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">angles</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]*</span><span style="color: #004600;">PI</span><span style="color: #0000FF;">/</span><span style="color: #000000;">180</span> |
|||
<span style="color: #000000;">x</span> <span style="color: #0000FF;">+=</span> <span style="color: #7060A8;">cos</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ai_rad</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000000;">y</span> <span style="color: #0000FF;">+=</span> <span style="color: #7060A8;">sin</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ai_rad</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">abs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)<</span><span style="color: #000000;">1e-16</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #008000;">"not meaningful"</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #7060A8;">atan2</span><span style="color: #0000FF;">(</span><span style="color: #000000;">y</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">180</span><span style="color: #0000FF;">/</span><span style="color: #004600;">PI</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">toSecAngle</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">hours</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">minutes</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">seconds</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #0000FF;">((</span><span style="color: #000000;">hours</span><span style="color: #0000FF;">*</span><span style="color: #000000;">60</span><span style="color: #0000FF;">+</span><span style="color: #000000;">minutes</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">60</span><span style="color: #0000FF;">+</span><span style="color: #000000;">seconds</span><span style="color: #0000FF;">)/(</span><span style="color: #000000;">24</span><span style="color: #0000FF;">*</span><span style="color: #000000;">60</span><span style="color: #0000FF;">*</span><span style="color: #000000;">60</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">360</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<span style="color: #008080;">constant</span> <span style="color: #000000;">Times</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">toSecAngle</span><span style="color: #0000FF;">(</span><span style="color: #000000;">23</span><span style="color: #0000FF;">,</span><span style="color: #000000;">00</span><span style="color: #0000FF;">,</span><span style="color: #000000;">17</span><span style="color: #0000FF;">),</span> |
|||
<span style="color: #000000;">toSecAngle</span><span style="color: #0000FF;">(</span><span style="color: #000000;">23</span><span style="color: #0000FF;">,</span><span style="color: #000000;">40</span><span style="color: #0000FF;">,</span><span style="color: #000000;">20</span><span style="color: #0000FF;">),</span> |
|||
<span style="color: #000000;">toSecAngle</span><span style="color: #0000FF;">(</span><span style="color: #000000;">00</span><span style="color: #0000FF;">,</span><span style="color: #000000;">12</span><span style="color: #0000FF;">,</span><span style="color: #000000;">45</span><span style="color: #0000FF;">),</span> |
|||
<span style="color: #000000;">toSecAngle</span><span style="color: #0000FF;">(</span><span style="color: #000000;">00</span><span style="color: #0000FF;">,</span><span style="color: #000000;">17</span><span style="color: #0000FF;">,</span><span style="color: #000000;">19</span><span style="color: #0000FF;">)}</span> |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">toHMS</span><span style="color: #0000FF;">(</span><span style="color: #004080;">object</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #004080;">string</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">s</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">+=</span><span style="color: #000000;">360</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">24</span><span style="color: #0000FF;">*</span><span style="color: #000000;">60</span><span style="color: #0000FF;">*</span><span style="color: #000000;">60</span><span style="color: #0000FF;">*</span><span style="color: #000000;">s</span><span style="color: #0000FF;">/</span><span style="color: #000000;">360</span> |
|||
<span style="color: #004080;">atom</span> <span style="color: #000000;">hours</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">/</span><span style="color: #000000;">3600</span><span style="color: #0000FF;">),</span> |
|||
<span style="color: #000000;">mins</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3600</span><span style="color: #0000FF;">)/</span><span style="color: #000000;">60</span><span style="color: #0000FF;">),</span> |
|||
<span style="color: #000000;">secs</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">60</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%02d:%02d:%02d"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">hours</span><span style="color: #0000FF;">,</span><span style="color: #000000;">mins</span><span style="color: #0000FF;">,</span><span style="color: #000000;">secs</span><span style="color: #0000FF;">})</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #000000;">s</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Mean Time is %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">toHMS</span><span style="color: #0000FF;">(</span><span style="color: #000000;">MeanAngle</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Times</span><span style="color: #0000FF;">))})</span> |
|||
<!--</syntaxhighlight>--> |
|||
{{out}} |
|||
<pre> |
|||
Mean Time is 23:47:43 |
|||
</pre> |
|||
=={{header|PHP}}== |
|||
<syntaxhighlight lang="php"> |
|||
<?php |
|||
function time2ang($tim) { |
|||
if (!is_string($tim)) return $tim; |
|||
$parts = explode(':',$tim); |
|||
if (count($parts)!=3) return $tim; |
|||
$sec = ($parts[0]*3600)+($parts[1]*60)+$parts[2]; |
|||
$ang = 360.0 * ($sec/86400.0); |
|||
return $ang; |
|||
} |
|||
function ang2time($ang) { |
|||
if (!is_numeric($ang)) return $ang; |
|||
$sec = 86400.0 * $ang / 360.0; |
|||
$parts = array(floor($sec/3600),floor(($sec % 3600)/60),$sec % 60); |
|||
$tim = sprintf('%02d:%02d:%02d',$parts[0],$parts[1],$parts[2]); |
|||
return $tim; |
|||
} |
|||
function meanang($ang) { |
|||
if (!is_array($ang)) return $ang; |
|||
$sins = 0.0; |
|||
$coss = 0.0; |
|||
foreach($ang as $a) { |
|||
$sins += sin(deg2rad($a)); |
|||
$coss += cos(deg2rad($a)); |
|||
} |
|||
$avgsin = $sins / (0.0+count($ang)); |
|||
$avgcos = $coss / (0.0+count($ang)); |
|||
$avgang = rad2deg(atan2($avgsin,$avgcos)); |
|||
while ($avgang < 0.0) $avgang += 360.0; |
|||
return $avgang; |
|||
} |
|||
$bats = array('23:00:17','23:40:20','00:12:45','00:17:19'); |
|||
$angs = array(); |
|||
foreach ($bats as $t) $angs[] = time2ang($t); |
|||
$ma = meanang($angs); |
|||
$result = ang2time($ma); |
|||
print "The mean time of day is $result (angle $ma).\n"; |
|||
?> |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
The mean time of day is 23:47:43 (angle 356.9306730355). |
|||
</pre> |
|||
=={{header|PicoLisp}}== |
=={{header|PicoLisp}}== |
||
< |
<syntaxhighlight lang="picolisp">(load "@lib/math.l") |
||
(de meanTime (Lst) |
(de meanTime (Lst) |
||
Line 770: | Line 1,979: | ||
(sum '((S) (cos (*/ ($tim S) pi 43200))) Lst) ) |
(sum '((S) (cos (*/ ($tim S) pi 43200))) Lst) ) |
||
43200 pi ) |
43200 pi ) |
||
(tim$ (% (+ Tim 86400) 86400) T) ) )</ |
(tim$ (% (+ Tim 86400) 86400) T) ) )</syntaxhighlight> |
||
{{out|Test}} |
{{out|Test}} |
||
< |
<syntaxhighlight lang="picolisp">: (meanTime '("23:00:17" "23:40:20" "00:12:45" "00:17:19")) |
||
-> "23:47:43"</ |
-> "23:47:43"</syntaxhighlight> |
||
=={{header|PL/I}}== |
=={{header|PL/I}}== |
||
< |
<syntaxhighlight lang="pli">*process source attributes xref; |
||
avt: Proc options(main); |
avt: Proc options(main); |
||
/*-------------------------------------------------------------------- |
/*-------------------------------------------------------------------- |
||
Line 821: | Line 2,030: | ||
End; |
End; |
||
End;</ |
End;</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>23:47:43</pre> |
<pre>23:47:43</pre> |
||
=={{header|PowerShell}}== |
|||
<syntaxhighlight lang="powershell"> |
|||
function Get-MeanTimeOfDay |
|||
{ |
|||
[CmdletBinding()] |
|||
[OutputType([timespan])] |
|||
Param |
|||
( |
|||
[Parameter(Mandatory=$true, |
|||
ValueFromPipeline=$true, |
|||
ValueFromPipelineByPropertyName=$true)] |
|||
[ValidatePattern("(?:2[0-3]|[01]?[0-9])[:.][0-5]?[0-9][:.][0-5]?[0-9]")] |
|||
[string[]] |
|||
$Time |
|||
) |
|||
Begin |
|||
{ |
|||
[double[]]$angles = @() |
|||
function ConvertFrom-Time ([timespan]$Time) |
|||
{ |
|||
[double]((360 * $Time.Hours / 24) + (360 * $Time.Minutes / (24 * 60)) + (360 * $Time.Seconds / (24 * 3600))) |
|||
} |
|||
function ConvertTo-Time ([double]$Angle) |
|||
{ |
|||
$t = New-TimeSpan -Hours ([int](24 * 60 * 60 * $Angle / 360) / 3600) ` |
|||
-Minutes (([int](24 * 60 * 60 * $Angle / 360) % 3600 - [int](24 * 60 * 60 * $Angle / 360) % 60) / 60) ` |
|||
-Seconds ([int]((24 * 60 * 60 * $Angle / 360) % 60)) |
|||
if ($t.Days -gt 0) |
|||
{ |
|||
return ($t - (New-TimeSpan -Hours 1)) |
|||
} |
|||
$t |
|||
} |
|||
function Get-MeanAngle ([double[]]$Angles) |
|||
{ |
|||
[double]$x,$y = 0 |
|||
for ($i = 0; $i -lt $Angles.Count; $i++) |
|||
{ |
|||
$x += [Math]::Cos($Angles[$i] * [Math]::PI / 180) |
|||
$y += [Math]::Sin($Angles[$i] * [Math]::PI / 180) |
|||
} |
|||
$result = [Math]::Atan2(($y / $Angles.Count), ($x / $Angles.Count)) * 180 / [Math]::PI |
|||
if ($result -lt 0) |
|||
{ |
|||
return ($result + 360) |
|||
} |
|||
$result |
|||
} |
|||
} |
|||
Process |
|||
{ |
|||
$angles += ConvertFrom-Time $_ |
|||
} |
|||
End |
|||
{ |
|||
ConvertTo-Time (Get-MeanAngle $angles) |
|||
} |
|||
} |
|||
</syntaxhighlight> |
|||
<syntaxhighlight lang="powershell"> |
|||
[timespan]$meanTimeOfDay = "23:00:17","23:40:20","00:12:45","00:17:19" | Get-MeanTimeOfDay |
|||
"Mean time is {0}" -f (Get-Date $meanTimeOfDay.ToString()).ToString("hh:mm:ss tt") |
|||
</syntaxhighlight> |
|||
{{Out}} |
|||
<pre> |
|||
Mean time is 11:47:43 PM |
|||
</pre> |
|||
=={{header|Python}}== |
=={{header|Python}}== |
||
< |
<syntaxhighlight lang="python">from cmath import rect, phase |
||
from math import radians, degrees |
from math import radians, degrees |
||
Line 849: | Line 2,136: | ||
if __name__ == '__main__': |
if __name__ == '__main__': |
||
print( mean_time(["23:00:17", "23:40:20", "00:12:45", "00:17:19"]) )</ |
print( mean_time(["23:00:17", "23:40:20", "00:12:45", "00:17:19"]) )</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>23:47:43</pre> |
<pre>23:47:43</pre> |
||
=={{header|Racket}}== |
=={{header|Racket}}== |
||
< |
<syntaxhighlight lang="racket"> |
||
#lang racket |
#lang racket |
||
(define (mean-angle/radians as) |
(define (mean-angle/radians as) |
||
Line 875: | Line 2,162: | ||
(loop q (cons (~r r #:min-width 2 #:pad-string "0") ts)))))) |
(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")) |
(mean-time '("23:00:17" "23:40:20" "00:12:45" "00:17:19")) |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre>"23:47:43"</pre> |
<pre>"23:47:43"</pre> |
||
=={{header|Raku}}== |
|||
(formerly Perl 6) |
|||
{{works with|Rakudo|2015.12}} |
|||
<syntaxhighlight lang="raku" line>sub tod2rad($_) { [+](.comb(/\d+/) Z* 3600,60,1) * tau / 86400 } |
|||
sub rad2tod ($r) { |
|||
my $x = $r * 86400 / tau; |
|||
(($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 } |
|||
my @times = ["23:00:17", "23:40:20", "00:12:45", "00:17:19"]; |
|||
say "{ mean-time(@times) } is the mean time of @times[]";</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
23:47:43 is the mean time of 23:00:17 23:40:20 00:12:45 00:17:19 |
|||
</pre> |
|||
=={{header|REXX}}== |
=={{header|REXX}}== |
||
< |
<syntaxhighlight lang="rexx">/* REXX --------------------------------------------------------------- |
||
* 25.06.2014 Walter Pachl |
* 25.06.2014 Walter Pachl |
||
* taken from ooRexx using my very aged sin/cos/artan functions |
* taken from ooRexx using my very aged sin/cos/artan functions |
||
Line 980: | Line 2,290: | ||
End |
End |
||
Numeric Digits (prec) |
Numeric Digits (prec) |
||
Return r+0</ |
Return r+0</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>23:47:43</pre> |
<pre>23:47:43</pre> |
||
=={{header|RPL}}== |
|||
{{works with|Halcyon Calc|4.2.7}} |
|||
≪ → angles |
|||
≪ 0 1 angles SIZE '''FOR''' j |
|||
1 angles j GET R→C P→R + '''NEXT''' |
|||
angles SIZE / ARG |
|||
≫ ≫ ''''MEANG'''' STO |
|||
≪ → times |
|||
≪ { } 1 times SIZE '''FOR''' j |
|||
1 times j GET HMS→ 15 * + '''NEXT''' |
|||
'''MEANG''' 15 / 24 MOD →HMS 4 FIX RND STD |
|||
≫ ≫ ''''MTIME'''' STO |
|||
{23.0017 23.4020 0.1245 0.1719 } '''MTIME''' |
|||
{{out}} |
|||
<pre> |
|||
1: 23.4743 |
|||
</pre> |
|||
=={{header|Ruby}}== |
=={{header|Ruby}}== |
||
Using the methods at [[http://rosettacode.org/wiki/Averages/Mean_angle#Ruby|Averages/Mean angle]] |
Using the methods at [[http://rosettacode.org/wiki/Averages/Mean_angle#Ruby|Averages/Mean angle]] |
||
< |
<syntaxhighlight lang="ruby">def time2deg(t) |
||
raise "invalid time" unless m = t.match(/^(\d\d):(\d\d):(\d\d)$/) |
raise "invalid time" unless m = t.match(/^(\d\d):(\d\d):(\d\d)$/) |
||
hh,mm,ss = m[1..3].map {|e| e.to_i} |
hh,mm,ss = m[1..3].map {|e| e.to_i} |
||
Line 1,005: | Line 2,335: | ||
end |
end |
||
puts mean_time ["23:00:17", "23:40:20", "00:12:45", "00:17:19"]</ |
puts mean_time ["23:00:17", "23:40:20", "00:12:45", "00:17:19"]</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
23:47:43 |
23:47:43 |
||
=={{header|Run BASIC}}== |
|||
<syntaxhighlight lang="runbasic">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) |
|||
if y <> 0 then |
|||
atan2 = (2 * (atn((sqr((x * x) + (y * y)) - x)/ y))) |
|||
else |
|||
atan2 = (y=0)*(x<0)*pi |
|||
end if |
|||
End Function</syntaxhighlight> |
|||
=={{header|Rust}}== |
|||
<syntaxhighlight lang="rust"> |
|||
use std::f64::consts::PI; |
|||
#[derive(Debug, PartialEq, Eq)] |
|||
struct Time { |
|||
h: u8, |
|||
m: u8, |
|||
s: u8, |
|||
} |
|||
impl Time { |
|||
/// Create a Time from equivalent radian measure |
|||
fn from_radians(mut rads: f64) -> Time { |
|||
rads %= 2.0 * PI; |
|||
if rads < 0.0 { |
|||
rads += 2.0 * PI |
|||
} |
|||
Time { |
|||
h: (rads * 12.0 / PI) as u8, |
|||
m: ((rads * 720.0 / PI) % 60.0) as u8, |
|||
s: ((rads * 43200.0 / PI) % 60.0).round() as u8, |
|||
} |
|||
} |
|||
/// Create a Time from H/M/S |
|||
fn from_parts(h: u8, m: u8, s: u8) -> Result<Time, ()> { |
|||
if h > 23 || m > 59 || s > 59 { |
|||
return Err(()); |
|||
} |
|||
Ok(Time { h, m, s }) |
|||
} |
|||
/// Return time as measure in radians |
|||
fn as_radians(&self) -> f64 { |
|||
((self.h as f64 / 12.0) + (self.m as f64 / 720.0) + (self.s as f64 / 43200.0)) * PI |
|||
} |
|||
} |
|||
/// Compute the mean time from a slice of times |
|||
fn mean_time(times: &[Time]) -> Time { |
|||
// compute sum of sines and cosines |
|||
let (ss, sc) = times |
|||
.iter() |
|||
.map(Time::as_radians) |
|||
.map(|a| (a.sin(), a.cos())) |
|||
.fold((0.0, 0.0), |(ss, sc), (s, c)| (ss + s, sc + c)); |
|||
// scaling does not matter for atan2, meaning we do not have to divide sums by len |
|||
Time::from_radians(ss.atan2(sc)) |
|||
} |
|||
fn main() { |
|||
let times = [ |
|||
Time::from_parts(23, 00, 17).unwrap(), |
|||
Time::from_parts(23, 40, 20).unwrap(), |
|||
Time::from_parts(00, 12, 45).unwrap(), |
|||
Time::from_parts(00, 17, 19).unwrap(), |
|||
]; |
|||
let mean = mean_time(×); |
|||
println!("{:02}:{:02}:{:02}", mean.h, mean.m, mean.s); |
|||
} |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
23:47:43 |
|||
</pre> |
|||
=={{header|Scala}}== |
=={{header|Scala}}== |
||
{{libheader|java.time.LocalTime}}< |
{{libheader|java.time.LocalTime}}<syntaxhighlight lang="scala">import java.time.LocalTime |
||
import scala.compat.Platform |
import scala.compat.Platform |
||
Line 1,040: | Line 2,484: | ||
assert(LocalTime.MIN.plusSeconds(meanAngle(times, dayInSeconds).round).toString == "23:47:40") |
assert(LocalTime.MIN.plusSeconds(meanAngle(times, dayInSeconds).round).toString == "23:47:40") |
||
println(s"Successfully completed without errors. [total ${Platform.currentTime - executionStart} ms]") |
println(s"Successfully completed without errors. [total ${Platform.currentTime - executionStart} ms]") |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Scheme}}== |
|||
{{libheader|Scheme/SRFIs}} |
|||
To be self-contained, this starts with the functions from [[Averages/Mean angle]] |
|||
<syntaxhighlight lang="scheme"> |
|||
(import (scheme base) |
|||
(scheme inexact) |
|||
(scheme read) |
|||
(scheme write) |
|||
(srfi 1)) ; for fold |
|||
;; functions copied from "Averages/Mean angle" task |
|||
(define (average l) |
|||
(/ (fold + 0 l) (length l))) |
|||
(define pi 3.14159265358979323846264338327950288419716939937510582097) |
|||
(define (radians a) |
|||
(* pi 1/180 a)) |
|||
(define (degrees a) |
|||
(* 180 (/ 1 pi) a)) |
|||
(define (mean-angle angles) |
|||
(let* ((angles (map radians angles)) |
|||
(cosines (map cos angles)) |
|||
(sines (map sin angles))) |
|||
(degrees (atan (average sines) (average cosines))))) |
|||
;; -- new functions for this task |
|||
(define (time->angle time) |
|||
(let* ((time2 ; replaces : with space in string |
|||
(string-map (lambda (c) (if (char=? c #\:) #\space c)) time)) |
|||
(string-port (open-input-string time2)) |
|||
(hour (read string-port)) |
|||
(minutes (read string-port)) |
|||
(seconds (read string-port))) |
|||
(/ (* 360 (+ (* hour 3600) (* minutes 60) seconds)) |
|||
(* 24 60 60)))) |
|||
(define (angle->time angle) |
|||
(let* ((nom-angle (if (negative? angle) (+ 360 angle) angle)) |
|||
(time (/ (* nom-angle 24 60 60) 360)) |
|||
(hour (exact (floor (/ time 3600)))) |
|||
(minutes (exact (floor (/ (- time (* 3600 hour)) 60)))) |
|||
(seconds (exact (floor (- time (* 3600 hour) (* 60 minutes)))))) |
|||
(string-append (number->string hour) |
|||
":" |
|||
(number->string minutes) |
|||
":" |
|||
(number->string seconds)))) |
|||
(define (mean-time-of-day times) |
|||
(angle->time (mean-angle (map time->angle times)))) |
|||
(write (mean-time-of-day '("23:00:17" "23:40:20" "00:12:45" "00:17:19"))) |
|||
(newline) |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
"23:47:43" |
|||
</pre> |
|||
=={{header|Sidef}}== |
|||
{{trans|Ruby}} |
|||
Using the '''mean_angle()''' function from: [http://rosettacode.org/wiki/Averages/Mean_angle#Sidef "Averages/Mean angle"] |
|||
<syntaxhighlight lang="ruby">func time2deg(t) { |
|||
(var m = t.match(/^(\d\d):(\d\d):(\d\d)$/)) || die "invalid time" |
|||
var (hh,mm,ss) = m.cap.map{.to_i}... |
|||
((hh ~~ 24.range) && (mm ~~ 60.range) && (ss ~~ 60.range)) || die "invalid time" |
|||
(hh*3600 + mm*60 + ss) * 360 / 86400 |
|||
} |
|||
func deg2time(d) { |
|||
var sec = ((d % 360) * 86400 / 360) |
|||
"%02d:%02d:%02d" % (sec/3600, (sec%3600)/60, sec%60) |
|||
} |
|||
func mean_time(times) { |
|||
deg2time(mean_angle(times.map {|t| time2deg(t)})) |
|||
} |
|||
say mean_time(["23:00:17", "23:40:20", "00:12:45", "00:17:19"])</syntaxhighlight> |
|||
{{out}} |
|||
<pre>23:47:43</pre> |
|||
=={{header|SQL}}/{{header|PostgreSQL}}== |
|||
{{trans|Python}} |
|||
<syntaxhighlight lang="sql"> |
|||
--Setup table for testing |
|||
CREATE TABLE time_table(times time); |
|||
INSERT INTO time_table values ('23:00:17'::time),('23:40:20'::time),('00:12:45'::time),('00:17:19'::time) |
|||
--Compute mean time |
|||
SELECT to_timestamp((degrees(atan2(AVG(sin),AVG(cos))))* (24*60*60)/360)::time |
|||
FROM |
|||
(SELECT |
|||
cos(radians(t*360/(24*60*60))),sin(radians(t*360/(24*60*60))) |
|||
FROM |
|||
(SELECT EXTRACT(epoch from times) t |
|||
FROM time_table) T1 |
|||
)T2</syntaxhighlight> |
|||
Output: |
|||
<pre> |
|||
23:47:43.361529 |
|||
</pre> |
|||
=={{header|Swift}}== |
|||
<syntaxhighlight lang="swift">import Foundation |
|||
@inlinable public func d2r<T: FloatingPoint>(_ f: T) -> T { f * .pi / 180 } |
|||
@inlinable public func r2d<T: FloatingPoint>(_ f: T) -> T { f * 180 / .pi } |
|||
public func meanOfAngles(_ angles: [Double]) -> Double { |
|||
let cInv = 1 / Double(angles.count) |
|||
let (y, x) = |
|||
angles.lazy |
|||
.map(d2r) |
|||
.map({ (sin($0), cos($0)) }) |
|||
.reduce(into: (0.0, 0.0), { $0.0 += $1.0; $0.1 += $1.1 }) |
|||
return r2d(atan2(cInv * y, cInv * x)) |
|||
} |
|||
struct DigitTime { |
|||
var hour: Int |
|||
var minute: Int |
|||
var second: Int |
|||
init?(fromString str: String) { |
|||
let split = str.components(separatedBy: ":").compactMap(Int.init) |
|||
guard split.count == 3 else { |
|||
return nil |
|||
} |
|||
(hour, minute, second) = (split[0], split[1], split[2]) |
|||
} |
|||
init(fromDegrees angle: Double) { |
|||
let totalSeconds = 24 * 60 * 60 * angle / 360 |
|||
second = Int(totalSeconds.truncatingRemainder(dividingBy: 60)) |
|||
minute = Int((totalSeconds.truncatingRemainder(dividingBy: 3600) - Double(second)) / 60) |
|||
hour = Int(totalSeconds / 3600) |
|||
} |
|||
func toDegrees() -> Double { |
|||
return 360 * Double(hour) / 24.0 + 360 * Double(minute) / (24 * 60.0) + 360 * Double(second) / (24 * 3600.0) |
|||
} |
|||
} |
|||
extension DigitTime: CustomStringConvertible { |
|||
var description: String { String(format: "%02i:%02i:%02i", hour, minute, second) } |
|||
} |
|||
let times = ["23:00:17", "23:40:20", "00:12:45", "00:17:19"].compactMap(DigitTime.init(fromString:)) |
|||
guard times.count == 4 else { |
|||
fatalError() |
|||
} |
|||
let meanTime = DigitTime(fromDegrees: 360 + meanOfAngles(times.map({ $0.toDegrees() }))) |
|||
print("Given times \(times), the mean time is \(meanTime)")</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Given times [23:00:17, 23:40:20, 00:12:45, 00:17:19], the mean time is 23:47:43</pre> |
|||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
< |
<syntaxhighlight lang="tcl">proc meanTime {times} { |
||
set secsPerRad [expr {60 * 60 * 12 / atan2(0,-1)}] |
set secsPerRad [expr {60 * 60 * 12 / atan2(0,-1)}] |
||
set sumSin [set sumCos 0.0] |
set sumSin [set sumCos 0.0] |
||
Line 1,060: | Line 2,678: | ||
} |
} |
||
puts [meanTime {23:00:17 23:40:20 00:12:45 00:17:19}]</ |
puts [meanTime {23:00:17 23:40:20 00:12:45 00:17:19}]</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
23:47:43 |
23:47:43 |
||
=={{header|VBA}}== |
|||
Uses Excel and [[Averages/Mean_angle#VBA|mean angle]]. |
|||
<syntaxhighlight lang="vb">Public Sub mean_time() |
|||
Dim angles() As Double |
|||
s = [{"23:00:17","23:40:20","00:12:45","00:17:19"}] |
|||
For i = 1 To UBound(s) |
|||
s(i) = 360 * TimeValue(s(i)) |
|||
Next i |
|||
Debug.Print Format(mean_angle(s) / 360 + 1, "hh:mm:ss") |
|||
End Sub</syntaxhighlight>{{out}} |
|||
<pre>23:47:43</pre> |
|||
=={{header|Visual Basic .NET}}== |
|||
{{trans|C#}} |
|||
<syntaxhighlight lang="vbnet">Module Module1 |
|||
Function TimeToDegrees(time As TimeSpan) As Double |
|||
Return 360 * time.Hours / 24.0 + 360 * time.Minutes / (24 * 60.0) + 360 * time.Seconds / (24 * 3600.0) |
|||
End Function |
|||
Function DegreesToTime(angle As Double) As TimeSpan |
|||
Return New TimeSpan((24 * 60 * 60 * angle \ 360) \ 3600, ((24 * 60 * 60 * angle \ 360) Mod 3600 - (24 * 60 * 60 * angle \ 360) Mod 60) \ 60, (24 * 60 * 60 * angle \ 360) Mod 60) |
|||
End Function |
|||
Function MeanAngle(angles As List(Of Double)) As Double |
|||
Dim y_part = 0.0 |
|||
Dim x_part = 0.0 |
|||
Dim numItems = angles.Count |
|||
For Each angle In angles |
|||
x_part += Math.Cos(angle * Math.PI / 180) |
|||
y_part += Math.Sin(angle * Math.PI / 180) |
|||
Next |
|||
Return Math.Atan2(y_part / numItems, x_part / numItems) * 180 / Math.PI |
|||
End Function |
|||
Sub Main() |
|||
Dim digitimes As New List(Of Double) |
|||
Dim digitime As TimeSpan |
|||
Dim input As String |
|||
Console.WriteLine("Enter times, end with no input: ") |
|||
Do |
|||
input = Console.ReadLine |
|||
If Not String.IsNullOrWhiteSpace(input) Then |
|||
If TimeSpan.TryParse(input, digitime) Then |
|||
digitimes.Add(TimeToDegrees(digitime)) |
|||
Else |
|||
Console.WriteLine("Seems this is wrong input: ingnoring time") |
|||
End If |
|||
End If |
|||
Loop Until String.IsNullOrWhiteSpace(input) |
|||
If digitimes.Count > 0 Then |
|||
Console.WriteLine("The mean time is : {0}", DegreesToTime(360 + MeanAngle(digitimes))) |
|||
End If |
|||
End Sub |
|||
End Module</syntaxhighlight> |
|||
{{out}} |
|||
<pre>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</pre> |
|||
=={{header|V (Vlang)}}== |
|||
{{trans|Wren}} |
|||
<syntaxhighlight lang="v (vlang)">import math |
|||
const inputs = ["23:00:17", "23:40:20", "00:12:45", "00:17:19"] |
|||
fn main() { |
|||
angles := inputs.map(time_to_degs(it)) |
|||
println('Mean time of day is: ${degs_to_time(mean_angle(angles))}') |
|||
} |
|||
fn mean_angle(angles []f64) f64 { |
|||
n := angles.len |
|||
mut sin_sum := f64(0) |
|||
mut cos_sum := f64(0) |
|||
for angle in angles { |
|||
sin_sum += math.sin(angle * math.pi / 180) |
|||
cos_sum += math.cos(angle * math.pi / 180) |
|||
} |
|||
return math.atan2(sin_sum/n, cos_sum/n) * 180 / math.pi |
|||
} |
|||
fn degs_to_time(dd f64) string{ |
|||
mut d := dd |
|||
for d < 0 { |
|||
d += 360 |
|||
} |
|||
mut s := math.round(d * 240) |
|||
h := math.floor(s/3600) |
|||
mut m := math.fmod(s, 3600) |
|||
s = math.fmod(m, 60) |
|||
m = math.floor(m / 60) |
|||
return "${h:02}:${m:02}:${s:02}" |
|||
} |
|||
fn time_to_degs(time string) f64 { |
|||
t := time.split(":") |
|||
h := t[0].f64() * 3600 |
|||
m := t[1].f64() * 60 |
|||
s := t[2].f64() |
|||
return (h + m + s) / 240 |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Mean time of day is: 23:47:43 |
|||
</pre> |
|||
=={{header|Wren}}== |
|||
{{libheader|Wren-fmt}} |
|||
<syntaxhighlight lang="wren">import "./fmt" for Fmt |
|||
var timeToDegs = Fn.new { |time| |
|||
var t = time.split(":") |
|||
var h = Num.fromString(t[0]) * 3600 |
|||
var m = Num.fromString(t[1]) * 60 |
|||
var s = Num.fromString(t[2]) |
|||
return (h + m + s) / 240 |
|||
} |
|||
var degsToTime = Fn.new { |d| |
|||
while (d < 0) d = d + 360 |
|||
var s = (d * 240).round |
|||
var h = (s/3600).floor |
|||
var m = s % 3600 |
|||
s = m % 60 |
|||
m = (m / 60).floor |
|||
return Fmt.swrite("$2d:$2d:$2d", h, m, s) |
|||
} |
|||
var meanAngle = Fn.new { |angles| |
|||
var n = angles.count |
|||
var sinSum = 0 |
|||
var cosSum = 0 |
|||
for (angle in angles) { |
|||
sinSum = sinSum + (angle * Num.pi / 180).sin |
|||
cosSum = cosSum + (angle * Num.pi / 180).cos |
|||
} |
|||
return (sinSum/n).atan(cosSum/n) * 180 / Num.pi |
|||
} |
|||
var times = ["23:00:17", "23:40:20", "00:12:45", "00:17:19"] |
|||
var angles = times.map { |t| timeToDegs.call(t) }.toList |
|||
System.print("Mean time of day is : %(degsToTime.call(meanAngle.call(angles)))")</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Mean time of day is : 23:47:43 |
|||
</pre> |
|||
=={{header|XPL0}}== |
=={{header|XPL0}}== |
||
< |
<syntaxhighlight lang="xpl0">include c:\cxpl\codes; |
||
proc NumOut(N); \Display 2-digit N with leading zero |
proc NumOut(N); \Display 2-digit N with leading zero |
||
Line 1,101: | Line 2,877: | ||
]; |
]; |
||
TimeOut(MeanTime([4, [23,00,17], [23,40,20], [00,12,45], [00,17,19]]))</ |
TimeOut(MeanTime([4, [23,00,17], [23,40,20], [00,12,45], [00,17,19]]))</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
23:47:43 |
23:47:43 |
||
</pre> |
</pre> |
||
=={{header|Yabasic}}== |
|||
{{trans|Phix}} |
|||
<syntaxhighlight lang="yabasic">sub atan2(y, x) |
|||
return 2 * atan((sqrt(x **2 + y ** 2) - x) / y) |
|||
end sub |
|||
sub MeanAngle(angles()) |
|||
local x, y, ai_rad, l, i |
|||
l = arraysize(angles(), 1) |
|||
for i = 1 to l |
|||
ai_rad = angles(i) * PI / 180 |
|||
x = x + cos(ai_rad) |
|||
y = y + sin(ai_rad) |
|||
next i |
|||
if abs(x) < 1e-16 return false |
|||
return atan2(y, x) * 180 / PI |
|||
end sub |
|||
sub toSecAngle(hours, minutes, seconds) |
|||
return ((hours * 60 + minutes) * 60 + seconds) / (24 * 60 * 60) * 360 |
|||
end sub |
|||
dim Times(4) |
|||
Times(1) = toSecAngle(23,00,17) |
|||
Times(2) = toSecAngle(23,40,20) |
|||
Times(3) = toSecAngle(00,12,45) |
|||
Times(4) = toSecAngle(00,17,19) |
|||
sub toHMS$(t) |
|||
local s$ |
|||
if t then |
|||
if t < 0 t = t + 360 |
|||
t = 24 * 60 * 60 * t / 360 |
|||
s$ = str$(int(t / 3600), "%02g") + ":" + str$(int(mod(t, 3600) / 60), "%02g") + ":" + str$(int(mod(t, 60)), "%02g") |
|||
else |
|||
s$ = "not meaningful" |
|||
end if |
|||
return s$ |
|||
end sub |
|||
print "Mean Time is ", toHMS$(MeanAngle(Times())) |
|||
// Output: Mean Time is 23:47:43 |
|||
</syntaxhighlight> |
|||
=={{header|zkl}}== |
=={{header|zkl}}== |
||
Line 1,111: | Line 2,936: | ||
to task "Averages/Mean angle" and some on-the-fly |
to task "Averages/Mean angle" and some on-the-fly |
||
time-to-angle and back conversions. |
time-to-angle and back conversions. |
||
< |
<syntaxhighlight lang="zkl">var D=Time.Date; |
||
fcn meanT(t1,t2,etc){ |
fcn meanT(t1,t2,etc){ |
||
ts:=vm.arglist.apply(fcn(hms){ |
ts:=vm.arglist.apply(fcn(hms){ |
||
Line 1,122: | Line 2,947: | ||
if(mt<0) mt+=24; //-0.204622-->23.7954 |
if(mt<0) mt+=24; //-0.204622-->23.7954 |
||
D.toHour(mt).concat(":") |
D.toHour(mt).concat(":") |
||
}</ |
}</syntaxhighlight> |
||
Time.Date.toFloat/toHour convert 24hr HMS to fractional time and back. Multiplying fractional time by 360/24=15 yields angle. |
Time.Date.toFloat/toHour convert 24hr HMS to fractional time and back. Multiplying fractional time by 360/24=15 yields angle. |
||
{{out}} |
{{out}} |
Latest revision as of 16:20, 27 December 2023
You are encouraged to solve this task according to the task description, using any language you may know.
- Task
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.
|
11l
F mean_angle(angles)
V x = sum(angles.map(a -> cos(radians(a)))) / angles.len
V y = sum(angles.map(a -> sin(radians(a)))) / angles.len
R degrees(atan2(y, x))
F mean_time(times)
V t = (times.map(time -> time.split(‘:’)))
V seconds = (t.map(hms -> (Float(hms[2]) + Int(hms[1]) * 60 + Int(hms[0]) * 3600)))
V day = 24 * 60 * 60
V to_angles = seconds.map(s -> s * 360.0 / @day)
V mean_as_angle = mean_angle(to_angles)
V mean_seconds = round(mean_as_angle * day / 360.0)
I mean_seconds < 0
mean_seconds += day
V h = mean_seconds I/ 3600
V m = mean_seconds % 3600
V s = m % 60
m = m I/ 60
R ‘#02:#02:#02’.format(h, m, s)
print(mean_time([‘23:00:17’, ‘23:40:20’, ‘00:12:45’, ‘00:17:19’]))
- Output:
23:47:43
Action!
Action! does not support trigonometry, therefore a simple arithmetic solution has been proposed.
INCLUDE "H6:REALMATH.ACT"
DEFINE PTR="CARD"
TYPE Time=[BYTE s,m,h]
REAL r60
PROC PrintB2(BYTE b)
IF b<10 THEN Put('0) FI
PrintB(b)
RETURN
PROC PrintTime(Time POINTER t)
PrintB2(t.h) Put(':)
PrintB2(t.m) Put(':)
PrintB2(t.s)
RETURN
PROC Decode(CHAR ARRAY st Time POINTER t)
CHAR ARRAY tmp
IF st(0)#8 THEN Break() FI
SCopyS(tmp,st,1,2) t.h=ValB(tmp)
SCopyS(tmp,st,4,5) t.m=ValB(tmp)
SCopyS(tmp,st,7,8) t.s=ValB(tmp)
RETURN
PROC TimeToSeconds(Time POINTER t REAL POINTER seconds)
REAL r
IntToReal(t.h,seconds)
RealMult(seconds,r60,seconds)
IntToReal(t.m,r)
RealAdd(seconds,r,seconds)
RealMult(seconds,r60,seconds)
IntToReal(t.s,r)
RealAdd(seconds,r,seconds)
RETURN
PROC SecondsToTime(REAL POINTER seconds Time POINTER t)
REAL tmp1,tmp2
RealAssign(seconds,tmp1)
RealMod(tmp1,r60,tmp2)
t.s=RealToInt(tmp2)
RealDivInt(tmp1,r60,tmp2)
RealMod(tmp2,r60,tmp1)
t.m=RealToInt(tmp1)
RealDivInt(tmp2,r60,tmp1)
t.h=RealToInt(tmp1)
RETURN
PROC AverageTime(PTR ARRAY times BYTE count Time POINTER res)
BYTE i
Time t
REAL avg,rcount,seconds,halfDay,day
IntToReal(0,avg)
IntToReal(count,rcount)
ValR("43200",halfDay) ;seconds in the half of day
ValR("86400",day) ;seconds in the whole day
FOR i=0 TO count-1
DO
Decode(times(i),t)
TimeToSeconds(t,seconds)
IF RealLess(seconds,halfDay) THEN
RealAdd(seconds,day,seconds) ;correction of time
FI
RealAdd(avg,seconds,avg)
OD
RealDivInt(avg,rcount,avg)
WHILE RealGreaterOrEqual(avg,day)
DO
RealSub(avg,day,avg) ;correction of time
OD
SecondsToTime(avg,res)
RETURN
PROC Main()
DEFINE COUNT="4"
PTR ARRAY times(COUNT)
Time t
Put(125) PutE() ;clear the screen
IntToReal(60,r60)
times(0)="23:00:17" times(1)="23:40:20"
times(2)="00:12:45" times(3)="00:17:19"
AverageTime(times,COUNT,t)
Print("Mean time is ") PrintTime(t)
RETURN
- Output:
Screenshot from Atari 8-bit computer
Mean time is 23:47:40
Ada
with Ada.Calendar.Formatting;
with Ada.Command_Line;
with Ada.Numerics.Elementary_Functions;
with Ada.Strings.Fixed;
with Ada.Text_IO;
procedure Mean_Time_Of_Day is
subtype Time is Ada.Calendar.Time;
subtype Time_Of_Day is Ada.Calendar.Day_Duration;
subtype Time_String is String (1 .. 8); -- "HH:MM:SS"
type Time_List is array (Positive range <>) of Time_String;
function Average_Time (List : Time_List) return Time_String is
function To_Time (Time_Image : Time_String) return Time
is (Ada.Calendar.Formatting.Value ("2000-01-01 " & Time_Image));
function To_Time_Of_Day (TS : Time) return Time_Of_Day is
use Ada.Calendar.Formatting;
Hour_Part : constant Time_Of_Day := 60.0 * 60.0 * Hour (TS);
Min_Part : constant Time_Of_Day := 60.0 * Minute (TS);
Sec_Part : constant Time_Of_Day := Time_Of_Day (Second (TS));
begin
return Hour_Part + Min_Part + Sec_Part;
end To_Time_Of_Day;
function To_Time_Image (Angle : Time_Of_Day) return Time_String
is
use Ada.Calendar.Formatting;
TOD : constant Time := Time_Of
(Year => 2000, Month => 1, Day => 1, -- Not used
Seconds => Angle);
begin
return Ada.Strings.Fixed.Tail (Image (TOD), Time_String'Length);
end To_Time_Image;
function Average_Time_Of_Day (List : Time_List) return Time_Of_Day is
use Ada.Numerics.Elementary_Functions;
Cycle : constant Float := Float (Time_Of_Day'Last);
X_Sum, Y_Sum : Float := 0.0;
Angle : Float;
begin
for Time_Stamp of List loop
Angle := Float (To_Time_Of_Day (To_Time (Time_Stamp)));
X_Sum := X_Sum + Cos (Angle, Cycle => Cycle);
Y_Sum := Y_Sum + Sin (Angle, Cycle => Cycle);
end loop;
Angle := Arctan (Y_Sum, X_Sum, Cycle => Cycle);
if Angle < 0.0 then
Angle := Angle + Cycle;
elsif Angle > Cycle then
Angle := Angle - Cycle;
end if;
return Time_Of_Day (Angle);
end Average_Time_Of_Day;
begin
return To_Time_Image (Average_Time_Of_Day (List));
end Average_Time;
use Ada.Command_Line;
List : Time_List (1 .. Argument_Count);
begin
if Argument_Count = 0 then
raise Constraint_Error;
end if;
for A in 1 .. Argument_Count loop
List (A) := Argument (A);
end loop;
Ada.Text_IO.Put_Line (Average_Time (List));
exception
when others =>
Ada.Text_IO.Put_Line ("Usage: mean_time_of_day <time-1> ...");
Ada.Text_IO.Put_Line (" <time-1> ... 'HH:MM:SS' format");
end Mean_Time_Of_Day;
- Output:
% ./mean_time_of_day 23:00:17 23:40:20 00:12:45 00:17:19 23:47:43
ALGOL 68
Uses code from the Averages/Mean angle task, included here for convenience.
BEGIN # Mean time of day mapping time to angles #
# code from the Averages/Mean angle task - angles are in degrees #
PROC mean angle = ([]REAL angles)REAL:
(
INT size = UPB angles - LWB angles + 1;
REAL y part := 0, x part := 0;
FOR i FROM LWB angles TO UPB angles DO
x part +:= cos (angles[i] * pi / 180);
y part +:= sin (angles[i] * pi / 180)
OD;
arc tan2 (y part / size, x part / size) * 180 / pi
);
# end code from the Averages/Mean angle task #
MODE TIME = STRUCT( INT hh, mm, ss );
OP TOANGLE = ( TIME t )REAL: ( ( ( ( ( ss OF t / 60 ) + mm OF t ) / 60 ) + hh OF t ) * 360 ) / 24;
OP TOTIME = ( REAL a )TIME:
BEGIN
REAL t := ( a * 24 ) / 360;
WHILE t < 0 DO t +:= 24 OD;
WHILE t > 24 DO t -:= 24 OD;
INT hh = ENTIER t;
t -:= hh *:= 60;
INT mm = ENTIER t;
INT ss = ENTIER ( ( t - mm ) * 60 );
( hh, mm, ss )
END # TOTIME # ;
PROC mean time = ( []TIME times )TIME:
BEGIN
[ LWB times : UPB times ]REAL angles;
FOR i FROM LWB times TO UPB times DO angles[ i ] := TOANGLE times[ i ] OD;
TOTIME mean angle( angles )
END # mean time # ;
OP SHOW = ( TIME t )VOID:
BEGIN
PROC d2 = ( INT n )STRING: IF n < 10 THEN "0" ELSE "" FI + whole( n, 0 );
print( ( d2( hh OF t ), ":", d2( mm OF t ), ":", d2( ss OF t ) ) )
END # show time # ;
SHOW mean time( ( ( 23,00,17 ), ( 23,40,20 ), ( 00,12,45 ), ( 00,17,19 ) ) )
END
- Output:
23:47:43
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) {
static 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")
}
- Output:
The mean time is: 23:47:43
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);
}
$ 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
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
- Output:
Mean time is 23:47:43
C
#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;
}
- 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#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using static System.Math;
namespace RosettaCode;
class Program
{
private const int SecondsPerDay = 60 * 60 * 24;
static void Main()
{
var digitimes = new List<TimeSpan>();
Console.WriteLine("Enter times, end with no input: ");
while (true) {
string input = Console.ReadLine();
if (string.IsNullOrWhiteSpace(input)) break;
if (TimeSpan.TryParse(input, out var digitime)) {
digitimes.Add(digitime);
} else {
Console.WriteLine("Seems this is wrong input: ignoring time");
}
}
if(digitimes.Count() > 0)
Console.WriteLine($"The mean time is : {MeanTime(digitimes)}");
}
public static TimeSpan MeanTime(IEnumerable<TimeSpan> ts) => FromDegrees(MeanAngle(ts.Select(ToDegrees)));
public static double ToDegrees(TimeSpan ts) => ts.TotalSeconds * 360d / SecondsPerDay;
public static TimeSpan FromDegrees(double degrees) => TimeSpan.FromSeconds((int)(degrees * SecondsPerDay / 360));
public static double MeanAngle(IEnumerable<double> angles)
{
var x = angles.Average(a => Cos(a * PI / 180));
var y = angles.Average(a => Sin(a * PI / 180));
return (Atan2(y, x) * 180 / PI + 360) % 360;
}
}
- 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
C++
#include <iomanip>
#include <iostream>
#include <vector>
#define _USE_MATH_DEFINES
#include <math.h>
struct Time {
int hour, minute, second;
friend std::ostream &operator<<(std::ostream &, const Time &);
};
std::ostream &operator<<(std::ostream &os, const Time &t) {
return os << std::setfill('0')
<< std::setw(2) << t.hour << ':'
<< std::setw(2) << t.minute << ':'
<< std::setw(2) << t.second;
}
double timeToDegrees(Time &&t) {
return 360.0 * t.hour / 24.0
+ 360.0 * t.minute / (24 * 60.0)
+ 360.0 * t.second / (24 * 3600.0);
}
Time degreesToTime(double angle) {
while (angle < 0.0) {
angle += 360.0;
}
while (angle > 360.0) {
angle -= 360.0;
}
double totalSeconds = 24.0 * 60 * 60 * angle / 360;
Time t;
t.second = (int)totalSeconds % 60;
t.minute = ((int)totalSeconds % 3600 - t.second) / 60;
t.hour = (int)totalSeconds / 3600;
return t;
}
double meanAngle(const std::vector<double> &angles) {
double yPart = 0.0, xPart = 0.0;
for (auto a : angles) {
xPart += cos(a * M_PI / 180);
yPart += sin(a * M_PI / 180);
}
return atan2(yPart / angles.size(), xPart / angles.size()) * 180 / M_PI;
}
int main() {
std::vector<double> tv;
tv.push_back(timeToDegrees({ 23, 0, 17 }));
tv.push_back(timeToDegrees({ 23, 40, 20 }));
tv.push_back(timeToDegrees({ 0, 12, 45 }));
tv.push_back(timeToDegrees({ 0, 17, 19 }));
double ma = meanAngle(tv);
auto mt = degreesToTime(ma);
std::cout << mt << '\n';
return 0;
}
- Output:
23:47:43
Common Lisp
;; * Loading the split-sequence library
(eval-when (:compile-toplevel :load-toplevel :execute)
(ql:quickload '("split-sequence")))
;; * The package definition
(defpackage :mean-time-of-day
(:use :common-lisp :iterate :split-sequence))
(in-package :mean-time-of-day)
;; * The data
(defparameter *time-values*
'("23:00:17" "23:40:20" "00:12:45" "00:17:19"))
(defun time->radian (time)
"Returns the radian value for TIME given as a STRING like HH:MM:SS. Assuming a
valid input value."
(destructuring-bind (h m s)
(mapcar #'parse-integer (split-sequence #\: time))
(+ (* h (/ PI 12)) (* m (/ PI 12 60)) (* s (/ PI 12 3600)))))
(defun radian->time (radian)
"Returns the corresponding time as a string like HH:MM:SS for RADIAN."
(let* ((time (if (plusp radian)
(round (/ (* 12 3600 radian) PI))
(round (/ (* 12 3600 (+ radian (* 2 PI))) PI))))
(h (floor time 3600))
(m (floor (- time (* h 3600)) 60))
(s (- time (* h 3600) (* m 60))))
(format nil "~2,'0D:~2,'0D:~2,'0D" h m s)))
(defun make-polar (rho theta)
"Returns a complex representing the polar coordinates."
(complex (* rho (cos theta)) (* rho (sin theta))))
(defun mean-time (times)
"Returns the mean time value within 24h of the list of TIMES given as strings
HH:MM:SS."
(radian->time (phase
(reduce #'+ (mapcar (lambda (time)
(make-polar 1 (time->radian time))) times)))))
- Output:
MEAN-TIME-OF-DAY> (mean-time *time-values*) "23:47:43"
D
import std.stdio, std.range, std.algorithm, std.complex, std.math,
std.format, std.conv;
double radians(in double d) pure nothrow @safe @nogc {
return d * PI / 180;
}
double degrees(in double r) pure nothrow @safe @nogc {
return r * 180 / PI;
}
double meanAngle(in double[] deg) pure nothrow @safe @nogc {
return (deg.map!(d => fromPolar(1, d.radians)).sum / deg.length).arg.degrees;
}
string meanTime(in string[] times) pure @safe {
auto t = times.map!(times => times.split(':').to!(int[3]));
assert(t.all!(hms => 24.iota.canFind(hms[0]) &&
60.iota.canFind(hms[1]) &&
60.iota.canFind(hms[2])),
"Invalid time");
auto seconds = t.map!(hms => hms[2] + hms[1] * 60 + hms[0] * 3600);
enum day = 24 * 60 * 60;
const to_angles = seconds.map!(s => s * 360.0 / day).array;
immutable mean_as_angle = to_angles.meanAngle;
auto mean_seconds_fp = mean_as_angle * day / 360.0;
if (mean_seconds_fp < 0)
mean_seconds_fp += day;
immutable mean_seconds = mean_seconds_fp.to!uint;
immutable h = mean_seconds / 3600;
immutable m = mean_seconds % 3600;
return "%02d:%02d:%02d".format(h, m / 60, m % 60);
}
void main() @safe {
["23:00:17", "23:40:20", "00:12:45", "00:17:19"].meanTime.writeln;
}
- Output:
23:47:43
Delphi
program Averages_Mean_time_of_day;
{$APPTYPE CONSOLE}
uses
System.SysUtils,
System.Math;
const
Inputs: TArray<string> = ['23:00:17', '23:40:20', '00:12:45', '00:17:19'];
function ToTimes(ts: TArray<string>): TArray<TTime>;
begin
SetLength(result, length(ts));
for var i := 0 to High(ts) do
Result[i] := StrToTime(ts[i]);
end;
function MeanTime(times: TArray<TTime>): TTime;
var
ssum, csum: TTime;
h, m, s, ms: word;
dayFrac, fsec, ssin, ccos: double;
begin
if Length(times) = 0 then
exit(0);
ssum := 0;
csum := 0;
for var t in times do
begin
DecodeTime(t, h, m, s, ms);
fsec := (h * 60 + m) * 60 + s + ms / 1000;
ssin := sin(fsec * Pi / (12 * 60 * 60));
ccos := cos(fsec * Pi / (12 * 60 * 60));
ssum := ssum + ssin;
csum := csum + ccos;
end;
if (ssum = 0) and (csum = 0) then
raise Exception.Create('Error MeanTime: Mean undefined');
dayFrac := frac(1 + ArcTan2(ssum, csum) / (2 * Pi));
fsec := dayFrac * 24 * 3600;
ms := Trunc(frac(fsec) * 1000);
s := trunc(fsec) mod 60;
m := trunc(fsec) div 60 mod 60;
h := trunc(fsec) div 3600;
Result := EncodeTime(h, m, s, ms);
end;
begin
writeln(TimeToStr(MeanTime(ToTimes(Inputs))));
readln;
end.
EasyLang
func tm2deg t$ .
t[] = number strsplit t$ ":"
return 360 * t[1] / 24.0 + 360 * t[2] / (24 * 60.0) + 360 * t[3] / (24 * 3600.0)
.
func$ deg2tm deg .
len t[] 3
h = floor (24 * 60 * 60 * deg / 360)
t[3] = h mod 60
h = h div 60
t[2] = h mod 60
t[1] = h div 60
for h in t[]
if h < 10
s$ &= 0
.
s$ &= h
s$ &= ":"
.
return substr s$ 1 8
.
func mean ang[] .
for ang in ang[]
x += cos ang
y += sin ang
.
return atan2 (y / len ang[]) (x / len ang[])
.
in$ = "23:00:17 23:40:20 00:12:45 00:17:19"
for s$ in strsplit in$ " "
ar[] &= tm2deg s$
.
print deg2tm (360 + mean ar[])
EchoLisp
;; string hh:mm:ss to radians
(define (time->radian time)
(define-values (h m s) (map string->number (string-split time ":")))
(+ (* h (/ PI 12)) (* m (/ PI 12 60)) (* s (/ PI 12 3600))))
;; radians to string hh:mm;ss
(define (radian->time rad)
(when (< rad 0) (+= rad (* 2 PI)))
(define t (round (/ (* 12 3600 rad) PI)))
(define h (quotient t 3600))
(define m (quotient (- t (* h 3600)) 60))
(define s (- t (* 3600 h) (* 60 m)))
(string-join (map number->string (list h m s)) ":"))
(define (mean-time times)
(radian->time
(angle
(for/sum ((t times)) (make-polar 1 (time->radian t))))))
(mean-time '{"23:00:17" "23:40:20" "00:12:45" "00:17:19"})
→ "23:47:43"
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]) ).
- 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"
Euphoria
include std/console.e
include std/math.e
include std/mathcons.e
include std/sequence.e
include std/get.e
function T2D(sequence TimeSeq)
return (360 * TimeSeq[1] / 24 + 360 * TimeSeq[2] / (24 * 60) +
360 * TimeSeq[3] / (24 * 3600))
end function
function D2T(atom angle)
sequence TimeSeq = {0,0,0}
atom seconds = 24 * 60 * 60 * angle / 360
TimeSeq[3] = mod(seconds,60)
TimeSeq[2] = (mod(seconds,3600) - TimeSeq[3]) / 60
TimeSeq[1] = seconds / 3600
return TimeSeq
end function
function MeanAngle(sequence angles)
atom x = 0, y = 0
integer l = length(angles)
for i = 1 to length(angles) do
x += cos(angles[i] * PI / 180)
y += sin(angles[i] * PI / 180)
end for
return atan2(y / l, x / l) * 180 / PI
end function
sequence TimeEntry, TimeList = {}, TimeSeq
puts(1,"Enter times. Enter with no input to end\n")
while 1 do
TimeEntry = prompt_string("")
if equal(TimeEntry,"") then -- no more entries
for i = 1 to length(TimeList) do
TimeList[i] = split(TimeList[i],":") -- split the times into sequences
for j = 1 to 3 do
TimeList[i][j] = defaulted_value(TimeList[i][j],0) -- convert to numerical values
end for
end for
exit
end if
TimeList = append(TimeList,TimeEntry)
end while
sequence AngleList = repeat({},length(TimeList))
for i = 1 to length(AngleList) do
AngleList[i] = T2D(TimeList[i])
end for
sequence MeanTime = D2T(360+MeanAngle(AngleList))
printf(1,"\nMean Time: %d:%d:%d\n",MeanTime)
if getc(0) then end if
- Output:
Enter Times. Enter with no input to end. 23:00:17 23:40:20 00:12:45 00:17:19 Mean Time: 23:47:43
F#
open System
open System.Numerics
let deg2rad d = d * Math.PI / 180.
let rad2deg r = r * 180. / Math.PI
let makeComplex = fun r -> Complex.FromPolarCoordinates(1., r)
// 1 msec = 10000 ticks
let time2deg = TimeSpan.Parse >> (fun ts -> ts.Ticks) >> (float) >> (*) (10e-9/24.)
let deg2time = (*) (24. * 10e7) >> (int64) >> TimeSpan
[<EntryPoint>]
let main argv =
let msg = "Average time for [" + (String.Join("; ",argv)) + "] is"
argv
|> Seq.map (time2deg >> deg2rad >> makeComplex)
|> Seq.fold (fun x y -> Complex.Add(x,y)) Complex.Zero
|> fun c -> c.Phase |> rad2deg
|> fun d -> if d < 0. then d + 360. else d
|> deg2time |> fun t -> t.ToString(@"hh\:mm\:ss")
|> printfn "%s: %s" msg
0
- Output:
>RosettaCode 23:00:17 23:40:20 00:12:45 00:17:19 Average time for [23:00:17; 23:40:20; 00:12:45; 00:17:19] is: 23:47:43
Factor
USING: arrays formatting kernel math math.combinators
math.functions math.libm math.parser math.trig qw sequences
splitting ;
IN: rosetta-code.mean-time
CONSTANT: input qw{ 23:00:17 23:40:20 00:12:45 00:17:19 }
: time>deg ( hh:mm:ss -- x )
":" split [ string>number ] map first3
[ 15 * ] [ 1/4 * ] [ 1/240 * ] tri* + + ;
: mean-angle ( seq -- x )
[ deg>rad ] map [ [ sin ] map-sum ] [ [ cos ] map-sum ]
[ length ] tri recip [ * ] curry bi@ fatan2 rad>deg ;
: cutf ( x -- str y )
[ >integer number>string ] [ dup floor - ] bi ;
: mean-time ( seq -- str )
[ time>deg ] map mean-angle [ 360 + ] when-negative 24 *
360 / cutf 60 * cutf 60 * round cutf drop 3array ":" join ;
: mean-time-demo ( -- )
input dup mean-time "Mean time for %u is %s.\n" printf ;
MAIN: mean-time-demo
- Output:
Mean time for { "23:00:17" "23:40:20" "00:12:45" "00:17:19" } is 23:47:43.
Fortran
program mean_time_of_day
implicit none
integer(kind=4), parameter :: dp = kind(0.0d0)
type time_t
integer(kind=4) :: hours, minutes, seconds
end type
character(len=8), dimension(4), parameter :: times = &
(/ '23:00:17', '23:40:20', '00:12:45', '00:17:19' /)
real(kind=dp), dimension(size(times)) :: angles
real(kind=dp) :: mean
angles = time_to_angle(str_to_time(times))
mean = mean_angle(angles)
if (mean < 0) mean = 360 + mean
write(*, fmt='(I2.2, '':'', I2.2, '':'', I2.2)') angle_to_time(mean)
contains
real(kind=dp) function mean_angle(angles)
real(kind=dp), dimension(:), intent (in) :: angles
real(kind=dp) :: x, y
x = sum(sin(radians(angles)))/size(angles)
y = sum(cos(radians(angles)))/size(angles)
mean_angle = degrees(atan2(x, y))
end function
elemental real(kind=dp) function radians(angle)
real(kind=dp), intent (in) :: angle
real(kind=dp), parameter :: pi = 4d0*atan(1d0)
radians = angle/180*pi
end function
elemental real(kind=dp) function degrees(angle)
real(kind=dp), intent (in) :: angle
real(kind=dp), parameter :: pi = 4d0*atan(1d0)
degrees = 180*angle/pi
end function
elemental type(time_t) function str_to_time(str)
character(len=*), intent (in) :: str
! Assuming time in format hh:mm:ss
read(str, fmt='(I2, 1X, I2, 1X, I2)') str_to_time
end function
elemental real(kind=dp) function time_to_angle(time) result (res)
type(time_t), intent (in) :: time
real(kind=dp) :: seconds
real(kind=dp), parameter :: seconds_in_day = 24*60*60
seconds = time%seconds + 60*time%minutes + 60*60*time%hours
res = 360*seconds/seconds_in_day
end function
elemental type(time_t) function angle_to_time(angle)
real(kind=dp), intent (in) :: angle
real(kind=dp) :: seconds
real(kind=dp), parameter :: seconds_in_day = 24*60*60
seconds = seconds_in_day*angle/360d0
angle_to_time%hours = int(seconds/60d0/60d0)
seconds = mod(seconds, 60d0*60d0)
angle_to_time%minutes = int(seconds/60d0)
angle_to_time%seconds = mod(seconds, 60d0)
end function
end program
- Output:
23:47:43
FreeBASIC
' FB 1.05.0 Win64
Const pi As Double = 3.1415926535897932
Function meanAngle(angles() As Double) As Double
Dim As Integer length = Ubound(angles) - Lbound(angles) + 1
Dim As Double sinSum = 0.0
Dim As Double cosSum = 0.0
For i As Integer = LBound(angles) To UBound(angles)
sinSum += Sin(angles(i) * pi / 180.0)
cosSum += Cos(angles(i) * pi / 180.0)
Next
Return Atan2(sinSum / length, cosSum / length) * 180.0 / pi
End Function
' time string assumed to be in format "hh:mm:ss"
Function timeToSecs(t As String) As Integer
Dim As Integer hours = Val(Left(t, 2))
Dim As Integer mins = Val(Mid(t, 4, 2))
Dim As Integer secs = Val(Right(t, 2))
Return 3600 * hours + 60 * mins + secs
End Function
' 1 second of time = 360/(24 * 3600) = 1/240th degree
Function timeToDegrees(t As String) As Double
Dim secs As Integer = timeToSecs(t)
Return secs/240.0
End Function
Function degreesToTime(d As Double) As String
If d < 0 Then d += 360.0
Dim secs As Integer = d * 240.0
Dim hours As Integer = secs \ 3600
Dim mins As Integer = secs Mod 3600
secs = mins Mod 60
mins = mins \ 60
Dim hBuffer As String = Right("0" + Str(hours), 2)
Dim mBuffer As String = Right("0" + Str(mins), 2)
Dim sBuffer As String = Right("0" + Str(secs), 2)
Return hBuffer + ":" + mBuffer + ":" + sBuffer
End Function
Dim tm(1 To 4) As String = {"23:00:17", "23:40:20", "00:12:45", "00:17:19"}
Dim angles(1 To 4) As Double
For i As Integer = 1 To 4
angles(i) = timeToDegrees(tm(i))
Next
Dim mean As Double = meanAngle(angles())
Print "Average time is : "; degreesToTime(mean)
Print
Print "Press any key to quit"
Sleep
- Output:
Average time is : 23:47:43
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
}
- Output:
23:47:43
Groovy
Solution:
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)
}
Test:
println (meanTime("23:00:17", "23:40:20", "00:12:45", "00:17:19"))
- Output:
23:47:43
Haskell
import Data.Complex (cis, phase)
import Data.List.Split (splitOn)
import Text.Printf (printf)
timeToRadians :: String -> Float
timeToRadians time =
let hours:minutes:seconds:_ = splitOn ":" time
s = fromIntegral (read seconds :: Int)
m = fromIntegral (read minutes :: Int)
h = fromIntegral (read hours :: Int)
in (2*pi)*(h+ (m + s/60.0 )/60.0 )/24.0
radiansToTime :: Float -> String
radiansToTime r =
let tau = pi*2
(_,fDay) = properFraction (r / tau) :: (Int, Float)
fDayPositive = if fDay < 0 then 1.0+fDay else fDay
(hours, fHours) = properFraction $ 24.0 * fDayPositive
(minutes, fMinutes) = properFraction $ 60.0 * fHours
seconds = 60.0 * fMinutes
in printf "%0d" (hours::Int) ++ ":" ++ printf "%0d" (minutes::Int) ++ ":" ++ printf "%0.0f" (seconds::Float)
meanAngle :: [Float] -> Float
meanAngle = phase . sum . map cis
main :: IO ()
main = putStrLn $ radiansToTime $ meanAngle $ map timeToRadians ["23:00:17", "23:40:20", "00:12:45", "00:17:19"]
- Output:
23:47:43
Icon and Unicon
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
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
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
- Example Use:
meanTime '23:00:17 23:40:20 00:12:45 00:17:19 '
23:47:43
Java
public class MeanTimeOfDay {
static double meanAngle(double[] angles) {
int len = angles.length;
double sinSum = 0.0;
for (int i = 0; i < len; i++) {
sinSum += Math.sin(angles[i] * Math.PI / 180.0);
}
double cosSum = 0.0;
for (int i = 0; i < len; i++) {
cosSum += Math.cos(angles[i] * Math.PI / 180.0);
}
return Math.atan2(sinSum / len, cosSum / len) * 180.0 / Math.PI;
}
/* time string assumed to be in format "hh:mm:ss" */
static int timeToSecs(String t) {
int hours = Integer.parseInt(t.substring(0, 2));
int mins = Integer.parseInt(t.substring(3, 5));
int secs = Integer.parseInt(t.substring(6, 8));
return 3600 * hours + 60 * mins + secs;
}
/* 1 second of time = 360/(24 * 3600) = 1/240th degree */
static double timeToDegrees(String t) {
return timeToSecs(t) / 240.0;
}
static String degreesToTime(double d) {
if (d < 0.0) d += 360.0;
int secs = (int)(d * 240.0);
int hours = secs / 3600;
int mins = secs % 3600;
secs = mins % 60;
mins /= 60;
return String.format("%2d:%2d:%2d", hours, mins, secs);
}
public static void main(String[] args) {
String[] tm = {"23:00:17", "23:40:20", "00:12:45", "00:17:19"};
double[] angles = new double[4];
for (int i = 0; i < 4; i++) angles[i] = timeToDegrees(tm[i]);
double mean = meanAngle(angles);
System.out.println("Average time is : " + degreesToTime(mean));
}
}
- Output:
Average time is : 23:47:43
JavaScript
var args = process.argv.slice(2);
function time_to_seconds( hms ) {
var parts = hms.split(':');
var h = parseInt(parts[0]);
var m = parseInt(parts[1]);
var s = parseInt(parts[2]);
if ( h < 12 ) {
h += 24;
}
var seconds = parseInt(parts[0]) * 60 * 60 + parseInt(parts[1]) * 60 + parseInt(parts[2]);
return seconds;
}
function seconds_to_time( s ) {
var h = Math.floor( s/(60 * 60) );
if ( h < 10 ) {
h = '0' + h;
}
s = s % (60 * 60);
var m = Math.floor( s/60 );
if ( m < 10 ) {
m = '0' + m;
}
s = s % 60
if ( s < 10 ) {
s = '0' + s;
}
return h + ':' + m + ':' + s;
}
var sum = 0, count = 0, idx;
for (idx in args) {
var seconds = time_to_seconds( args[idx] );
sum += seconds;
count++;
}
var seconds = Math.floor( sum / count )
console.log( 'Mean time is ', seconds_to_time(seconds));
- Output:
$ node mean_time.js 23:00:17 23:40:20 00:12:45 00:17:19 Mean time is 23:47:40
jq
The "mean time" of two times that differ by 12 hours (e.g. ["00:00:00", "12:00:00"]) is not very well-defined, and is accordingly computed as null here.
# input: array of "h:m:s"
def mean_time_of_day:
def pi: 4 * (1|atan);
def to_radians: pi * . /(12*60*60);
def from_radians: (. * 12*60*60) / pi;
def secs2time: # produce "hh:mm:ss" string
def pad: tostring | (2 - length) * "0" + .;
"\(./60/60 % 24 | pad):\(./60 % 60 | pad):\(. % 60 | pad)";
def round:
if . < 0 then -1 * ((- .) | round) | if . == -0 then 0 else . end
else floor as $x
| if (. - $x) < 0.5 then $x else $x+1 end
end;
map( split(":")
| map(tonumber)
| (.[0]*3600 + .[1]*60 + .[2])
| to_radians )
| (map(sin) | add) as $y
| (map(cos) | add) as $x
| if $x == 0 then (if $y > 3e-14 then pi/2 elif $y < -3e-14 then -(pi/2) else null end)
else ($y / $x) | atan
end
| if . == null then null
else from_radians
| if (.<0) then . + (24*60*60) else . end
| round
| secs2time
end ;
Examples
["0:0:0", "12:0:0" ],
["0:0:0", "24:0:0" ],
["1:0:0", "1:0:0" ],
["20:0:0", "4:0:0" ],
["20:0:0", "4:0:2" ],
["23:0:0", "23:0:0" ],
["23:00:17", "23:40:20", "00:12:45", "00:17:19"]
| mean_time_of_day
- Output:
$ jq -r -n -f Mean_time_of_day.jq
null
00:00:00
01:00:00
00:00:00
00:00:01
23:00:00
23:47:43
Julia
using Statistics
function meantime(times::Array, dlm::String=":")
c = π / (12 * 60 * 60)
a = map(x -> parse.(Int, x), split.(times, dlm))
ϕ = collect(3600t[1] + 60t[2] + t[3] for t in a)
d = angle(mean(exp.(c * im * ϕ))) / 2π # days
if d < 0 d += 1 end
# Convert to h:m:s
h = trunc(Int, d * 24)
m = trunc(Int, d * 24 * 60) - h * 60
s = trunc(Int, d * 24 * 60 * 60) - h * 60 * 60 - m * 60
return "$h:$m:$s"
end
times = String["23:00:17", "23:40:20", "00:12:45", "00:17:19"]
mtime = meantime(times)
println("Times:")
println.(times)
println("Mean: $mtime")
- Output:
Times: 23:00:17 23:40:20 00:12:45 00:17:19 Mean: 23:47:43
Kotlin
// version 1.0.6
fun meanAngle(angles: DoubleArray): Double {
val sinSum = angles.sumByDouble { Math.sin(it * Math.PI / 180.0) }
val cosSum = angles.sumByDouble { Math.cos(it * Math.PI / 180.0) }
return Math.atan2(sinSum / angles.size, cosSum / angles.size) * 180.0 / Math.PI
}
/* time string assumed to be in format "hh:mm:ss" */
fun timeToSecs(t: String): Int {
val hours = t.slice(0..1).toInt()
val mins = t.slice(3..4).toInt()
val secs = t.slice(6..7).toInt()
return 3600 * hours + 60 * mins + secs
}
/* 1 second of time = 360/(24 * 3600) = 1/240th degree */
fun timeToDegrees(t: String): Double = timeToSecs(t) / 240.0
fun degreesToTime(d: Double): String {
var dd = d
if (dd < 0.0) dd += 360.0
var secs = (dd * 240.0).toInt()
val hours = secs / 3600
var mins = secs % 3600
secs = mins % 60
mins /= 60
return String.format("%2d:%2d:%2d", hours, mins, secs)
}
fun main(args: Array<String>) {
val tm = arrayOf("23:00:17", "23:40:20", "00:12:45", "00:17:19")
val angles = DoubleArray(4) { timeToDegrees(tm[it]) }
val mean = meanAngle(angles)
println("Average time is : ${degreesToTime(mean)}")
}
- Output:
Average time is : 23:47:43
Liberty BASIC
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
- Output:
Average of: 23:00:17 23:40:20 00:12:45 00:17:19 is 23:47:43
Lua
local times = {"23:00:17","23:40:20","00:12:45","00:17:19"}
-- returns time converted to a radian format
local function timeToAngle(str)
local h,m,s = str:match("(..):(..):(..)")
return (h + m / 60 + s / 3600)/12 * math.pi
end
-- computes the mean of the angles inside a list
local function meanAngle(angles)
local sumSin,sumCos = 0,0
for k,v in pairs(angles) do
sumSin = sumSin + math.sin(v)
sumCos = sumCos + math.cos(v)
end
return math.atan2(sumSin,sumCos)
end
-- converts and angle back to a time string
local function angleToTime(angle)
local abs = angle % (math.pi * 2)
local time = abs / math.pi * 12
local h = math.floor(time)
local m = math.floor(time * 60) % 60
local s = math.floor(time * 3600) % 60
return string.format("%02d:%02d:%02d", h, m, s)
end
-- convert times to angles
for k,v in pairs(times) do
times[k] = timeToAngle(v)
end
print(angleToTime(meanAngle(times)))
- Output:
23:47:43
Mathematica / Wolfram Language
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"}]
- Output:
23:47:43
MATLAB / Octave
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;
mean_time_of_day({'23:00:17', '23:40:20', '00:12:45', '00:17:19'}) ans = 23:47:43
Nim
import math, complex, strutils, sequtils
proc meanAngle(deg: openArray[float]): float =
var c: Complex[float]
for d in deg:
c += rect(1.0, degToRad(d))
radToDeg(phase(c / float(deg.len)))
proc meanTime(times: openArray[string]): string =
const day = 24 * 60 * 60
let
angles = times.map(proc(time: string): float =
let t = time.split(":")
(t[2].parseInt + t[1].parseInt * 60 + t[0].parseInt * 3600) * 360 / day)
ms = (angles.meanAngle * day / 360 + day) mod day
(h,m,s) = (ms.int div 3600, (ms.int mod 3600) div 60, ms.int mod 60)
align($h, 2, '0') & ":" & align($m, 2, '0') & ":" & align($s, 2, '0')
echo meanTime(["23:00:17", "23:40:20", "00:12:45", "00:17:19"])
- Output:
23:47:43
Oberon-2
MODULE AvgTimeOfDay;
IMPORT
M := LRealMath,
T := NPCT:Tools,
Out := NPCT:Console;
CONST
secsDay = 86400;
secsHour = 3600;
secsMin = 60;
toRads = M.pi / 180;
VAR
h,m,s: LONGINT;
data: ARRAY 4 OF LONGREAL;
PROCEDURE TimeToDeg(time: STRING): LONGREAL;
VAR
parts: ARRAY 3 OF STRING;
h,m,s: LONGREAL;
BEGIN
T.Split(time,':',parts);
h := T.StrToInt(parts[0]);
m := T.StrToInt(parts[1]);
s := T.StrToInt(parts[2]);
RETURN (h * secsHour + m * secsMin + s) * 360 / secsDay;
END TimeToDeg;
PROCEDURE DegToTime(d: LONGREAL; VAR h,m,s: LONGINT);
VAR
ds: LONGREAL;
PROCEDURE Mod(x,y: LONGREAL): LONGREAL;
VAR
c: LONGREAL;
BEGIN
c := ENTIER(x / y);
RETURN x - c * y
END Mod;
BEGIN
ds := Mod(d,360.0) * secsDay / 360.0;
h := ENTIER(ds / secsHour);
m := ENTIER(Mod(ds,secsHour) / secsMin);
s := ENTIER(Mod(ds,secsMin));
END DegToTime;
PROCEDURE Mean(g: ARRAY OF LONGREAL): LONGREAL;
VAR
i,l: LONGINT;
sumSin, sumCos: LONGREAL;
BEGIN
i := 0;l := LEN(g);sumSin := 0.0;sumCos := 0.0;
WHILE i < l DO
sumSin := sumSin + M.sin(g[i] * toRads);
sumCos := sumCos + M.cos(g[i] * toRads);
INC(i)
END;
RETURN M.arctan2(sumSin / l,sumCos / l) * 180 / M.pi;
END Mean;
BEGIN
data[0] := TimeToDeg("23:00:17");
data[1] := TimeToDeg("23:40:20");
data[2] := TimeToDeg("00:12:45");
data[3] := TimeToDeg("00:17:19");
DegToTime(Mean(data),h,m,s);
Out.String(":> ");Out.Int(h,0);Out.Char(':');Out.Int(m,0);Out.Char(':');Out.Int(s,0);Out.Ln
END AvgTimeOfDay.
- Output:
:> 23:47:43
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)))
- Output:
The mean time of [23:00:17; 23:40:20; 00:12:45; 00:17:19] is: 23:47:43
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
- Output:
23:47:43
PARI/GP
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]])
- Output:
[23, 47, 43]
Perl
Traditional
Using the core module Math::Complex
to enable use of complex numbers. The POSIX
CPAN module provides the fmod
routine for non-integer modulus calculations.
use strict;
use warnings;
use POSIX 'fmod';
use Math::Complex;
use List::Util qw(sum);
use utf8;
use constant τ => 2 * 3.1415926535;
# time-of-day to radians
sub tod2rad {
($h,$m,$s) = split /:/, @_[0];
(3600*$h + 60*$m + $s) * τ / 86400;
}
# radians to time-of-day
sub rad2tod {
my $x = $_[0] * 86400 / τ;
sprintf '%02d:%02d:%02d', fm($x/3600,24), fm($x/60,60), fm($x,60);
}
# float modulus, normalized to positive values
sub fm {
my($n,$b) = @_;
$x = fmod($n,$b);
$x += $b if $x < 0;
}
sub phase { arg($_[0]) } # aka theta
sub cis { cos($_[0]) + i*sin($_[0]) }
sub mean_time { rad2tod phase sum map { cis tod2rad $_ } @_ }
@times = ("23:00:17", "23:40:20", "00:12:45", "00:17:19");
print mean_time(@times) . " is the mean time of " . join(' ', @times) . "\n";
- Output:
23:47:43 is the mean time of 23:00:17 23:40:20 00:12:45 00:17:19
v5.36
As previous, but using features from an up-to-date release of Perl, e.g. strict/warn/subroutine signatures without the use
boilerplate.
use v5.36;
use POSIX 'fmod';
use Math::Complex;
use List::Util 'sum';
use utf8;
use constant τ => 2 * 2 * atan2(1, 0);
sub R_to_ToD ($radians) { my $x = $radians * 86400 / τ; sprintf '%02d:%02d:%02d', fm($x/3600,24), fm($x/60,60), fm($x,60) }
sub ToD_to_R ($h,$m,$s) { (3600*$h + 60*$m + $s) * τ / 86400 }
sub fm ($n,$b) { my $x = fmod($n,$b); $x += $b if $x < 0 }
sub cis ($radians) { cos($radians) + i*sin($radians) }
sub phase ($Θ) { arg( $Θ ) }
sub mean_time(@t) { R_to_ToD phase sum map { cis ToD_to_R split ':', $_ } @t }
my @times = <23:00:17 23:40:20 00:12:45 00:17:19>;
say my $result = mean_time(@times) . ' is the mean time of ' . join ' ', @times;
- Output:
23:47:43 is the mean time of 23:00:17 23:40:20 00:12:45 00:17:19
Phix
with javascript_semantics function MeanAngle(sequence angles) atom x = 0, y = 0 for i=1 to length(angles) do atom ai_rad = angles[i]*PI/180 x += cos(ai_rad) y += sin(ai_rad) end for if abs(x)<1e-16 then return "not meaningful" end if return atan2(y,x)*180/PI end function function toSecAngle(integer hours, integer minutes, integer seconds) return ((hours*60+minutes)*60+seconds)/(24*60*60)*360 end function constant Times = {toSecAngle(23,00,17), toSecAngle(23,40,20), toSecAngle(00,12,45), toSecAngle(00,17,19)} function toHMS(object s) if not string(s) then if s<0 then s+=360 end if s = 24*60*60*s/360 atom hours = floor(s/3600), mins = floor(remainder(s,3600)/60), secs = remainder(s,60) s = sprintf("%02d:%02d:%02d",{hours,mins,secs}) end if return s end function printf(1,"Mean Time is %s\n",{toHMS(MeanAngle(Times))})
- Output:
Mean Time is 23:47:43
PHP
<?php
function time2ang($tim) {
if (!is_string($tim)) return $tim;
$parts = explode(':',$tim);
if (count($parts)!=3) return $tim;
$sec = ($parts[0]*3600)+($parts[1]*60)+$parts[2];
$ang = 360.0 * ($sec/86400.0);
return $ang;
}
function ang2time($ang) {
if (!is_numeric($ang)) return $ang;
$sec = 86400.0 * $ang / 360.0;
$parts = array(floor($sec/3600),floor(($sec % 3600)/60),$sec % 60);
$tim = sprintf('%02d:%02d:%02d',$parts[0],$parts[1],$parts[2]);
return $tim;
}
function meanang($ang) {
if (!is_array($ang)) return $ang;
$sins = 0.0;
$coss = 0.0;
foreach($ang as $a) {
$sins += sin(deg2rad($a));
$coss += cos(deg2rad($a));
}
$avgsin = $sins / (0.0+count($ang));
$avgcos = $coss / (0.0+count($ang));
$avgang = rad2deg(atan2($avgsin,$avgcos));
while ($avgang < 0.0) $avgang += 360.0;
return $avgang;
}
$bats = array('23:00:17','23:40:20','00:12:45','00:17:19');
$angs = array();
foreach ($bats as $t) $angs[] = time2ang($t);
$ma = meanang($angs);
$result = ang2time($ma);
print "The mean time of day is $result (angle $ma).\n";
?>
- Output:
The mean time of day is 23:47:43 (angle 356.9306730355).
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) ) )
- Test:
: (meanTime '("23:00:17" "23:40:20" "00:12:45" "00:17:19"))
-> "23:47:43"
PL/I
*process source attributes xref;
avt: Proc options(main);
/*--------------------------------------------------------------------
* 25.06.2014 Walter Pachl taken from REXX
*-------------------------------------------------------------------*/
Dcl (addr,hbound,sin,cos,atan) Builtin;
Dcl sysprint Print;
Dcl times(4) Char(8) Init('23:00:17','23:40:20','00:12:45','00:17:19');
Dcl time Char(8);
Dcl (alpha,x,y,ss,ww) Dec Float(18) Init(0);
Dcl day Bin Fixed(31) Init(86400);
Dcl pi Dec Float(18) Init(3.14159265358979323846);
Dcl (i,h,m,s) bin Fixed(31) Init(0);
Do i=1 To hbound(times); /* loop over times */
time=times(i); /* pick a time */
alpha=t2a(time); /* convert to angle (radians) */
x=x+sin(alpha); /* accumulate sines */
y=y+cos(alpha); /* accumulate cosines */
End;
ww=atan(x/y); /* compute average angle */
ss=ww*day/(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;
Put Edit(h,':',m,':',s)(Skip,3(p'99',a));
t2a: Procedure(t) Returns(Bin Float(18)); /* convert time to angle */
Dcl t Char(8);
Dcl 1 tt Based(addr(t)),
2 hh Pic'99',
2 * Char(1),
2 mm Pic'99',
2 * Char(1),
2 ss Pic'99';
Dcl sec Bin Fixed(31);
Dcl a Bin Float(18);
sec=(hh*60+mm)*60+ss;
If sec>(day/2) Then
sec=sec-day;
a=2*pi*sec/day;
Return (a);
End;
End;
- Output:
23:47:43
PowerShell
function Get-MeanTimeOfDay
{
[CmdletBinding()]
[OutputType([timespan])]
Param
(
[Parameter(Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)]
[ValidatePattern("(?:2[0-3]|[01]?[0-9])[:.][0-5]?[0-9][:.][0-5]?[0-9]")]
[string[]]
$Time
)
Begin
{
[double[]]$angles = @()
function ConvertFrom-Time ([timespan]$Time)
{
[double]((360 * $Time.Hours / 24) + (360 * $Time.Minutes / (24 * 60)) + (360 * $Time.Seconds / (24 * 3600)))
}
function ConvertTo-Time ([double]$Angle)
{
$t = New-TimeSpan -Hours ([int](24 * 60 * 60 * $Angle / 360) / 3600) `
-Minutes (([int](24 * 60 * 60 * $Angle / 360) % 3600 - [int](24 * 60 * 60 * $Angle / 360) % 60) / 60) `
-Seconds ([int]((24 * 60 * 60 * $Angle / 360) % 60))
if ($t.Days -gt 0)
{
return ($t - (New-TimeSpan -Hours 1))
}
$t
}
function Get-MeanAngle ([double[]]$Angles)
{
[double]$x,$y = 0
for ($i = 0; $i -lt $Angles.Count; $i++)
{
$x += [Math]::Cos($Angles[$i] * [Math]::PI / 180)
$y += [Math]::Sin($Angles[$i] * [Math]::PI / 180)
}
$result = [Math]::Atan2(($y / $Angles.Count), ($x / $Angles.Count)) * 180 / [Math]::PI
if ($result -lt 0)
{
return ($result + 360)
}
$result
}
}
Process
{
$angles += ConvertFrom-Time $_
}
End
{
ConvertTo-Time (Get-MeanAngle $angles)
}
}
[timespan]$meanTimeOfDay = "23:00:17","23:40:20","00:12:45","00:17:19" | Get-MeanTimeOfDay
"Mean time is {0}" -f (Get-Date $meanTimeOfDay.ToString()).ToString("hh:mm:ss tt")
- Output:
Mean time is 11:47:43 PM
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"]) )
- Output:
23:47:43
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"))
- Output:
"23:47:43"
Raku
(formerly Perl 6)
sub tod2rad($_) { [+](.comb(/\d+/) Z* 3600,60,1) * tau / 86400 }
sub rad2tod ($r) {
my $x = $r * 86400 / tau;
(($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 }
my @times = ["23:00:17", "23:40:20", "00:12:45", "00:17:19"];
say "{ mean-time(@times) } is the mean time of @times[]";
- Output:
23:47:43 is the mean time of 23:00:17 23:40:20 00:12:45 00:17:19
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
pi=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
- Output:
23:47:43
RPL
≪ → angles ≪ 0 1 angles SIZE FOR j 1 angles j GET R→C P→R + NEXT angles SIZE / ARG ≫ ≫ 'MEANG' STO
≪ → times ≪ { } 1 times SIZE FOR j 1 times j GET HMS→ 15 * + NEXT MEANG 15 / 24 MOD →HMS 4 FIX RND STD ≫ ≫ 'MTIME' STO
{23.0017 23.4020 0.1245 0.1719 } MTIME
- Output:
1: 23.4743
Ruby
Using the methods at [angle]
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"]
- Output:
23:47:43
Run BASIC
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)
if y <> 0 then
atan2 = (2 * (atn((sqr((x * x) + (y * y)) - x)/ y)))
else
atan2 = (y=0)*(x<0)*pi
end if
End Function
Rust
use std::f64::consts::PI;
#[derive(Debug, PartialEq, Eq)]
struct Time {
h: u8,
m: u8,
s: u8,
}
impl Time {
/// Create a Time from equivalent radian measure
fn from_radians(mut rads: f64) -> Time {
rads %= 2.0 * PI;
if rads < 0.0 {
rads += 2.0 * PI
}
Time {
h: (rads * 12.0 / PI) as u8,
m: ((rads * 720.0 / PI) % 60.0) as u8,
s: ((rads * 43200.0 / PI) % 60.0).round() as u8,
}
}
/// Create a Time from H/M/S
fn from_parts(h: u8, m: u8, s: u8) -> Result<Time, ()> {
if h > 23 || m > 59 || s > 59 {
return Err(());
}
Ok(Time { h, m, s })
}
/// Return time as measure in radians
fn as_radians(&self) -> f64 {
((self.h as f64 / 12.0) + (self.m as f64 / 720.0) + (self.s as f64 / 43200.0)) * PI
}
}
/// Compute the mean time from a slice of times
fn mean_time(times: &[Time]) -> Time {
// compute sum of sines and cosines
let (ss, sc) = times
.iter()
.map(Time::as_radians)
.map(|a| (a.sin(), a.cos()))
.fold((0.0, 0.0), |(ss, sc), (s, c)| (ss + s, sc + c));
// scaling does not matter for atan2, meaning we do not have to divide sums by len
Time::from_radians(ss.atan2(sc))
}
fn main() {
let times = [
Time::from_parts(23, 00, 17).unwrap(),
Time::from_parts(23, 40, 20).unwrap(),
Time::from_parts(00, 12, 45).unwrap(),
Time::from_parts(00, 17, 19).unwrap(),
];
let mean = mean_time(×);
println!("{:02}:{:02}:{:02}", mean.h, mean.m, mean.s);
}
- Output:
23:47:43
Scala
import java.time.LocalTime
import scala.compat.Platform
trait MeanAnglesComputation {
import scala.math.{Pi, atan2, cos, 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 {
val dayInSeconds = 60 * 60 * 24
def times = batTimes.map(t => afterMidnight(t).toDouble)
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")
assert(LocalTime.MIN.plusSeconds(meanAngle(times, dayInSeconds).round).toString == "23:47:40")
println(s"Successfully completed without errors. [total ${Platform.currentTime - executionStart} ms]")
}
Scheme
To be self-contained, this starts with the functions from Averages/Mean angle
(import (scheme base)
(scheme inexact)
(scheme read)
(scheme write)
(srfi 1)) ; for fold
;; functions copied from "Averages/Mean angle" task
(define (average l)
(/ (fold + 0 l) (length l)))
(define pi 3.14159265358979323846264338327950288419716939937510582097)
(define (radians a)
(* pi 1/180 a))
(define (degrees a)
(* 180 (/ 1 pi) a))
(define (mean-angle angles)
(let* ((angles (map radians angles))
(cosines (map cos angles))
(sines (map sin angles)))
(degrees (atan (average sines) (average cosines)))))
;; -- new functions for this task
(define (time->angle time)
(let* ((time2 ; replaces : with space in string
(string-map (lambda (c) (if (char=? c #\:) #\space c)) time))
(string-port (open-input-string time2))
(hour (read string-port))
(minutes (read string-port))
(seconds (read string-port)))
(/ (* 360 (+ (* hour 3600) (* minutes 60) seconds))
(* 24 60 60))))
(define (angle->time angle)
(let* ((nom-angle (if (negative? angle) (+ 360 angle) angle))
(time (/ (* nom-angle 24 60 60) 360))
(hour (exact (floor (/ time 3600))))
(minutes (exact (floor (/ (- time (* 3600 hour)) 60))))
(seconds (exact (floor (- time (* 3600 hour) (* 60 minutes))))))
(string-append (number->string hour)
":"
(number->string minutes)
":"
(number->string seconds))))
(define (mean-time-of-day times)
(angle->time (mean-angle (map time->angle times))))
(write (mean-time-of-day '("23:00:17" "23:40:20" "00:12:45" "00:17:19")))
(newline)
- Output:
"23:47:43"
Sidef
Using the mean_angle() function from: "Averages/Mean angle"
func time2deg(t) {
(var m = t.match(/^(\d\d):(\d\d):(\d\d)$/)) || die "invalid time"
var (hh,mm,ss) = m.cap.map{.to_i}...
((hh ~~ 24.range) && (mm ~~ 60.range) && (ss ~~ 60.range)) || die "invalid time"
(hh*3600 + mm*60 + ss) * 360 / 86400
}
func deg2time(d) {
var sec = ((d % 360) * 86400 / 360)
"%02d:%02d:%02d" % (sec/3600, (sec%3600)/60, sec%60)
}
func mean_time(times) {
deg2time(mean_angle(times.map {|t| time2deg(t)}))
}
say mean_time(["23:00:17", "23:40:20", "00:12:45", "00:17:19"])
- Output:
23:47:43
SQL/PostgreSQL
--Setup table for testing
CREATE TABLE time_table(times time);
INSERT INTO time_table values ('23:00:17'::time),('23:40:20'::time),('00:12:45'::time),('00:17:19'::time)
--Compute mean time
SELECT to_timestamp((degrees(atan2(AVG(sin),AVG(cos))))* (24*60*60)/360)::time
FROM
(SELECT
cos(radians(t*360/(24*60*60))),sin(radians(t*360/(24*60*60)))
FROM
(SELECT EXTRACT(epoch from times) t
FROM time_table) T1
)T2
Output:
23:47:43.361529
Swift
import Foundation
@inlinable public func d2r<T: FloatingPoint>(_ f: T) -> T { f * .pi / 180 }
@inlinable public func r2d<T: FloatingPoint>(_ f: T) -> T { f * 180 / .pi }
public func meanOfAngles(_ angles: [Double]) -> Double {
let cInv = 1 / Double(angles.count)
let (y, x) =
angles.lazy
.map(d2r)
.map({ (sin($0), cos($0)) })
.reduce(into: (0.0, 0.0), { $0.0 += $1.0; $0.1 += $1.1 })
return r2d(atan2(cInv * y, cInv * x))
}
struct DigitTime {
var hour: Int
var minute: Int
var second: Int
init?(fromString str: String) {
let split = str.components(separatedBy: ":").compactMap(Int.init)
guard split.count == 3 else {
return nil
}
(hour, minute, second) = (split[0], split[1], split[2])
}
init(fromDegrees angle: Double) {
let totalSeconds = 24 * 60 * 60 * angle / 360
second = Int(totalSeconds.truncatingRemainder(dividingBy: 60))
minute = Int((totalSeconds.truncatingRemainder(dividingBy: 3600) - Double(second)) / 60)
hour = Int(totalSeconds / 3600)
}
func toDegrees() -> Double {
return 360 * Double(hour) / 24.0 + 360 * Double(minute) / (24 * 60.0) + 360 * Double(second) / (24 * 3600.0)
}
}
extension DigitTime: CustomStringConvertible {
var description: String { String(format: "%02i:%02i:%02i", hour, minute, second) }
}
let times = ["23:00:17", "23:40:20", "00:12:45", "00:17:19"].compactMap(DigitTime.init(fromString:))
guard times.count == 4 else {
fatalError()
}
let meanTime = DigitTime(fromDegrees: 360 + meanOfAngles(times.map({ $0.toDegrees() })))
print("Given times \(times), the mean time is \(meanTime)")
- Output:
Given times [23:00:17, 23:40:20, 00:12:45, 00:17:19], the mean time is 23:47:43
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}]
- Output:
23:47:43
VBA
Uses Excel and mean angle.
Public Sub mean_time()
Dim angles() As Double
s = [{"23:00:17","23:40:20","00:12:45","00:17:19"}]
For i = 1 To UBound(s)
s(i) = 360 * TimeValue(s(i))
Next i
Debug.Print Format(mean_angle(s) / 360 + 1, "hh:mm:ss")
End Sub
- Output:
23:47:43
Visual Basic .NET
Module Module1
Function TimeToDegrees(time As TimeSpan) As Double
Return 360 * time.Hours / 24.0 + 360 * time.Minutes / (24 * 60.0) + 360 * time.Seconds / (24 * 3600.0)
End Function
Function DegreesToTime(angle As Double) As TimeSpan
Return New TimeSpan((24 * 60 * 60 * angle \ 360) \ 3600, ((24 * 60 * 60 * angle \ 360) Mod 3600 - (24 * 60 * 60 * angle \ 360) Mod 60) \ 60, (24 * 60 * 60 * angle \ 360) Mod 60)
End Function
Function MeanAngle(angles As List(Of Double)) As Double
Dim y_part = 0.0
Dim x_part = 0.0
Dim numItems = angles.Count
For Each angle In angles
x_part += Math.Cos(angle * Math.PI / 180)
y_part += Math.Sin(angle * Math.PI / 180)
Next
Return Math.Atan2(y_part / numItems, x_part / numItems) * 180 / Math.PI
End Function
Sub Main()
Dim digitimes As New List(Of Double)
Dim digitime As TimeSpan
Dim input As String
Console.WriteLine("Enter times, end with no input: ")
Do
input = Console.ReadLine
If Not String.IsNullOrWhiteSpace(input) Then
If TimeSpan.TryParse(input, digitime) Then
digitimes.Add(TimeToDegrees(digitime))
Else
Console.WriteLine("Seems this is wrong input: ingnoring time")
End If
End If
Loop Until String.IsNullOrWhiteSpace(input)
If digitimes.Count > 0 Then
Console.WriteLine("The mean time is : {0}", DegreesToTime(360 + MeanAngle(digitimes)))
End If
End Sub
End Module
- 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
V (Vlang)
import math
const inputs = ["23:00:17", "23:40:20", "00:12:45", "00:17:19"]
fn main() {
angles := inputs.map(time_to_degs(it))
println('Mean time of day is: ${degs_to_time(mean_angle(angles))}')
}
fn mean_angle(angles []f64) f64 {
n := angles.len
mut sin_sum := f64(0)
mut cos_sum := f64(0)
for angle in angles {
sin_sum += math.sin(angle * math.pi / 180)
cos_sum += math.cos(angle * math.pi / 180)
}
return math.atan2(sin_sum/n, cos_sum/n) * 180 / math.pi
}
fn degs_to_time(dd f64) string{
mut d := dd
for d < 0 {
d += 360
}
mut s := math.round(d * 240)
h := math.floor(s/3600)
mut m := math.fmod(s, 3600)
s = math.fmod(m, 60)
m = math.floor(m / 60)
return "${h:02}:${m:02}:${s:02}"
}
fn time_to_degs(time string) f64 {
t := time.split(":")
h := t[0].f64() * 3600
m := t[1].f64() * 60
s := t[2].f64()
return (h + m + s) / 240
}
- Output:
Mean time of day is: 23:47:43
Wren
import "./fmt" for Fmt
var timeToDegs = Fn.new { |time|
var t = time.split(":")
var h = Num.fromString(t[0]) * 3600
var m = Num.fromString(t[1]) * 60
var s = Num.fromString(t[2])
return (h + m + s) / 240
}
var degsToTime = Fn.new { |d|
while (d < 0) d = d + 360
var s = (d * 240).round
var h = (s/3600).floor
var m = s % 3600
s = m % 60
m = (m / 60).floor
return Fmt.swrite("$2d:$2d:$2d", h, m, s)
}
var meanAngle = Fn.new { |angles|
var n = angles.count
var sinSum = 0
var cosSum = 0
for (angle in angles) {
sinSum = sinSum + (angle * Num.pi / 180).sin
cosSum = cosSum + (angle * Num.pi / 180).cos
}
return (sinSum/n).atan(cosSum/n) * 180 / Num.pi
}
var times = ["23:00:17", "23:40:20", "00:12:45", "00:17:19"]
var angles = times.map { |t| timeToDegs.call(t) }.toList
System.print("Mean time of day is : %(degsToTime.call(meanAngle.call(angles)))")
- Output:
Mean time of day is : 23:47:43
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]]))
- Output:
23:47:43
Yabasic
sub atan2(y, x)
return 2 * atan((sqrt(x **2 + y ** 2) - x) / y)
end sub
sub MeanAngle(angles())
local x, y, ai_rad, l, i
l = arraysize(angles(), 1)
for i = 1 to l
ai_rad = angles(i) * PI / 180
x = x + cos(ai_rad)
y = y + sin(ai_rad)
next i
if abs(x) < 1e-16 return false
return atan2(y, x) * 180 / PI
end sub
sub toSecAngle(hours, minutes, seconds)
return ((hours * 60 + minutes) * 60 + seconds) / (24 * 60 * 60) * 360
end sub
dim Times(4)
Times(1) = toSecAngle(23,00,17)
Times(2) = toSecAngle(23,40,20)
Times(3) = toSecAngle(00,12,45)
Times(4) = toSecAngle(00,17,19)
sub toHMS$(t)
local s$
if t then
if t < 0 t = t + 360
t = 24 * 60 * 60 * t / 360
s$ = str$(int(t / 3600), "%02g") + ":" + str$(int(mod(t, 3600) / 60), "%02g") + ":" + str$(int(mod(t, 60)), "%02g")
else
s$ = "not meaningful"
end if
return s$
end sub
print "Mean Time is ", toHMS$(MeanAngle(Times()))
// Output: Mean Time is 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.
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(":")
}
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
- Programming Tasks
- Date and time
- 11l
- Action!
- Action! Tool Kit
- Action! Real Math
- Ada
- ALGOL 68
- AutoHotkey
- AWK
- BBC BASIC
- C
- C sharp
- C++
- Common Lisp
- D
- Delphi
- System.SysUtils
- System.Math
- EasyLang
- EchoLisp
- Erlang
- Euphoria
- F Sharp
- Factor
- Fortran
- FreeBASIC
- Go
- Groovy
- Haskell
- Icon
- Unicon
- J
- Java
- JavaScript
- Jq
- Julia
- Kotlin
- Liberty BASIC
- Lua
- Mathematica
- Wolfram Language
- MATLAB
- Octave
- Nim
- Oberon-2
- OCaml
- OoRexx
- PARI/GP
- Perl
- Phix
- PHP
- PicoLisp
- PL/I
- PowerShell
- Python
- Racket
- Raku
- REXX
- RPL
- Ruby
- Run BASIC
- Rust
- Scala
- Java.time.LocalTime
- Scheme
- Scheme/SRFIs
- Sidef
- SQL
- PostgreSQL
- Swift
- Tcl
- VBA
- Visual Basic .NET
- V (Vlang)
- Wren
- Wren-fmt
- XPL0
- Yabasic
- Zkl