A Clock Problem

One of the best ways to improve your programming ability is to appreciate the fact that there are so many ways to express the solution a single problem, including ways that might surprise you, and that programming ideas go way beyond the syntax of the very first language you learned.

A Challenge

Canvas isn’t supported on this browser.

Animation adapted from Mozilla

Phil Dorin created the following interesting problem: Determine the times in which the hour and minute hand of a 12-hour analog clock are antiparallel, and list them, in order, using the 12-hour U.S. style, producing the following output:

12:32:43
01:38:10
02:43:38
03:49:05
04:54:32
06:00:00
07:05:27
08:10:54
09:16:21
10:21:49
11:27:16

The answers must be computed, not hard-coded. There are two main approaches to this problem:

Here we’ll produce analytic solutions to the problem in 42 different languages. Sometimes we’ll make use of library routines to generate and format times, and sometimes we’ll compute hour, minute, and section fields using basic arithmetic only. We’ll go for really short, comment-free hacks with outrageous violations of proper coding styles, just to make the answers short. Our goal is to just show snippets of many different languages.

The Solutions

 

python-logo.png

In Python, using the time module:

  import time
  for h in range(0, 11):
      print(time.strftime('%I:%M:%S', time.gmtime((h+0.5) * 43200.0/11)))

Calculating the time components ourselves:

for i in range(0, 11):
    t = int((i + 0.5) * 43200.0 / 11)
    h, t = divmod(t, 3600)
    m, s = divmod(t, 60)
    print(f'{(h if h else 12):02}:{m:02}:{s:02}')

On the command line:

python3 -c 'import sys,time;[sys.stdout.write(time.strftime("%I:%M:%S",\
    time.gmtime((i + 0.5) * 43200 / 11))+"\n") for i in range(0, 11)]'
 

ruby-logo.png

Thanks to class Time being built-in, in Ruby, we have a true one-liner:

0.upto(10) {|i| puts((Time.gm(0) + (i + 0.5) * 43200 / 11).strftime('%I:%M:%S'))}

Calculating the time components ourselves:

0.upto 10 do |i|
  t = (i + 0.5) * 43200 / 11
  h, t = t.divmod 3600
  m, s = t.divmod 60
  printf("%02d:%02d:%02d\n", (h == 0 ? 12 : h), m, s)
end

Directly from the command line:

ruby -e '0.upto(10) {|i| puts((Time.gm(0) + (i + 0.5) * 43200 / 11).strftime("%I:%M:%S"))}'
 

lua-logo.png

Lua has an os module with time and date functions:

for i = 0, 10 do
  print(os.date("!%I:%M:%S", math.floor((i + 0.5) * 43200 / 11)))
end

This can even be on one line:

for i = 0, 10 do print(os.date("!%I:%M:%S", math.floor((i + 0.5) * 43200 / 11))) end

Here is the do-it-yourself formatting version:

for i = 0, 10 do
  local t = math.floor((i + 0.5) * 43200 / 11)
  local h = t // 3600
  local m = t % 3600
  print(string.format("%02d:%02d:%02d", (h < 1 and 12 or h), m // 60, m % 60))
end

And directly on the command line:

lua -e 'for i = 0, 10 do print(os.date("!%I:%M:%S", math.floor((i + 0.5) * 43200 / 11))) end'
 

tcl-logo.png

This Tcl solution is due to B.J. Johnson:

for {set i 0} {$i < 11} {incr i} {
    puts [clock format [expr int(($i + 0.5) * 43200 / 11)] -format %I:%M:%S]
}
 

perl-logo.jpeg

Perl time! Using the POSIX module for time formatting:

use POSIX 'strftime';
print strftime("%I:%M:%S", gmtime(($_ + 0.5) * 43200 / 11))."\n" for (0..10);

Calculating and formatting the time components ourselves:

for my $i (0..10) {
    my $t = int(($i + 0.5) * 43200 / 11);
    my $h = int($t / 3600);
    my $m = $t % 3600;
    printf("%02d:%02d:%02d\n", ($h ? $h : 12), $m / 60, $m % 60);
}

Passing the program as a command line argument:

perl -MPOSIX -le 'print strftime("%I:%M:%S", gmtime(($_ + 0.5) * 43200 / 11)) for (0..10)'
 

awk-logo.png

Here it is in AWK, under the do-it-yourself way:

BEGIN {
    for (i = 0; i < 11; i++) {
        t = int((i + 0.5) * 43200.0 / 11)
        h = int(t / 3600)
        m = int(t % 3600)
        printf "%02d:%02d:%02d\n", (h ? h : 12), m / 60, m % 60
    }
}

The GNU AWK dialect (that’s the AWK you get on GNU-based systems, Ubuntu, Debian, etc., and not macOS) has strftime built-in:

BEGIN {
    for (i = 0; i < 11; i++) {
        print strftime("%I:%M:%S", (i+0.5) * 43200.0/11, 1)
    }
}
 

c-logo.png

The C standard library for creating a time structure allocates the structure, so we need code to free that memory. The library code for formatting the time writes into a buffer that we have to specify a bound for. That’s systems programming for you.

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
    for (int i = 0; i < 11; i++) {
        char s[9];
        time_t t = (time_t)((int)((i + 0.5) * 43200.0 / 11));
        struct tm *st = gmtime(&t);
        strftime(s, 9, "%I:%M:%S", st);
        free(st);
        printf("%s\n",s);
    }
    return 0;
}

Perhaps surprisingly, eschewing the library leads to smaller code:

#include <stdio.h>
int main() {
    for (int i = 0; i < 11; i++) {
        int t = (i + 0.5) * 43200.0 / 11, h = t / 3600, m = t % 3600;
        printf("%02d:%02d:%02d\n", (h ? h : 12), m / 60, m % 60);
    }
    return 0;
}
 

cpp-logo.png

Most C programs are C++ programs, so we could take the C program above and change the include of <stdio.h> to <cstdio> and it would run fine. Or, we can use C++ streams for output:

#include <iostream>
#include <iomanip>
using namespace std;

int main() {
    for (auto i = 0; i < 11; i++) {
        int t = (i + 0.5) * 43200.0 / 11, h = t / 3600, m = t % 3600;
        cout << setfill('0') << setw(2) << (h ? h : 12)
             << ':' << setw(2) << (m / 60)
             << ':' << setw(2) << (m % 60)
             << endl;
    }
    return 0;
}
 

d-logo.png

D looks a little like C:

import core.stdc.stdio;

int main() {
    for (int i = 0; i < 11; i++) {
        int t = cast(int)((cast(double)i + 0.5) * 43200.0 / 11.0);
        int h = t / 3600;
        int m = t % 3600;
        printf("%02d:%02d:%02d\n", (h ? h : 12), m / 60, m % 60);
    }
    return 0;
}
 

rust-logo.png

I only have the do-it yourself version in Rust for now:

fn main() {
    for i in 0..11 {
        let t = (((i as f64) + 0.5) * 43200.0 / 11.0) as i32;
        let h = t / 3600;
        let m = t % 3600;
        println!("{:02}:{:02}:{:02}", if h == 0 {12} else {h}, m / 60, m % 60);
    }
}
 

go-logo.png

Just the do-it yourself version for now:

package main
import "fmt"
func main() {
    for i := 0; i < 11; i++ {
        t := int64((float64(i) + 0.5) * 43200.0 / 11.0)
        h := t / 3600
        m := t % 3600
        if h == 0 {h = 12}
        fmt.Printf("%02d:%02d:%02d\n", h, m / 60, m % 60)
    }
}
 

swift-logo.png

The do-it yourself formatting version:

import Foundation
for i in 0..<11 {
    let t = Int((Double(i) + 0.5) * 43200.0 / 11)
    let (h, m) = t.quotientAndRemainder(dividingBy: 3600)
    print(String(format:"%02d:%02d:%02d", arguments:[(h==0 ? 12 : h), m / 60, m % 60]))
}
 

csharp-logo.png

My first C# program:

using System;
public class AnalogClockHandsComputer
{
    public static void Main()
    {
        for (var i = 0; i < 11; i++)
        {
            var t = (int)((i + 0.5) * 43200.0 / 11);
            var h = t / 3600;
            var m = t % 3600;
            Console.WriteLine("{0:00}:{1:00}:{2:00}", (h != 0 ? h : 12), m / 60, m % 60);
        }
    }
}
 

java-logo.png

Using the built-in date and time classes:

import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
public class AntiparallelClockHandsComputer {
  public static void main(String[] args) {
      for (var i = 0; i < 11; i++) {
          var time = LocalTime.MIDNIGHT.plusSeconds(Math.round((0.5+i)*43200.0/11));
          System.out.println(time.format(DateTimeFormatter.ofPattern("hh:mm:ss")));
      }
  }
}

And the direct computation:

public class AntiparallelClockHandsComputer {
    public static void main(String[] args) {
        for (var i = 0; i < 11; i++) {
            int t = (int)((i + 0.5) * 43200.0 / 11), h = t / 3600, m = t % 3600;
            System.out.printf("%02d:%02d:%02d\n", (h == 0 ? 12 : h), m / 60, m % 60);
        }
    }
}
 

groovy-logo.png

I hope this is okay. It gives the right answers at least.

0.upto(10) {i ->
    def t = (int)((i + 0.5) * 43200.0 / 11);
    def h = t.intdiv(3600);
    def m = t % 3600;
    printf("%02d:%02d:%02d\n", (h == 0 ? 12 : h), m.intdiv(60), m % 60);
}
 

scala-logo.jpeg

I did this Scala one real quick. It might be nice to use the functions from java.time.

0 until 11 foreach { i =>
  val t = ((i + 0.5) * 43200/11).toInt;
  val h = t / 3600;
  val m = t % 3600
  printf("%02d:%02d:%02d\n", if (h == 0) 12 else h, m / 60, m % 60)
}
 

ceylon-logo.png

I’m not very good with Ceylon yet, so this is my first pass. I know there is a Ceylon time module, but I’ve not looked into it yet.

function pad(Integer n) => if (n < 10) then "0``n``" else "``n``";

for (i in 0:11) {
    Integer t = ((i + 0.5) * 43200.0 / 11).integer;
    Integer h = t / 3600;
    Integer m = t % 3600;
    print("``if (h==0) then 12 else h``:``pad(m / 60)``:``pad(m % 60)``");
}
 

kotlin-logo.png

Here’s my quick Kotlin hack:

fun main(args: Array) {
    for (i in 0..10) {
      val t = ((i + 0.5) * 43200.0 / 11).toInt()
      val h = t / 3600
      val m = t % 3600
      println(String.format("%02d:%02d:%02d", if (h==0) 12 else h, m / 60, m % 60));
    }
}
 

js-logo.png

The built-in time formatting utilities are weak, but moment.js is a fabulous third-party library. Here’s a command line version for Node:

const moment = require('moment')
for (let h = 0; h < 11; h++) {
  console.log(moment.unix((h+0.5) * 43200/11).utcOffset(0).format('hh:mm:ss'));
}

If you don’t want to install a third party library, and you don’t mind an outrageous hack (extracting time fields by position from an ISO datetime), you can do this 😬:

for (let i = 0; i < 11; i += 1) {
  const d = new Date((i + 0.5) * 43200000 / 11);
  console.log(d.toISOString().substring(11,19).replace(/^00/, '12'));
}
 

coffeescript-logo128.png

CoffeScript can use the moment library too:

moment = require 'moment'
for i in [0..10]
  console.log moment.unix((i+0.5) * 43200/11).utcOffset(0).format('hh:mm:ss')

And here’s the horrible hacky version:

(console.log new Date((i+0.5)*43200000/11).toISOString().substring(11,19).replace(/^00/,'12') for i in [0..10])
 

dart-logo.png

This one is due to Alex Schneider, who is very good at Dart:

void main() {
    new Iterable.generate(11, (index) {
        var s = (index + 0.5) * 43200 / 11;
        var hm = [s ~/ 3600, s % 3600];
        var hms = [hm[0] == 0 ? 12 : hm[0], hm[1] ~/ 60, (hm[1] % 60).truncate()].map((m) =>
            m.toString().padLeft(2, '0')).toList();
        print('${hms[0]}:${hms[1]}:${hms[2]}');
    }).last;
}
 

sml-logo.png

Standard ML has access to the POSIX time formatting and parsing functions, just with different names:

val _ = map print (List.tabulate(11, fn i => Date.fmt "%I:%M:%S\n"
    (Date.fromTimeUniv (Time.fromReal ((real(i)+0.5)*43200.0/11.0)))));
 

ocaml-logo.png

This is my first try:

for i = 0 to 10 do
  let t = truncate ((float i +. 0.5) *. 43200.0 /. 11.0) in
  let h = t / 3600 in
  let m = t mod 3600 in
  Printf.printf ("%02d:%02d:%02d\n") (if h = 0 then 12 else h) (m / 60) (m mod 60)
done;;

I couldn’t find date formatting functions in the standard, OCaml libraries, but there is a Date module in Batteries Included supporting the traditional "%I:%M:%S" format string.  

fsharp-logo.png

Here it is in F# with no special time functions:

for i in 0..10 do
  let t = int ((float i + 0.5) * 43200.0 / 11.0) in
  let h = t / 3600 in
  let m = t % 3600 in
  printfn ("%02d:%02d:%02d") (if h = 0 then 12 else h) (m / 60) (m % 60)
 

elm-logo.png

Elm doesn’t really write to the console, so here we produce some HTML:

import Html exposing (text, pre)
import List exposing (map, range, repeat)
import String exposing (padLeft, join)

pad n = padLeft 2 '0' (toString n)

time i =
  let
    t = floor((toFloat i + 0.5) * 43200.0 / 11)
    h = t // 3600
    m = t % 3600
  in
    join ":" (map pad [if (h==0) then 12 else h, m // 60, m % 60])

main =
  range 0 10 |> map time |> join "\n" |> text |> repeat 1 |> pre []
 

haskell-logo.png

This Haskell solution is courtesy of Mike Dillon:

import Text.Printf (printf)

antiParallel :: Int -> (Int,Int,Int)
antiParallel n = (if h == 0 then 12 else h, m, s)
    where t = truncate $ (fromIntegral n + 0.5) * 43200 / 11
          (h, ms) = t `divMod` 3600
          (m, s) = ms `divMod` 60

main = mapM_ (putStrLn . renderTime . antiParallel) [0..10]
    where renderTime (h,m,s) = printf "%02d:%02d:%02d" h m s
 

lisp-logo.png

I’m not sure where in the extensive Common Lisp library the time formatting functions are. All I’ve been able to write is this crappy version. A lot of Lisp purists will be really unhappy with the for-loop and demand that it be rewritten with tail recursion, but whatever:

(loop for i from 0 to 10 do
  (let*
    ((p (/ (* (+ i 0.5) 43200.0) 11))
     (h (/ p 3600))
     (m (mod p 3600)))
    (format t "~1,'0d:~2,'0d:~2,'0d~%"
      (truncate (if (< p 3600) 12 h))
      (truncate (/ m 60))
      (truncate (mod m 60)))))
 

clojure-logo.png

Here’s the Clojure version without the time functions:

(doseq [i (range 0 11)]
  (let [
    p (int (/ (* (+ i 0.5) 43200.0) 11))
    h (quot p 3600)
    m (rem p 3600)]
    (printf "%02d:%02d:%02d\n" (if (zero? h) 12 h) (quot m 60) (rem m 60))))
 

erlang-logo.png

With the usual direct computation:

% First line is ignored when running with escript
main(_) ->
  lists:foreach(fun (I) ->
    P = trunc((I + 0.5) * 43200 / 11),
    H = trunc(P / 3600),
    M = trunc(P rem 3600),
    io:format("~2..0b:~2..0b:~2..0b~n", [trunc(case H of 0->12;_->H end), trunc(M/60), trunc(M rem 60)])
  end, lists:seq(0,10)).
 

ada-logo.png

The shortest solution I could find uses a non-standard package, from the GNU Ada distribution, GNAT:

with Ada.Calendar, GNAT.Calendar.Time_IO. Ada.Text_IO;
use Ada.Calendar, GNAT.Calendar.Time_IO, Ada.Text_IO;

procedure Clock_Hands is
    T: Time;
begin
    for I in 0..10 loop
        T := Time_Of(2000, 1, 1, (Duration(I)+0.5)*Duration(43200.0/11.0));
        Put_Time(T, "%I:%M:%S"); New_Line;
    end loop;
end Clock_Hands;
 

fortran-logo.png

This one works with Fortran 90 and later. I haven’t learned if there is a nice time formatting function yet.

program antiparallel_clock_hands

    integer :: h, m, t

    do i = 0, 10
        t = int((i + 0.5) * 43200.0 / 11);
        h = t / 3600;
        m = mod(t, 3600);
        if (h == 0) h = 12
        write (*, '(i2.2,":",i2.2,":",i2.2)') h, m / 60, mod(m, 60)
    end do
end
 

matlab-logo.gif

Thanks to Juan Carrillo for this MATLAB script:
t = ((0:10)+0.5)*43200/11;
hours = floor(t/3600)+12*(floor(t/3600) == 0);
minutes = floor(mod(t/60,60));
seconds = floor(mod(t,60));
fprintf('%02i:%02i:%02i\n',[hours;minutes;seconds])
 

julia-logo.jpeg

This is the direct way:
using Printf
for i = 0:10
  t = trunc((i + 0.5) * 43200.0 / 11)
  h = div(t, 3600)
  m = mod(t, 3600)
  @printf("%02d:%02d:%02d\n", (h == 0 ? 12 : h), div(m, 60), mod(m,60))
end
 

r-logo.png

These solutions are courtesy of Sourav Sen Gupta. Here it is in three lines:
t <- ((0:10) + 0.5) * 43200 / 11
f <- format(.POSIXct(t,tz="GMT"), "%I:%M:%S")
write(f, stdout())
And as a nice one-liner:
write(format(.POSIXct(((0:10)+0.5)*43200/11, tz="GMT"), "%I:%M:%S"), stdout())
 

chapel-logo.png

Well, obviously this is not a very good example of how cool Chapel is, but live with it:

for i in 0..10 {
  var t = (((i: real) + 0.5) * 43200.0 / 11.0): int;
  var h = (t / 3600) : int;
  var m = (t % 3600) : int;
  writef("%02i:%02i:%02i\n", if h==0 then 12 else h, m / 60, m % 60);
}
 

smalltalk-logo.png

I tested this with the GNU Smalltalk dialect, but should work okay for most dialects. I got some good insights from Leandro Caniglia on Stack Overflow:

0 to: 10 do: [ :i |
  t := ((i + 0.5) * 43200.0 / 11) floor.
  h := t // 3600.
  h = 0 ifTrue: [h := 12].
  m := (t \\ 3600) // 60.
  s := t \\ 60.
  (Transcript show: ({'' . h . m . s} fold: [:r :t |
    pad := t < 10 ifTrue: ['0'] ifFalse: [''].
    colon := r isEmpty ifTrue: [''] ifFalse: [':'].
    r , colon , pad , (t asString)])) nl.]
 

gprolog-logo.png

This solution is due to Matt Brown, and uses GNU Prolog:
antiParallel(N,H,M,S) :-
    T  is floor((N + 0.5) * 43200 / 11),
    H  is floor(T / 3600),
    Ms is mod(T,3600),
    M  is floor(Ms / 60),
    S  is mod(Ms,60).

formatTime(0,M,S) :- formatTime(12,M,S).
formatTime(H,M,S) :- H =\= 0, format('%02d:%02d:%02d\n', [H,M,S]).

clockHands(N) :-
    N =< 10,
    antiParallel(N,H,M,S),
    formatTime(H,M,S),
    N1 is N + 1,
    clockHands(N1).
clockHands(11).
 

apl-logo.png

This works here. I had help from StackOverflow user MBass on this one.
pad ← {¯2↑,'0',⍕⍵}

time ← {
  H ← ⌊ ⍵ ÷ 3600
  H ← pad (H 12)[H = 0]
  M ← pad ⌊ (3600 | ⍵) ÷ 60
  S ← pad 60 | ⍵
  H,':',M,':',S
}

time¨ 11 1 ⍴ ⌊((⍳ 11) + 0.5) × 43200.0 ÷ 11
 

php-logo.png

PHP, love it or hate it, has thousands of built-in top-level functions, and one of them is gmstrftime.

for ($i = 0; $i < 11; $i++) {
    echo gmstrftime("%I:%M:%S", ($i+0.5) * 43200.0/11) . "<br />";
}
 

bash-logo.png

Bash (at least as of Version 4.2) can’t do floating point arithmetic directly, so we can cheat by getting bc to do the calcs for us:

for i in {0..10}; do
    t=$(echo "scale=6; t=(($i+0.5)*43200/11); scale=0; t/=1; t" | bc)
    h=$((t / 3600))
    m=$((t % 3600))
    printf "%02d:%02d:%02d\n" $((h == 0 ? 12 : h)) $((m / 60)) $((m % 60))
done
 

gas-logo.png

Not sure why I wasted an hour of my life on this:

         .global  main
         .text
main:
         push      %rdi                   # callee-save registers
         push      %rsi

         xor       %ecx,  %ecx            # ecx will count from 0 to 11
         jmp       test                   # start the loop

next:
         cvtsi2sd  %ecx, %xmm0            # i
         addsd     (half), %xmm0          # (i + 0.5)
         mulsd     (halfday), %xmm0       # (i _ 0.5) * 43200.0
         divsd     (eleven), %xmm0        # xmm0 contains time in seconds
         cvtsd2si  %xmm0, %eax            # eax has time in seconds from midnight
         xor       %edx, %edx
         mov       $3600, %r11
         div       %r11d                  # eax has hours, edx has minutes
         mov       %eax, %esi             # hours will be 2nd arg to printf
         mov       $12, %r11d
         cmp       $0, %esi
         cmovzl    %r11d, %esi            # use '12' rather than '0' for display
         mov       %edx, %eax             # break up total minutes
         xor       %edx, %edx
         mov       $60, %r11d             # eax has minutes, edx has seconds
         div       %r11d                  # eax has minutes, edx has seconds
         push      %rcx                   # save counter AND align stack!
         mov       %edx, %ecx             # seconds is 4th arg to printf
         mov       %eax, %edx             # minutes is 3rd arg to printf
         mov       $format, %edi
         call      printf                 # printf(format, h, m, s)
         pop       %rcx

         inc       %ecx                   # Next hour
test:
         cmp       $11, %ecx              # Done?
         jl        next                   # Nope

         pop       %rsi
         pop       %rdi
         ret

format:  .asciz   "%02d:%02d:%02d\n"
half:    .double  0.5
halfday: .double  43200.0
eleven:  .double  11.0
 

nasm-logo.png

This didn’t take too long; I just quickly translated from GAS:

; Antiparallel clockhands
; Targeted to ELF64 binaries only (e.g., not OS X)
;
; nasm -felf64 clockhands.asm && gcc clockhands.o && ./a.out

         global    main
         extern    printf

         section   .text

main:
         push      rdi                   ; callee-save registers
         push      rsi

         xor       ecx, ecx              ; ecx will count from 0 to 11
         jmp       check                 ; start the loop

next:
         cvtsi2sd  xmm0, ecx             ; i
         addsd     xmm0, [half]          ; (i + 0.5)
         mulsd     xmm0, [halfday]       ; (i _ 0.5) * 43200.0
         divsd     xmm0, [eleven]        ; xmm0 contains time in seconds
         cvtsd2si  eax, xmm0             ; eax has time in seconds from midnight
         xor       edx, edx
         mov       r11, 3600
         div       r11d                  ; eax has hours, edx has minutes
         mov       esi, eax              ; hours will be 2nd arg to printf
         mov       r11d, 12
         cmp       esi, 0
         cmovz     esi, r11d             ; use '12' rather than '0' for display
         mov       eax, edx              ; break up total minutes
         xor       edx, edx
         mov       r11d, 60              ; eax has minutes, edx has seconds
         div       r11d                  ; eax has minutes, edx has seconds
         push      rcx                   ; save counter AND align stack!
         mov       ecx, edx              ; seconds is 4th arg to printf
         mov       edx, eax              ; minutes is 3rd arg to printf
         lea       rdi, [format]
         call      printf               ; printf(format, h, m, s)
         pop       rcx

         inc       ecx                   ; Next hour
check:
         cmp       ecx, 11               ; Done?
         jl        next                  ; Nope

         pop       rsi
         pop       rdi
         ret


         section   .data
format:  db        "%02d:%02d:%02d", 10, 0
half:    dq        0.5
halfday: dq        43200.0
eleven:  dq        11.0