Implementieren Sie eine einfache Stoppuhr


25

Herausforderung

Ihre Aufgabe ist es, ein Programm zu schreiben, das einmal pro Sekunde (auch unmittelbar nach dem Start Ihres Programms) die seit dem Start Ihres Programms verstrichene Zeit ausgibt.

Regeln

  • Die Zeit muss im hh:mm:ssFormat gedruckt werden. (führende Nullen für einstellige Werte)
  • Die Zeitstempel müssen durch CR, LF oder CRLF getrennt werden. (kein führendes Leerzeichen)
  • Jede Sekunde muss eine neue Zeit erscheinen. (stdout kann nicht für eine Sekunde gepuffert werden)
  • Das Verhalten des Programms nach 23:59:59 ist undefiniert.
  • Sie können sleep(1)auch dann verwenden , wenn eine bestimmte Sekunde übersprungen wird, wenn sich der Aufwand für Drucken, Berechnen, Schleifen usw. auf eine Sekunde summiert.

Beispielausgabe:

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

Beachten Sie, dass 00:00:03hier aufgrund von Verarbeitungsaufwand fehlt. Die tatsächlich übersprungenen Werte (falls vorhanden) hängen natürlich von der Implementierung und / oder dem System ab.

Referenzimplementierung in C: (nur POSIX-kompatible Systeme)

#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);
    }
}

Gewinnkriterien

Dies ist , kürzester Code in Bytes zu gewinnen!


Beachten Sie, dass für spätere Herausforderungen eine Klarstellung in den Kommentaren eine schlechte Sache ist. reference
user202729

Antworten:


9

MATL , 17 16 Bytes

`Z`12L/13XOD1Y.T

Probieren Sie es bei MATL Online!

Wie es funktioniert

`         % 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)

4
Wie um alles in der Welt haben Sie diese 37 Minuten nach Schließung beantwortet? o_O beschuldigt Caching
Mr. Xcoder

9
@ Mr.Xcoder Ich habe vor kurzem gelernt, die Macht zu benutzen
Luis Mendo

29

Operation Flashpoint- Skriptsprache,  174  171 Byte

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 Aktion:

158 Bytes, wenn die vorherige Zeit beim nächsten Mal überschrieben wird:

#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"

Technisch wird kein Wagenrücklauf verwendet, daher bin ich mir nicht sicher, ob diese Version auf die Regeln beschränkt ist.


5
Ich hatte nicht mit einem Flammpunkt gerechnet.
Polyducks

10
@Polyducks niemand erwartet Operation Flammpunkt
Pureferret


Da in Unix ein CR die Zeile überschreibt, denke ich, dass die zweite Antwort durch "entweder CR, LF oder CRLF sind erlaubt" validiert wird
Stan Strum

1
@StanStrum Zumindest auf meinem Ubuntu CRwird die Zeile nicht überschrieben. In der Tat CRLF, LFCRund LFalle sind semantisch äquivalent.

13

Bash + Coreutils, 28 26 Bytes

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

Das nicht druckbare Zeichen zwischen +und %ist ein ESC- Byte.

Dies setzt die Systemzeit auf 00:00:00 und erfordert daher Root-Rechte. Es wird außerdem davon ausgegangen, dass die Zeitzone UTC ist und dass keine anderen Prozesse die Systemuhr stören.

Jedes neue Timing setzt das Terminal zurück und überschreibt damit das vorherige.


Bash + Coreutils, 38 29 Bytes

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

Es gelten die gleichen Einschränkungen wie zuvor. Jedes neue Timing wird in einer neuen Zeile angezeigt.


Da es den Bytecount nicht ändert, würde ich den ersten datemit einem netten kleinen Zeilenvorschub vom Rest trennen . Aber es könnte zu schön für jemanden sein, der in der Lage ist, sich so etwas wie Ihre zweite Lösung auszudenken> :-(
Aaron

date -s0gibt die neue Zeit in STDOUT aus; Ich benutze die Pipe, um diese Ausgabe zum Schweigen zu bringen.
Dennis

Oh ja, danke für die Erklärung!
Aaron

5

APL (Dyalog Unicode) , 51 Byte

Voller Programmteil.

s←⎕AI
1↓∊':'@1∘⍕¨100+30 60 60 1E33⊃⎕AI-s
DL 1
2

Probieren Sie es online! (Drücken Sie STRG + EINGABETASTE, um zu starten und erneut, um zu stoppen.)

⎕AIA ccount I nformation (Benutzer - ID, Rechenzeit, Verbindungsdauer, Keying Zeit)

s← zuweisen s(für s Startzeit)
⎕AI-s subtrahieren svon⎕AI

3⊃ Wählen Sie das dritte Element (Verbindungszeit in Millisekunden), und
0 60 60 1E3⊤konvertieren Sie es in diese gemischte Basis.
3↑ Nehmen Sie die ersten 3 (Lässt die Millisekunden fallen),
100+ die zu jeder
':'@1∘⍕¨ Änderung (zum Auffüllen von Nullen) mit einem Doppelpunkt am ersten Zeichen der Zeichenfolgendarstellung jedes
ϵ hinzugefügt wurden nlist (flatten) löscht
1↓ den ersten Doppelpunkt (und druckt implizit auf stdout)

⎕DL 1D e l ay eine Sekunde

→2 gehe zu Zeile Nummer zwei


5

R , 59 44 Bytes

Fin R ist der Standardwert FALSE, aber es ist eine reguläre Variable und kann neu definiert werden. Bei Verwendung in der Arithmetik FALSEwird dazu gezwungen 0. Nachfragen F+1kehrt daher zurück 1. Wir weisen Fzu sein F+1, formatieren es schön, drucken und warten eine Sekunde. Fährt auf unbestimmte Zeit fort.

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

Funktioniert nicht mit TIO (aufgrund des Fehlens des hmsPakets), aber hier ist eine Beispielausgabe von meinem Computer:

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

5

Bash + Sleep + Date, auch 50 49 47 46 45 41 Bytes

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

Um eine Rundenzeit zu nehmen, drücke schnell ^ C, führe dies aus und führe dann das oben Gesagte erneut aus:

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

Zurücksetzen:

s=0; unset laps

Die Syntax von $ [s ++] scheint weiterhin zu funktionieren, ist jedoch in der bashManpage nicht mehr (AFAICS) dokumentiert . Und es ist immer noch ein Byte kürzer als die for ((...)) - Schleife, nachdem ich die Anführungszeichen entfernt habe.


AFAICT $[]ist eine veraltete / undokumentierte, aber immer noch unterstützte Form von$(()) . Ich bin mir nicht sicher, ob es häufig in Code-Golf-Antworten verwendet wird, aber die allgemeine Regel lautet, dass Ihr Code nur an mindestens einer Version des Interpreters für Ihre Sprache funktionieren muss. IMO ist es in Ordnung.
Peter Cordes

s=0ist nicht erforderlich, da durch arithmetische Substitution eine nicht festgelegte Variable als 0 behandelt wird . -uwird auch nicht benötigt, wenn Sie nur die Standard-Zeitzone (UTC) annehmen.
Dennis

-u wird auf meinem Computer benötigt :)
Will Crawford

4

Schnell , 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)}

Erläuterung

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
}

4

JavaScript (ES6), 99 Byte

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


2
Die Stunden beginnen für mich nicht bei 0. Der Versatz ändert sich abhängig von der Zeitzone der Systemuhr. (Win10)
LukeS

@LukeS Whoops, behoben!
Darrylyeo

4

Matlab (R2016b), 50 Byte

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

Erläuterung:

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

Alternative Version (auch 50 Bytes: P):

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

Willkommen auf der Seite! :)
DJMcMayhem

Vielen Dank Kumpel:)
Thiago Oleinik

@ LuisMendo Vielen Dank für den Vorschlag, aber ich habe nicht verstanden ... In Ihrem Beispiel, was ist die Variable t? Außerdem ist die Eingabe datestrin Tagen, so dass ich durch teilen 86400müsste, was die Byteanzahl um zwei erhöhen würde ...
Thiago Oleinik

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

Probieren Sie es online!

Wenn sleep (1) zulässig ist, sind einfache verschachtelte for-Schleifen kürzer als die integrierten Time-Handling-Methoden von Julias.

Alte Lösung ohne Schlaf (1) mit DateTime

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

tist die Zeitspanne von 'Tag 0' bis zum Start des Programms. now()-tist ein Moment in der Zeit , der dann mit formatiert wird Dates.format().

t0=now(); ...; now()-t0würde einen Zeitunterschied ergeben , mit dem nicht gearbeitet werden kann Dates.format().

Das Timing selbst ist mit dem Einbau trivial Timer.


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


Sie können durch das Ersetzen eines Bytes speichern "%02d:%02d:%02d"mit(":%02d"*3)[1:]
wnnmaw

1
Du brauchst nicht %24, Verhalten ist danach undefiniert 23:59:59.
Erik der Outgolfer

@EriktheOutgolfer Guter Punkt, aktualisiert.
Neil

3

JavaScript (ES6), 88 Byte

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

Im Wesentlichen derselbe Ansatz wie bei @ darrylyeo , funktioniert jedoch für alle Zeitzonen und verwendet einen etwas anderen Weg, um zu 0 zu gelangen.

[Bearbeiten] Darryls Antwort wurde korrigiert. Dies ist jedoch immer noch kürzer.


3

> <> , 82 + 7 = 89 Bytes

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

Probieren Sie es online!

+7 Bytes für die Verwendung des Flags -t.0125, damit jeder Befehl 1/80 Sekunde dauert. Jede Schleife enthält 80 Anweisungen, sodass jede Schleife eine Sekunde lang ist. Aufgrund der Rechenzeit ist dies in der Praxis tatsächlich länger.

Ich hatte eigentlich diesen ganzen Weg zum Puffern von bis zu 100 , bis ich @Not A Tree sah Antwort , die 7 Byte besseren Weg hatte als ich die Stunden und Minuten zu erzeugen, ist es unter 80 Trimmen Sie inspirieren auch die Verwendung von \/denen zweimal ausgeführt werden pro Schleife.

Wie es funktioniert

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:

Eine einzeilige Version der gleichen Größe, 80 + 9 Bytes:

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

Dies verwendet das -aFlag, um Häkchen für übersprungene Anweisungen hinzuzufügen.


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;

PHP Open Tags können in der Antwort weggelassen werden, wodurch Sie 6 Bytes sparen.
Daniel W.

2

Python 3 , 112 Bytes

Angenommen, es werden 1-Sekunden-Verzögerungen verwendet, auch wenn (selten) eine Sekunde übersprungen wird.

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)

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

Im unmittelbaren Fenster ausführen: Erwarteter Fehlerpunkt in etwa 23 Millionen Jahren (Gleitkommaauflösung schlägt fehl, ~ 8,5e9 Tage)



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")}}

Funktioniert nicht in TIO.


Ihr Programm scheint 00:00:00im Moment des Starts nicht gedruckt zu werden.
User202729

Behoben. Danke
Noskcaj


2

Bash + Coreutils + GNU-Datum, 50 Bytes

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

Inspiriert von @Dennis, benötigt diese Lösung keine Zeit, um geändert zu werden. Es speichert den anfänglichen Versatz von jetzt bis zur UNIX-Epoche (1. Januar 1970 00:00:00 UTC) in 'o' und zeigt dann [-ud options] (den aktuellen Zeitversatz) in UTC-Datum an, aber nur [+% X Option] HH: MM: SS. Dies sollte in Ländern funktionieren, in denen die aktuelle Zeitzone nicht UTC ist.


2

Sauber , 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]

Dieser funktioniert nur unter den Windows Clean-Bundles.

Fügen Sie 3 Bytes hinzu, wenn Sie möchten, dass es unter Linux funktioniert, wie Clean CLK_PER_TICK :== 1000000auf * nix. Wenn Sie möchten, dass es plattformübergreifend ist, fügen Sie stattdessen 8 Byte hinzu, da Sie CLK_PER_TICKanstelle des festgelegten Werts verwenden müssen. ( TIO-Link ist größer wegen oben )

Probieren Sie es online!


2

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

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

Dies wird in einer Endlosschleife ausgeführt, ohne zu schlafen, wobei die Zeit in derselben Zeile aktualisiert wird, anstatt jede Sekunde eine neue Zeile zu drucken. (Nach den Regeln noch erlaubt, hoffe ich.)

Diese etwas längere Version (72 + 3 = 75 Byte) wird stattdessen jede Sekunde in einer neuen Zeile gedruckt:

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

Beides setzt voraus, dass Sie sich in der UTC-Zeitzone befinden. Unter Linux können Sie dies erreichen, indem Sie die TZUmgebungsvariable festlegen. Eg TZ= python.


2

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

Vielen Dank an Jo King für den Hinweis auf die -aFlagge! Überprüfen Sie auch ihre Antwort .

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

Probieren Sie es online! (aber Sie müssen auf die 60 Sekunden warten).

Ich muss eine Funktion von> <> verwenden, die ich noch nie zuvor benötigt habe: Für diesen Code ist das Flag erforderlich -t.0125, mit dem die Ausführungsgeschwindigkeit auf 0,0125 Sekunden pro Tick oder 80 Ticks pro Sekunde festgelegt wird. Es gibt auch die -aFlagge, bei der Leerzeichen als Häkchen gezählt werden (in einigen Fällen ist der Interpreter etwas seltsam).

Grundsätzlich behält der Code einen Zähler bei, der jedes Mal erhöht wird, wenn der Fisch die Schleife durchläuft, und der Rest der Schleife konvertiert den Zähler in das hh:mm:ssFormat und druckt ihn aus. Die Schleife dauert genau 80 Ticks.

Dies sollte theoretisch funktionieren, aber in der Praxis ist jeder Tick aufgrund der Rechenzeit etwas länger als 0,0125 Sekunden. Wenn Sie \\in der zweiten Zeile auf <<ändern, erhalten Sie genauere Timings für TIO.

Sie können den Code auch auf dem Fischspielplatz in Aktion sehen, mit der Ausnahme, dass dieser Interpreter Leerzeichen etwas anders behandelt als der offizielle Interpreter. Alternativ können Sie die Flags auf TIO entfernen, damit der Code mit maximaler Geschwindigkeit ausgeführt wird, um das Verhalten nach einer Minute zu überprüfen.


-1 Byte durch Ersetzen des v in der ersten Zeile durch \!und Entfernen von zwei der zusätzlichen <. Noch ein paar Bytes, wenn Sie das verwenden-a Flag verwenden, das Leerzeichen und übersprungene Anweisungen als Häkchen zählt
Jo King

@JoKing, die -aFlagge hat mich ein bisschen mehr Golf spielen lassen, danke! Ich denke, Sie können den \!Trick auch in Ihrem Code anwenden: Probieren Sie es online aus!
Kein Baum

2

Java 8, volles Programm, 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);}}

Probieren Sie es hier aus (Zeitüberschreitung nach 60 Sekunden, daher habe ich den Ruhezustand auf 1 gesetzt, um mehr Ausgabe zu sehen).

Erläuterung:

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, Funktion, 94 Bytes

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

Probieren Sie es hier aus (Zeitüberschreitung nach 60 Sekunden, daher habe ich den Ruhezustand auf 1 gesetzt, um mehr Ausgabe zu sehen).

Erläuterung:

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

Hier ist ein kleines GIF, um zu sehen, dass es wie vorgesehen funktioniert, wenn 1000 ms verwendet werden:

Bildbeschreibung hier eingeben


2

PHP, 59 48 Bytes

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

Inspiriert von Darren Hs Antwort .

Alte Version :

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

PHP Open Tags können in der Antwort weggelassen werden, wodurch Sie 6 Bytes sparen.
Daniel W.

Großartiger Gedanke, aber 3600 muss 86400 sein, ansonsten beginnt der Zähler um 23:00:00 Uhr. Sie gewinnen also leider ein Byte, schlagen mich aber trotzdem um 9!
Darren H

@ DarrenH Ich denke, es hängt von Ihrer Ländereinstellung ab, darüber hatte ich nicht nachgedacht. Ich bin in GMT + 1, deshalb habe ich 3600 hinzugefügt, aber ich denke, für Engländer könnte man das -3600insgesamt entfernen , was 5 Bytes einsparen würde.
roberto06

1

Shell , 177 Bytes

Beachten Sie, dass dies nicht vollständig POSIX-konform ist, da es verwendet wird date +%s, was eine übliche dateErweiterung ist.

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

7
Normalerweise sollten Sie den Leuten die Möglichkeit geben, Ihre Herausforderung zu beantworten, bevor Sie sie selbst beantworten. Ich empfehle eine Woche, da einige nur zu bestimmten Zeiten während der Woche hier sein können.
Adám

1
@Adam Ich habe meine Antwort nicht akzeptiert und zum Zeitpunkt der Veröffentlichung wurden viel kürzere Antworten (wie Ihre) übermittelt.
MarkWeston

1

Ruby, 192 117 Bytes (Gutschrift an 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

Wie funktioniert es?

Verwendung der erweiterten Version (Die Umwandlung in eine Zeit wird als separate Funktion angegeben und verwendet ein anderes Ausgabeformat):

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

6
Willkommen auf der Seite! Jede Antwort auf eine Code-Golf- Herausforderung muss Golf sein. Sie sollten mindestens unnötige Leerzeichen entfernen und 1-stellige Variablennamen verwenden. Das würde man etwa 120 Bytes erhalten, und mit Hilfe printfstatt putskönnen noch ein paar Bytes speichern: Versuchen Sie es online! . Viel Spaß beim Golfen mit PPCG!
Dada

1

APL NARS, 109 63 57 Zeichen

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

3 + 3 + 48 + 3 = 57 (auch die anderen Apl-Lösungen gesehen)

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

Konvertieren Sie das INT ⍵ in der Ziffernfolge auf eine Art und Weise, wenn die Länge dieser Zeichenfolge 1 ist, und fügen Sie eine '0' davor hinzu

{∊⍵,¨':: '}

Kombiniere Array in ⍵ mit dem 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 

1

x86-64-Maschinencode (Linux-Systemaufruf): 78 Byte

RDTSC- Spin-Loop-Timing, Linuxsys_write -Systemaufruf.

x86-64 bietet keine bequeme Möglichkeit, die RDTSC-Referenztaktfrequenz zur Laufzeit abzufragen. Sie können eine MSR lesen (und eine darauf basierende Berechnung durchführen) , aber dies erfordert den Kernel-Modus oder Root + Opening /dev/cpu/%d/msr. Deshalb habe ich beschlossen, die Frequenz als Build-Zeit-Konstante festzulegen. (EinstellenFREQ_RDTSC Bedarf : Jede 32-Bit-Konstante ändert die Größe des Maschinencodes nicht.)

Beachten Sie, dass x86-CPUs seit mehreren Jahren eine feste RDTSC-Frequenz haben, sodass sie nicht als Zeitquelle verwendet werden können als Leistungsindikator für den Kerntakt verwendet werden können, es sei denn, Sie deaktivieren die Frequenzänderungen. (Es gibt aktuelle Leistungsindikatoren für die Zählung realer CPU-Zyklen.) Normalerweise tickt es mit der nominalen Aufkleberfrequenz, z. B. 4,0 GHz für meinen i7-6700k, unabhängig von Turbo oder Stromsparmodus. Wie auch immer, diese Wartezeit hängt nicht vom Lastdurchschnitt ab (wie dies bei einer kalibrierten Verzögerungsschleife der Fall wäre) und reagiert auch nicht auf CPU-Stromsparmaßnahmen.

Dieser Code funktioniert für alle x86-Geräte mit einer Referenzfrequenz unter 2 ^ 32 Hz, dh bis zu ~ 4,29 GHz. Darüber hinaus würden die niedrigen 32 des Zeitstempels in 1 Sekunde vollständig umgebrochen, sodass ich auch die edxhohen 32 Bits des Ergebnisses betrachten müsste .

Zusammenfassung :

Schiebe 00:00:00\nauf den Stapel. Dann in einer Schleife:

  • sys_write Systemaufruf
  • ADC-Schleife über die Ziffern (beginnend mit der letzten), um die Zeit um 1 zu erhöhen. Wrapping / Carry-In mit einem cmp/ behandelt cmov, wobei das CF-Ergebnis den Carry-In für die nächste Ziffer liefert.
  • rdtsc und speichern Sie die Startzeit.
  • drehen Sie, rdtscbis das Delta> = Ticks pro Sekunde der RDTSC-Frequenz ist.

NASM-Auflistung:

 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.

Kommentieren Sie die pauseAnweisung aus, um signifikanten Strom zu sparen: Dies erwärmt einen Kern um ~ 15 ° C ohne pause, aber nur um ~ 9 mit pause. (Auf Skylake, wo pausefür ~ 100 Zyklen statt ~ 5 geschlafen wird. Ich denke, es würde mehr sparen, wenn rdtsces nicht auch langsam wäre, so dass die CPU nicht viel Zeit benötigt).


Eine 32-Bit-Version wäre einige Bytes kürzer, z. B. wenn Sie eine 32-Bit-Version davon verwenden, um die anfängliche 00: 00: 00 \ n-Zeichenfolge zu übertragen.

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

Und auch mit 1 Byte dec edx. Der int 0x80Systemaufruf ABI würde esi / edi nicht verwenden, so dass die Registereinstellung für den Syscall gegenüber lodsb / stosb möglicherweise einfacher ist.


Ich hätte einen nanosleepSystemaufruf verwenden können, aber das war interessanter. Mit root unter Linux ist es möglich, den richtigen MSR zu lesen und programmgesteuert die RDTSC-Frequenz abzurufen.
Peter Cordes

1

q / kdb + , 40 Bytes

Lösung:

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

Beispiel:

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

Erläuterung:

Hier werden drei Befehle ausgeführt:

  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

Aufschlüsselung der Timerfunktion:

.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 für 41 Bytes :

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

Alternative 2 für 26 + 7 Bytes = 33 Bytes

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

und -t 1000als Argumente zur q-Binärdatei hinzufügen .

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.