Implement a Simple Stopwatch

25

1

Challenge

Your task is to write a program which, once a second (including immediately when your program is started), prints the elapsed time from the time your program was started.

Rules

  • Time must be printed in hh:mm:ss format. (leading zeros for single-digit values)
  • The time stamps must be separated by CR, LF, or CRLF. (no leading whitespace)
  • A new time must appear every second. (stdout cannot be buffered for a second)
  • The behavior of the program if it is run past 23:59:59 is undefined.
  • You may use sleep(1) even if a specific second may be skipped whenever the overhead to print, calculate, loop, etc. accumulates to a second.

Example output:

00:00:00
00:00:01
00:00:02
00:00:04
00:00:05
⋮

Note that 00:00:03 is missing here due to processing overhead. The actual skipped values (if any) are of course dependent on implementation and/or system.

Reference implementation in C: (POSIX-compatible systems only)

#include <unistd.h> // sleep()
#include <tgmath.h>
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>

#ifndef __STDC_IEC_559__
#error "unsupported double"
#endif
static_assert(sizeof(double) == 8, "double must have double precision");
#define MAX_PRECISE_DOUBLE ((double)(1ULL << 52))

int main(void) {
    time_t start = time(NULL);
    if (start == (time_t)-1) return EXIT_FAILURE;
    while (1) {
        time_t now = time(NULL);
        if (now == (time_t)-1) return EXIT_FAILURE;

        double diff = difftime(now, start);
        if (isnan(diff) || diff < 0) return EXIT_FAILURE;
        if (diff > MAX_PRECISE_DOUBLE) return EXIT_FAILURE;

        unsigned long long seconds = diff;
        unsigned long long h = seconds / 3600;
        seconds %= 3600;
        unsigned long long m = seconds / 60;
        seconds %= 60;
        unsigned long long s = seconds;

        (void)printf("\r%02llu:%02llu:%02llu", h, m, s);
        (void)fflush(stdout);

        (void)sleep(1);
    }
}

Winning criteria

This is , shortest code in bytes win!

MarkWeston

Posted 2017-12-26T10:50:19.183

Reputation: 403

Note for later challenges, clarification in the comments is a bad thing to do. reference

– user202729 – 2017-12-27T03:56:53.057

Answers

9

MATL, 17 16 bytes

`Z`12L/13XOD1Y.T

Try it at MATL Online!

How it works

`         % Do...while loop
  Z`      %   Push seconds elapsed since start of program
  12L     %   Push 86400 (predefined literal)
  /       %   Divide. This transforms seconds into days
  13XO    %   Convert to date string with format 13, which is 'HH:MM:SS'
  D       %   Display
  1Y.     %   Pause for 1 second
  T       %   True. Used as loop condition for infinite loop
          % End loop (implicit)

Luis Mendo

Posted 2017-12-26T10:50:19.183

Reputation: 87 464

4How in the world did you answer this 37 minutes after it has been closed? o_O blames caching – Mr. Xcoder – 2017-12-26T19:10:25.387

9@Mr.Xcoder I recently learned to use the Force – Luis Mendo – 2017-12-26T19:14:03.427

29

Operation Flashpoint scripting language,  174  171 bytes

s=""
#l
t=_time
t=t-t%1
a=t%60
c=(t-a)/60
b=c%60
c=(c-b)/60
d=""
e=d
f=d
?a<10:d=0
?b<10:e=0
?c<10:f=0
s=s+format["%1%2:%3%4:%5%6\n",f,c,e,b,d,a]
hint s
@t+1<_time
goto"l"

In action:

158 bytes, if the previous time is overwritten by the next time:

#l
t=_time
t=t-t%1
a=t%60
c=(t-a)/60
b=c%60
c=(c-b)/60
d=""
e=d
f=d
?a<10:d=0
?b<10:e=0
?c<10:f=0
hint format["%1%2:%3%4:%5%6",f,c,e,b,d,a]
@t+1<_time
goto"l"

Technically, no carriage return is used, so I'm not sure if this version confines to the rules.

Steadybox

Posted 2017-12-26T10:50:19.183

Reputation: 15 798

5I wasn't expecting operation flashpoint. – Polyducks – 2017-12-27T03:39:13.950

10@Polyducks nobody expects operation flashpoint – Pureferret – 2017-12-28T12:49:36.810

1

@Pureferret "If you see the flash, it is already too late."

– Steadybox – 2017-12-28T19:22:09.663

Since in Unix, a CR will overwrite the line, i think the second answer is validated by ‘either CR, LF, or CRLF are allowed’ – Stan Strum – 2018-02-22T20:23:20.360

1@StanStrum At least on my Ubuntu CR will not overwrite the line. In fact, CRLF, LFCR and LF are all semantically equivalent. – None – 2019-03-06T07:42:29.497

13

Bash + coreutils, 28 26 bytes

date -s0|yes date +c%T|sh

The unprintable character between + and % is an ESC byte.

This sets the system time to 00:00:00 and thus requires root privileges. It also assumes that the timezone is UTC and that no other processes will interfere with the system clock.

Each new timing resets the terminal, thus overwriting the previous one.


Bash + coreutils, 38 29 bytes

date -s0|yes date +%T|sh|uniq

The same restrictions as before apply. Each new timing is shown on a new line.

Dennis

Posted 2017-12-26T10:50:19.183

Reputation: 196 637

Since it doesn't change the bytecount I'd separate the first date from the rest with a nice little linefeed. But it might be too nice for someone able to come up with something like your second solution >:-( – Aaron – 2017-12-28T17:03:28.593

date -s0 prints the new time to STDOUT; I'm using the pipe to silence that output. – Dennis – 2017-12-28T17:05:22.390

Oh right, thanks for the explanation ! – Aaron – 2017-12-28T17:07:18.197

5

APL (Dyalog Unicode), 51 bytes

Full program body.

s←⎕AI
1↓∊':'@1∘⍕¨100+3↑0 60 60 1E3⊤3⊃⎕AI-s
⎕DL 1
→2

Try it online! (Press Ctrl+Enter to start, and again to stop.)

⎕AIAccount Information (user ID, compute time, connect time, keying time)

s← assign to s (for start time)
⎕AI-s subtract s from ⎕AI

3⊃ pick the third element (connect time in milliseconds)
0 60 60 1E3⊤ convert to this mixed-radix
3↑ take the first 3 (drops the milliseconds)
100+ one hundred added to each (to pad zeros)
':'@1∘⍕¨ amend with a colon at the first character of the string representation of each
ϵnlist (flatten)
1↓ drop the first colon (and implicitly print to stdout)

⎕DL 1Delay one second

→2 go to line number two

Adám

Posted 2017-12-26T10:50:19.183

Reputation: 37 779

5

R, 59 44 bytes

F in R defaults to FALSE, but it's a regular variable and can be redefined. When used in arithmetic, FALSE is coerced to 0. Asking for F+1 therefore returns 1. We assign F to be F+1, format it nicely, print, and wait for one second. Continues indefinitely.

repeat{print(hms::hms(F<-F+1))
Sys.sleep(1)}

Doesn't work on TIO (due to lack of the hms package), but here's a sample output from my machine:

00:00:00
00:00:01
00:00:02
00:00:03
00:00:04
00:00:05
00:00:06
00:00:07
00:00:08
00:00:09
00:00:10
00:00:11
00:00:12
00:00:13

rturnbull

Posted 2017-12-26T10:50:19.183

Reputation: 3 689

5

bash + sleep + date, also 50 49 47 46 45 41 bytes

while date -ud@$[s++] +%T;do sleep 1;done

To take a lap time, quickly hit ^C, run this and then rerun the above:

laps=("${laps[@]}" $s) ; echo ${laps[-1]}

To reset:

s=0; unset laps

The $[s++] syntax appears to still work, but is no longer (AFAICS) documented in the bash man page. And it's still a byte shorter than using the for((...)) loop, once I removed the quotes around it.

Will Crawford

Posted 2017-12-26T10:50:19.183

Reputation: 151

AFAICT, $[] is a deprecated/undocumented but still supported form of $(()). I'm not sure if it's commonly used in code-golf answers, but the general rule is that your code only has to work on at least one version of the interpreter for your language. IMO it's fine.

– Peter Cordes – 2017-12-30T06:39:32.553

s=0 isn't required, as arithmetic substitution will treat an unset variable as 0. -u also isn't needed if you just assume the default timezone (UTC). – Dennis – 2017-12-30T15:57:06.953

-u is needed on my machine :) – Will Crawford – 2017-12-30T18:13:02.377

4

Swift, 144 bytes

import Foundation
let s=Date()
while 1>0{let d=Int(-s.timeIntervalSinceNow)
print(String(format:"%02d:%02d:%02d",d/3600,d/60%60,d%60))
sleep(1)}

Explanation

import Foundation                       // Import `Date` and `sleep()`
let s = Date()                          // Get the time at the start of the program
while 1 > 0 {                           // While 1 > 0 (forever):
  let d = Int(-s.timeIntervalSinceNow)  //   Calculate time difference
  print(String(format:"%02d:%02d:%02d", //   Print the time
      d/3600,d/60%60,d%60))
  sleep(1)                              //   Sleep one second
}

Herman L

Posted 2017-12-26T10:50:19.183

Reputation: 3 611

4

JavaScript (ES6), 99 bytes

f=_=>console.log(new Date(new Date-d).toUTCString().slice(17,25))
f(d=Date.now(setInterval(f,1e3)))

darrylyeo

Posted 2017-12-26T10:50:19.183

Reputation: 6 214

2The hours do not start at 0 for me. The offset changes depending on the system clock timezone. (Win10) – LukeS – 2017-12-26T21:21:48.957

@LukeS Whoops, fixed! – darrylyeo – 2017-12-27T01:41:32.490

4

Matlab (R2016b), 50 bytes

t=now;while 1,disp(datestr(now-t,13)),pause(1),end

Explanation:

t=now; % Stores the current time
while 1 % Loops forever
    disp(datestr(now-t,13)) % Computes the difference since the program started
    % And prints with format 13 ('HH:MM:SS') - this may change between versions
    pause(1) % Waits one second
end

Alternate version (50 bytes too :P):

now;while 1,disp(datestr(now-ans,13)),pause(1),end

Thiago Oleinik

Posted 2017-12-26T10:50:19.183

Reputation: 341

Welcome to the site! :) – James – 2017-12-27T16:46:27.380

Thanks mate :) – Thiago Oleinik – 2017-12-27T17:37:11.270

@LuisMendo Thanks for the suggestion, but I didn't understand... In your example, what is the variable t? Also, the input to datestr is in days, so I would have to divide by 86400, which would increase the byte count by two... – Thiago Oleinik – 2017-12-27T20:11:17.143

3

Julia 0.6, 75 68 bytes

for h=0:23,m=0:59,s=0:59;@printf "%02i:%02i:%02i
" h m s;sleep(1)end

Try it online!

With sleep(1) allowed, simple nested for-loops are shorter than using Julias built-in time handling methods.

Old solution without sleep(1) using DateTime

t=now()-DateTime(0);Timer(x->println(Dates.format(now()-t,"HH:MM:SS")),0,1)

t is the amount of time passed from 'day 0' to when the program is started. now()-t is a moment in time, which is then formatted using Dates.format().

t0=now(); ...; now()-t0 would yield a time difference, that cannot be used with Dates.format().

The timing itself is trivial with the build-in Timer.

LukeS

Posted 2017-12-26T10:50:19.183

Reputation: 421

3

PHP 4+, 70 64 bytes

$x=time();while(1){sleep(1);echo date('H:i:s',time()-$x)."\n";}

PHP 5.3+, 69 63 bytes

$x=time();a:sleep(1);echo date('H:i:s',time()-$x)."\n";goto a;

Darren H

Posted 2017-12-26T10:50:19.183

Reputation: 731

PHP open tags can be omitted in the answer saving you 6 bytes. – Daniel W. – 2017-12-28T12:23:55.297

3

JavaScript (ES6), 88 bytes

f=_=>console.log(new Date(i++*1e3).toUTCString().slice(17,25))
f(i=0,setInterval(f,1e3))

Essentially the same approach as @darrylyeo's answer, but works for all timezones and uses a slightly different way to get to 0.

[Edit] Darryl's answer has been fixed. This is still shorter, though.

Birjolaxew

Posted 2017-12-26T10:50:19.183

Reputation: 323

3

Python 2, 85 bytes

import time
t=0
while 1:print(":%02d"*3)[1:]%(t/3600,t/60%60,t%60);time.sleep(1);t+=1

Credits

Neil

Posted 2017-12-26T10:50:19.183

Reputation: 2 417

You can save one byte by replacing "%02d:%02d:%02d" with (":%02d"*3)[1:] – wnnmaw – 2017-12-27T20:33:37.967

1You don't need %24, behavior is undefined after 23:59:59. – Erik the Outgolfer – 2017-12-28T12:48:36.083

@EriktheOutgolfer Good point, updated. – Neil – 2017-12-28T20:42:15.440

3

><>, 82 + 7 = 89 bytes

0\!
:/+1oan~?=3ln?$0(a:o":"n~?=4ln?$0(a:ro":"n~?=5ln?$0(a:,*a6-}:%*a6:,*a6-}:%*a6:

Try it online!

+7 bytes for using the flag -t.0125 to make the each instruction take 1/80th of a second. Each loop has 80 instructions, making each loop one second long. Because of computation time, this is actually longer in practice.

I actually had to buffer this all the way up to 100 until I saw @Not A Tree's answer which had 7 byte better way than mine to generate the hours and minutes, trimming it below 80. They also inspired the use of \/ which are executed twice per loop.

How It Works

0\...
./...
Initialises the stack with a 0 to represent the time

0\!
:/....................................................,*a6-}:%*a6:,*a6-}:%*a6:
Puts the hours, minutes and seconds in the stack

0\!
:/....n~?=3ln?$0(a:o":"n~?=4ln?$0(a:ro":"n~?=5ln?$0(a:...
Print out the hours, minutes, seconds separated by colons. 
If the number is below 0, print a leading 0. 
If the number is not, then there is an extra 0 on the stack, which is popped.

0\!
./+1oa...
Print a newline and increment the counter
And restart the loop

Bonus:

A one line version of the same size, 80 + 9 bytes:

0::6a*%:}-6a*,:6a*%:}-6a*,:a(0$?nl5=?~n":"or:a(0$?nl4=?~n":"o:a(0$?nl3=?~nao1+>!

This uses the -a flag to add ticks for skipped instructions.

Jo King

Posted 2017-12-26T10:50:19.183

Reputation: 38 234

2

Python 3, 112 bytes

Assuming using 1-second delays is ok, even if it (rarely) might skip a second.

from time import*;a=0
while 1:d=divmod;m,s=d(a,60);print(":".join(f"{k:02d}"for k in(*d(m,60),s)));a+=1;sleep(1)

Hannes Karppila

Posted 2017-12-26T10:50:19.183

Reputation: 3 090

2

VBA, 90

t=0:while(1):?format(t,"hh:mm:ss"):t=t+timeserial(0,0,1):q=timer:while q-timer<1:wend:wend

run in immediate window:expected failure point somewhere around 23 million years (floating point resolution fails ~8.5e9 days)

SeanC

Posted 2017-12-26T10:50:19.183

Reputation: 1 117

2

Clean, 173 172 168 bytes

import StdEnv,System.Time
$n i#i=(i/60^n)rem 60
=(i/10,i rem 10)
f i w#(Clock j,w)=clock w
#j=j/1000
|j>i=[j:f j w]=f i w
Start w=[($2i,':',$1i,':',$0i,'
')\\i<-f -1 w]

This one only works under the Windows Clean bundles.

Add 3 bytes if you want it to work under Linux, as Clean's CLK_PER_TICK :== 1000000 on *nix. If you want it to be cross-platform, add 8 bytes instead, as you need to use CLK_PER_TICK instead of the value it's set to. (TIO link is larger due to above)

Try it online!

Οurous

Posted 2017-12-26T10:50:19.183

Reputation: 7 916

2

PHP, 59 48 bytes

while(1){sleep(1);echo date('H:i:s',$i++)."\n";}

Inspired by Darren H's answer.

Old version :

<?php while(1){sleep(1);echo date('H:i:s',$i++-3600)."\n";}

roberto06

Posted 2017-12-26T10:50:19.183

Reputation: 351

PHP open tags can be omitted in the answer saving you 6 bytes. – Daniel W. – 2017-12-28T12:23:51.070

Great thought, but 3600 needs to be 86400 otherwise the counter starts at 23:00:00 so unfortunately you gain a byte, still beat me by 9 though! – Darren H – 2018-01-01T20:41:03.657

@DarrenH I think it depends on your locale, I hadn't thought about that. I'm in GMT+1, that's why I added 3600, but I guess for English people, you could remove the -3600 altogether, which would save 5 bytes. – roberto06 – 2018-01-02T12:13:45.827

2

Bash + coreutils + GNU date, 50 bytes

o=`date +"%s"`;yes date +%X -ud\"-$o sec\"|sh|uniq

Inspired by @Dennis, this solution doesn't require the time to be changed. It store stores the initial offset from now to the UNIX epoch (1 Jan 1970 00:00:00 UTC), in 'o', and then displays [-ud options] (the current time - offset), in UTC date, but only [+%X option] HH:MM:SS. This should work in countries where the current time-zone isn't UTC.

CSM

Posted 2017-12-26T10:50:19.183

Reputation: 219

2

AWK, 110 87 86 bytes

BEGIN{for(;;i++){printf("%02d:%02d:%02d\n",i/3600%60,i/60%60,i%60);system("sleep 1")}}

Does not work in TIO.

Noskcaj

Posted 2017-12-26T10:50:19.183

Reputation: 421

Your program doesn't seem to print 00:00:00 at the moment it's started. – user202729 – 2017-12-27T16:13:08.873

Fixed it. Thanks – Noskcaj – 2017-12-27T16:28:26.757

2

Jelly, 23 bytes

:⁽½c,60;%60d⁵j”:ṄœS1ṛ‘ß

Try it online!

Erik the Outgolfer

Posted 2017-12-26T10:50:19.183

Reputation: 38 134

Does it work with times above 1 minute? – H.PWiz – 2017-12-27T16:58:33.143

@H.PWiz It should, running some tests. EDIT: Looks like a dividend is wrong for the hours...fixed for a little save! – Erik the Outgolfer – 2017-12-27T17:00:32.320

2

APL (Dyalog), 37 bytes

{∇⍵+×⎕DL 1⊣⎕←1↓∊':'@1∘⍕¨100+⍵⊤⍨3⌿60}0

Try it online!

Full program.

Pretty similar to Adám's answer, however independently written and uses a non-⎕AI-based approach.

Erik the Outgolfer

Posted 2017-12-26T10:50:19.183

Reputation: 38 134

2

Python 2, 69 + 3 (TZ=) = 72 bytes

from time import*;s=time()
while 1:print ctime(time()-s)[11:19]+'\r',

This runs in a continuous loop, without sleeping, updating the time on the same line rather than printing a new line each second. (Still allowed by the rules, I hope.)

This slightly longer version (72+3=75 bytes) prints on a new line every second instead:

from time import*;s=time()
while 1:print ctime(time()-s)[11:19];sleep(1)

Both of these require you to be in the UTC timezone. On Linux you can achieve this by setting the TZ environment variable. E.g. TZ= python.

mercator

Posted 2017-12-26T10:50:19.183

Reputation: 359

2

><>, 106 bytes 82 + 9 = 91 bytes

Thanks to Jo King for suggesting the -a flag! Check out their answer too.

0v+1oan<n0/
:/<</?(a:,*a6-}:%*a6:,*a6-}:%*a6:\\
n<n0/<</?(a:ro":"
":"n<n0/<</?(a:o

Try it online! (but you'll have to wait for the 60 second timeout).

I got to use a feature of ><> that I've never needed before: this code requires the flag -t.0125, which sets the execution speed to 0.0125 seconds per tick, or 80 ticks per second. There's also the -a flag, which makes whitespace count as a tick (in some cases — the interpreter is a bit weird about this).

Basically, the code keeps a counter that's incremented each time the fish goes through the loop, and the rest of the loop converts the counter to hh:mm:ss format and prints it. The loop takes exactly 80 ticks.

This should work in theory, but in practice, each tick is slightly longer than 0.0125 seconds, because of computation time. Changing the \\ on the second line to << gives more accurate timings on TIO.

You can also watch the code in action at the fish playground, except that this interpreter treats whitespace slightly differently from the official interpreter. Alternatively, you can remove the flags on TIO to make the code run at top speed, to verify the behaviour for times after one minute.

Not a tree

Posted 2017-12-26T10:50:19.183

Reputation: 3 106

-1 byte by replacing the v in the first line with \! and removing two of the extra <. Another couple of bytes if you use the -a flag, which counts whitespace and skipped instructions as ticks – Jo King – 2017-12-30T18:40:46.510

@JoKing, The -a flag let me golf it a bit more, thank you! I think you can use the \! trick in your code, too: Try it online!

– Not a tree – 2017-12-30T20:10:48.260

2

Java 8, full program, 150 bytes

interface M{static void main(String[]a)throws Exception{for(int i=0;;Thread.sleep(1000))System.out.printf("%02d:%02d:%02d%n",i/3600,i/60%60,i++%60);}}

Try it here (times out after 60 seconds, so I've set the sleep to 1 to see more output).

Explanation:

interface M{                    // Program:
  static void main(String[]a)   //  Mandatory main-method
     throws Exception{          //    Mandatory throws for Thread.sleep
    for(int i=0;                //   Start at 0
        ;                       //   Loop indefinitely
         Thread.sleep(1000))    //     After every iteration: Sleep for 1 sec
      System.out.printf("%02d:%02d:%02d%n",
                                //    Print in the format "HH:mm:ss\n":
        i/3600,i/60%60,i++%60); //     The hours, minutes and seconds
                                //     (and increase `i` by 1 afterwards with `i++`)
                                //   End of loop (implicit / single-line body)
  }                             //  End of mandatory main-method
}                               // End of program

Java 8, function, 94 bytes

v->{for(int i=0;;Thread.sleep(1000))System.out.printf("%02d:%02d:%02d%n",i/3600,i/60%60,i++%60);}

Try it here (times out after 60 seconds, so I've set the sleep to 1 to see more output).

Explanation:

v->{   // Method with empty unused parameter and no return-type
  ...  //  Same as the program above
}      // End of method

Here is a small gif to see it works as intended when 1000 ms are used:

enter image description here

Kevin Cruijssen

Posted 2017-12-26T10:50:19.183

Reputation: 67 575

1

Shell, 177 bytes

Notice that this is not entirely POSIX conformant because it uses date +%s, which is a common date expansion.

a=`date +%s`;while true;do b=`date +%s`;s=`expr $b - $a`;h=`expr $s / 3600`;s=`expr $s % 3600`;m=`expr $s / 60`;s=`expr $s % 60`;printf '\r%02d:%02d:%02d' $h $m $s;sleep 1;done

MarkWeston

Posted 2017-12-26T10:50:19.183

Reputation: 403

7Normally, you should give people a chance to answer your challenge before answering it yourself. I recommend a week as some may only be here at certain times during the week. – Adám – 2017-12-26T18:02:39.093

1@Adám I haven't accepted my answer, and at the time I posted much shorter answers (like yours) were submitted. – MarkWeston – 2017-12-28T12:24:12.860

1

Ruby, 192 117 bytes (Credit to Dada)

t=Time.now
loop do
m,s=(Time.now-t).to_i.divmod(60)
h,m=m.divmod(60)
printf"%02d:%02d:%02d
",h,m,s
sleep 1
end

How does it work?

Going to use the expanded version (Conversion to a time is given as a separate function and uses a different output format):

def format_secs(s) # Converts the value in seconds to the required format
    mins, secs = s.divmod(60) # divmod returns the quotient and the remainder of a number
    hours, mins = mins.divmod(60)
    [hours,mins,secs].map { |e| e.to_s.rjust(2,'0') }.join ':'

    =begin
    [hours,mins,secs] -Creates a new array using the values allready provided for hours, minutes and seconds
    .map { - Creates a new array based on a operation on each of an array's values
    .to_s.rjust(2,'0')} - Turns the number into a string, and then adds "0" if needed to make the timer's result at least two digits
    .join ':' - Combines the result of the operation into a single string with a ":" in between the two numbers
    =end
end

t = Time.now # Saves the time at the program's (Rough) start

loop do
    puts format_secs((Time.now - t).to_i) # Returns the result of  the "format_secs" operation on the difference between the two times (in seconds) converted to a pure integer
    sleep 1 # Waits for one second
end

James007

Posted 2017-12-26T10:50:19.183

Reputation: 11

6

Welcome on the site! Every answer to a [tag:code-golf] challenge must be golfed. You should at least remove useless whitespaces, and use 1-character variable names. That would get you around 120 bytes, and using printf instead of puts can save a few more bytes: Try it online!. Happy golfing on PPCG!

– Dada – 2017-12-28T10:06:40.010

1

Powershell, 52 bytes

Newest (52 Bytes):

For($a=0){date -H:0 -Min:0 -S:$a -U:%T;Sleep 1;$a++}

Try it online!

It no longer requires admin, the solution is actually much simpler than before.

Using .Net (61 Bytes):

[DateTime]::Now.Date|set-date;For(1){get-date -U %T;Sleep(1)}

The .Net version exploits that Now.Date strips out the time, so it outputs 12:00 AM as the time. See: https://stackoverflow.com/a/9630340/8303961

Using only built-in commandlets (66 Bytes):

get-date -H:0 -Min:0 -S:0|set-date;For(1){get-date -U %T;Sleep(1)}

Both versions have to be run in a elevated powershell window due to changing the system time with set-date cmdlet.

CobyCode

Posted 2017-12-26T10:50:19.183

Reputation: 111

1

APL NARS, 109 63 57 chars

q;t
t←0
{∊⍵,¨':: '}{1<⍴x←⍕⍵:x⋄'0',x}¨(3⍴60)⊤⌊t+←⎕DL 1⋄→2

3+3+48+3=57 (seen the others Apl solutions too)

{1<⍴x←⍕⍵:x⋄'0',x}

convert the INT ⍵ in the string of digits in a way if the lenght of that string is 1 than add one '0' in front of it

{∊⍵,¨':: '}

combine array in ⍵ with the array ':: '

00:00:01 
00:00:02 
00:00:03 
00:00:04 
00:00:05 
00:00:06 
00:00:07 
00:00:08 
00:00:09 

RosLuP

Posted 2017-12-26T10:50:19.183

Reputation: 3 036

1

x86-64 machine code (Linux system call): 78 bytes

RDTSC spin-loop timing, Linux sys_write system call.

x86-64 doesn't provide a convenient way to query the RDTSC "reference clock" frequency at run time. You can read an MSR (and do a calculation based on that), but that requires kernel mode, or root + opening /dev/cpu/%d/msr, so I decided to make the frequency a build-time constant. (Adjust FREQ_RDTSC as necessary: any 32-bit constant won't change the size of the machine code)

Note that x86 CPUs for several years have had fixed RDTSC frequency so it is usable as a timesource, not a core clock cycle performance counter unless you take steps to disable frequency changes. (There are actual perf counters for counting real CPU cycles.) Usually it ticks at the nominal sticker frequency, e.g. 4.0GHz for my i7-6700k regardless of turbo or powersaving. Anyway, this busy-wait timing doesn't depend on load average (like a calibrated delay-loop would), and also isn't sensitive to CPU power saving.

This code will work for any x86 with a reference frequency below 2^32 Hz, i.e. up to ~4.29 GHz. Beyond that, the low 32 of the timestamp would wrap all the way in 1 second, so I'd have to look at the edx high 32 bits of the result, too.

Summary:

push 00:00:00\n on the stack. Then in a loop:

  • sys_write system call
  • ADC-loop over the digits (starting with the last) to increment the time by 1. Wrapping / carry-out handled with a cmp / cmov, with the CF result providing the carry-in for the next digit.
  • rdtsc and save the start time.
  • spin on rdtsc until the delta is >= ticks per second of the RDTSC frequency.

NASM listing:

 1  Address                            ; mov  %1, %2       ; use this macro to copy 64-bit registers in 2 bytes (no REX prefix)
 2           Machine code           %macro MOVE 2
 3           bytes                      push  %2
 4                                      pop   %1
 5                                  %endmacro
 6                                  
 7                                      ; frequency as a build-time constant because there's no easy way detect it without root + system calls, or kernel mode.
 8                                      FREQ_RDTSC equ 4000000000
 9                                  global _start
10                                  _start:
11 00000000 6A0A                        push     0xa                       ; newline
12 00000002 48BB30303A30303A3030        mov      rbx, "00:00:00"
13 0000000C 53                          push     rbx
14                                      ; rsp points to  `00:00:00\n`
20                                  
21                                      ; rbp = 0                (Linux process startup.  push imm8 / pop is as short as LEA for small constants)
22                                      ; low byte of rbx = '0'
23                                  .print:
24                                      ; edx potentially holds garbage (from rdtsc)
25                                  
26 0000000D 8D4501                      lea      eax, [rbp+1] ; __NR_write = 1
27 00000010 89C7                        mov      edi, eax     ; fd = 1 = stdout
28                                      MOVE     rsi, rsp
28 00000012 54                  <1>  push %2
28 00000013 5E                  <1>  pop %1
29 00000014 8D5008                      lea      edx, [rax-1 + 9]     ; len = 9 bytes.
30 00000017 0F05                        syscall               ; sys_write(1, buf, 9)
31                                  
32                                      ;; increment counter string:  least-significant digits are at high addresses (in printing order)
33 00000019 FD                          std                        ;  so loop backwards from the end, wrapping each digit manually
34 0000001A 488D7E07                    lea      rdi, [rsi+7]
35                                      MOVE     rsi, rdi
35 0000001E 57                  <1>  push %2
35 0000001F 5E                  <1>  pop %1
36                                  
37                                      ;; edx=9 from the system call
38 00000020 83C2FA                      add   edx, -9 + 3      ; edx=3 and set CF (so the low digit of seconds will be incremented by the carry-in)
39                                      ;stc
40                                  .string_increment_60:          ; do {
41 00000023 66B93902                    mov    cx, 0x0200 + '9'    ; saves 1 byte vs. ecx.
42                                      ; cl = '9' = wrap limit for manual carry of low digit.  ch = 2 = digit counter
43                                    .digitpair:
44 00000027 AC                          lodsb
45 00000028 1400                        adc      al, 0           ; carry-in = cmp from previous iteration; other instructions preserve CF
46 0000002A 38C1                        cmp      cl, al          ; manual carry-out + wrapping at '9' or '5'
47 0000002C 0F42C3                      cmovc    eax, ebx        ; bl = '0'.  1B shorter than JNC over a MOV al, '0'
48 0000002F AA                          stosb
49                                  
50 00000030 8D49FC                      lea     ecx, [rcx-4]    ; '9' -> '5' for the tens digit, so we wrap at 59
51 00000033 FECD                        dec     ch
52 00000035 75F0                        jnz    .digitpair
53                                      ; hours wrap from 59 to 00, so the max count is 59:59:59
54                                  
55 00000037 AC                          lodsb                        ; skip the ":" separator
56 00000038 AA                          stosb                        ; and increment rdi by storing the byte back again.  scasb would clobber CF
57                                  
58 00000039 FFCA                        dec     edx
59 0000003B 75E6                        jnz   .string_increment_60
60                                  
61                                      ; busy-wait for 1 second.  Note that time spent printing isn't counted, so error accumulates with a bias in one direction
62 0000003D 0F31                        rdtsc                         ; looking only at the 32-bit low halves works as long as RDTSC freq < 2^32 = ~4.29GHz
63 0000003F 89C1                        mov      ecx, eax             ; ecx = start
64                                  .spinwait:
65                                  ;    pause
66 00000041 0F31                        rdtsc                      ; edx:eax = reference cycles since boot
67 00000043 29C8                        sub      eax, ecx          ; delta = now - start.  This may wrap, but now we have the delta ready for a normal compare
68 00000045 3D00286BEE                  cmp      eax, FREQ_RDTSC   ; } while(delta < counts_per_second)
69                                   ;   cmp      eax, 40  ; fast count to test printing
70 0000004A 72F5                        jb     .spinwait
71                                  
72 0000004C EBBF                        jmp .print
  next address = 0x4E = size = 78 bytes.

Uncomment the pause instruction to save significant power: this heats one core up by ~15 degrees C without pause, but only by ~9 with pause. (On Skylake, where pause sleeps for ~100 cycles instead of ~5. I think it would save more if rdtsc wasn't also slow-ish so the CPU isn't doing much a lot of the time).


A 32-bit version would be a few bytes shorter, e.g. using a 32-bit version of this to push the initial 00:00:00\n string.

16                          ;    mov      ebx, "00:0"
17                          ;    push     rbx
18                          ;    bswap    ebx
19                          ;    mov      dword [rsp+4], ebx    ; in 32-bit mode, mov-imm / push / bswap / push would be 9 bytes vs. 11

And also using 1-byte dec edx. The int 0x80 system call ABI wouldn't use esi / edi, so the register setup for the syscall vs. lodsb / stosb might be simpler.

Peter Cordes

Posted 2017-12-26T10:50:19.183

Reputation: 2 810

I could have used a nanosleep system call, but this was more interesting. With root on Linux, it is possible to read the right MSR and programmatically get the RDTSC frequency. – Peter Cordes – 2018-01-02T20:42:19.700

1

q/kdb+, 40 bytes

Solution:

.z.ts:{-1($)18h$a+:1};a:-1;(.)"\\t 1000"

Example:

q).z.ts:{-1($)18h$a+:1};a:-1;(.)"\\t 1000"
q)00:00:00
00:00:01
00:00:02
00:00:03
00:00:04
00:00:05

Explanation:

There are three commands being executed here:

  1. .z.ts:{-1($)18h$a+:1}; / override timer function
  2. a:-1; / initialise variable a to -1
  3. (.)"\\t 1000" / start the timer with 1000ms precision

Breakdown of the timer function:

.z.ts:{-1 string 18h$a+:1} / ungolfed timer function
      {                  } / lambda function
                     a+:1  / add 1 to variable a
                 18h$      / cast to seconds
          string           / cast to string
       -1                  / write to stdout
.z.ts:                     / assign this function to .z.ts

Bonus:

Alternative 1 for 41 bytes:

a:.z.t;.z.ts:{-1($)18h$x-a};(.)"\\t 1000"

Alternative 2 for 26 + 7 bytes = 33 bytes

.z.ts:{-1($)18h$a+:1};a:-1

and adding -t 1000 as arguments to the q binary.

streetster

Posted 2017-12-26T10:50:19.183

Reputation: 3 635

0

Ocaml, 125 117 bytes

let rec f i=Printf.printf"%02d:%02d:%02d\n"(i/3600)(i/60 mod 60)(i mod 60);flush stdout;Unix.sleep 1;f(i+1)let()=f 0

This is the naive way to do it, minus useless spaces. With a regular coding style, it is :

let rec f i = 
  Printf.printf "%02d:%02d:%02d\n" (i/3600) (i/60 mod 60) (i mod 60);
  flush stdout;
  Unix.sleep 1;
  f (i+1)
let () = f 0

[EDIT] I forgot to remove spaces before submission... (-8 bytes)

Bromind

Posted 2017-12-26T10:50:19.183

Reputation: 289

0

JavaScript (ES6), 68 67 bytes

f=m=>setTimeout(f,c=1e3,m+c|c,alert((8+new Date(m|0)).split` `[4]))

Assumes the alert is dismissed immediately (for example, by holding down the <enter> key); if that's not permitted then add 6 bytes for console.log.


Try it

alert overridden with console.log for your sanity!

alert=console.log
f=m=>setTimeout(f,c=1e3,m+c|c,alert((8+new Date(m|0)).split` `[4]))
f()

Shaggy

Posted 2017-12-26T10:50:19.183

Reputation: 24 623

Umm, it starts at 01:00:00 instead of 00:00:00. – Kevin Cruijssen – 2018-01-05T16:04:08.627

@KevinCruijssen; it might be locale dependent. – Shaggy – 2018-02-14T15:57:54.390

Ah, you're probably right, since The Netherlands is in the +1 timezone. Maybe add some code at the start of the Try it code to set the timezone to +0? – Kevin Cruijssen – 2018-02-14T16:13:13.970

0

Windows Batch, 218 bytes

Only golfed a bit, can be improved.

@echo off
set/ah=m=s=0
:L
set r=00%h%
set r=%r:~-2%
set t=00%m%
set t=%t:~-2%
set y=00%s%
set y=%y:~-2%
echo %r%:%t%:%y%
set/as+=1
if %s%==60 set s=0&set/am+=1
if %m%==60 set m=0&set/ah+=1
timeout 1 /nobreak>nul
goto L

stevefestl

Posted 2017-12-26T10:50:19.183

Reputation: 539

0

mIRC 7.49 53 Bytes

set %i 0 | timer 0 1 say $!duration(%i,3) $(|) inc %i

O S

Posted 2017-12-26T10:50:19.183

Reputation: 221