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:ss
Format 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:03
hier 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 Code-Golf , kürzester Code in Bytes zu gewinnen!
Antworten:
MATL ,
1716 BytesProbieren Sie es bei MATL Online!
Wie es funktioniert
quelle
Operation Flashpoint- Skriptsprache,
174171 ByteIn Aktion:
158 Bytes, wenn die vorherige Zeit beim nächsten Mal überschrieben wird:
Technisch wird kein Wagenrücklauf verwendet, daher bin ich mir nicht sicher, ob diese Version auf die Regeln beschränkt ist.
quelle
CR
wird die Zeile nicht überschrieben. In der TatCRLF
,LFCR
undLF
alle sind semantisch äquivalent.Bash + Coreutils,
2826 BytesDas 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,
3829 BytesEs gelten die gleichen Einschränkungen wie zuvor. Jedes neue Timing wird in einer neuen Zeile angezeigt.
quelle
date
mit 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> :-(date -s0
gibt die neue Zeit in STDOUT aus; Ich benutze die Pipe, um diese Ausgabe zum Schweigen zu bringen.APL (Dyalog Unicode) , 51 Byte
Voller Programmteil.
Probieren Sie es online! (Drücken Sie STRG + EINGABETASTE, um zu starten und erneut, um zu stoppen.)
⎕AI
A ccount I nformation (Benutzer - ID, Rechenzeit, Verbindungsdauer, Keying Zeit)s←
zuweisens
(für s Startzeit)⎕AI-s
subtrahierens
von⎕AI
3⊃
Wählen Sie das dritte Element (Verbindungszeit in Millisekunden), und0 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öscht1↓
den ersten Doppelpunkt (und druckt implizit auf stdout)⎕DL 1
D e l ay eine Sekunde→2
gehe zu Zeile Nummer zweiquelle
R ,
5944 BytesF
in R ist der StandardwertFALSE
, aber es ist eine reguläre Variable und kann neu definiert werden. Bei Verwendung in der ArithmetikFALSE
wird dazu gezwungen0
. NachfragenF+1
kehrt daher zurück1
. Wir weisenF
zu seinF+1
, formatieren es schön, drucken und warten eine Sekunde. Fährt auf unbestimmte Zeit fort.Funktioniert nicht mit TIO (aufgrund des Fehlens des
hms
Pakets), aber hier ist eine Beispielausgabe von meinem Computer:quelle
Bash + Sleep + Date,
auch 504947464541 BytesUm eine Rundenzeit zu nehmen, drücke schnell ^ C, führe dies aus und führe dann das oben Gesagte erneut aus:
Zurücksetzen:
Die Syntax von $ [s ++] scheint weiterhin zu funktionieren, ist jedoch in der
bash
Manpage nicht mehr (AFAICS) dokumentiert . Und es ist immer noch ein Byte kürzer als die for ((...)) - Schleife, nachdem ich die Anführungszeichen entfernt habe.quelle
$[]
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.s=0
ist nicht erforderlich, da durch arithmetische Substitution eine nicht festgelegte Variable als 0 behandelt wird .-u
wird auch nicht benötigt, wenn Sie nur die Standard-Zeitzone (UTC) annehmen.Schnell , 144 Bytes
Erläuterung
quelle
JavaScript (ES6), 99 Byte
quelle
Matlab (R2016b), 50 Byte
Erläuterung:
Alternative Version (auch 50 Bytes: P):
quelle
:)
t
? Außerdem ist die Eingabedatestr
in Tagen, so dass ich durch teilen86400
müsste, was die Byteanzahl um zwei erhöhen würde ...Julia 0,6 ,
7568 BytesProbieren 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
ist die Zeitspanne von 'Tag 0' bis zum Start des Programms.now()-t
ist ein Moment in der Zeit , der dann mit formatiert wirdDates.format()
.t0=now(); ...; now()-t0
würde einen Zeitunterschied ergeben , mit dem nicht gearbeitet werden kannDates.format()
.Das Timing selbst ist mit dem Einbau trivial
Timer
.quelle
Python 2 , 85 Bytes
Credits
quelle
"%02d:%02d:%02d"
mit(":%02d"*3)[1:]
%24
, Verhalten ist danach undefiniert23:59:59
.JavaScript (ES6), 88 Byte
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.
quelle
> <> , 82 + 7 = 89 Bytes
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
Bonus:
Eine einzeilige Version der gleichen Größe, 80 + 9 Bytes:
Dies verwendet das
-a
Flag, um Häkchen für übersprungene Anweisungen hinzuzufügen.quelle
PHP 4+,
7064 BytesPHP 5.3+,
6963 Bytesquelle
Python 3 , 112 Bytes
Angenommen, es werden 1-Sekunden-Verzögerungen verwendet, auch wenn (selten) eine Sekunde übersprungen wird.
quelle
VBA, 90
Im unmittelbaren Fenster ausführen: Erwarteter Fehlerpunkt in etwa 23 Millionen Jahren (Gleitkommaauflösung schlägt fehl, ~ 8,5e9 Tage)
quelle
Jelly , 23 Bytes
Probieren Sie es online!
quelle
AWK ,
1108786 BytesFunktioniert nicht in TIO.
quelle
00:00:00
im Moment des Starts nicht gedruckt zu werden.APL (Dyalog) , 37 Bytes
Probieren Sie es online!
Volles Programm.
Ziemlich ähnlich wie Adáms Antwort, jedoch unabhängig geschrieben und ohne Grundlage
⎕AI
.quelle
Bash + Coreutils + GNU-Datum, 50 Bytes
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.
quelle
Sauber ,
173172168 BytesDieser 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 :== 1000000
auf * nix. Wenn Sie möchten, dass es plattformübergreifend ist, fügen Sie stattdessen 8 Byte hinzu, da SieCLK_PER_TICK
anstelle des festgelegten Werts verwenden müssen. ( TIO-Link ist größer wegen oben )Probieren Sie es online!
quelle
Python 2 , 69 + 3 (
TZ=
) = 72 BytesDies 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:
Beides setzt voraus, dass Sie sich in der UTC-Zeitzone befinden. Unter Linux können Sie dies erreichen, indem Sie die
TZ
Umgebungsvariable festlegen. EgTZ= python
.quelle
> <> ,
106 Bytes82 + 9 = 91 BytesVielen Dank an Jo King für den Hinweis auf die
-a
Flagge! Überprüfen Sie auch ihre Antwort .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-a
Flagge, 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:ss
Format 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.
quelle
\!
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-a
Flagge 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!Java 8, volles Programm, 150 Bytes
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:
Java 8, Funktion, 94 Bytes
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:
Hier ist ein kleines GIF, um zu sehen, dass es wie vorgesehen funktioniert, wenn 1000 ms verwendet werden:
quelle
PHP,
5948 BytesInspiriert von Darren Hs Antwort .
Alte Version :
quelle
-3600
insgesamt entfernen , was 5 Bytes einsparen würde.Shell , 177 Bytes
Beachten Sie, dass dies nicht vollständig POSIX-konform ist, da es verwendet wird
date +%s
, was eine üblichedate
Erweiterung ist.quelle
Ruby,
192117 Bytes (Gutschrift an Dada)Wie funktioniert es?
Verwendung der erweiterten Version (Die Umwandlung in eine Zeit wird als separate Funktion angegeben und verwendet ein anderes Ausgabeformat):
quelle
printf
stattputs
können noch ein paar Bytes speichern: Versuchen Sie es online! . Viel Spaß beim Golfen mit PPCG!APL NARS,
109 6357 Zeichen3 + 3 + 48 + 3 = 57 (auch die anderen Apl-Lösungen gesehen)
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 '::'
quelle
x86-64-Maschinencode (Linux-Systemaufruf): 78 Byte
RDTSC- Spin-Loop-Timing, Linux
sys_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
edx
hohen 32 Bits des Ergebnisses betrachten müsste .Zusammenfassung :
Schiebe
00:00:00\n
auf den Stapel. Dann in einer Schleife:sys_write
Systemaufrufcmp
/ behandeltcmov
, wobei das CF-Ergebnis den Carry-In für die nächste Ziffer liefert.rdtsc
und speichern Sie die Startzeit.rdtsc
bis das Delta> = Ticks pro Sekunde der RDTSC-Frequenz ist.NASM-Auflistung:
Kommentieren Sie die
pause
Anweisung aus, um signifikanten Strom zu sparen: Dies erwärmt einen Kern um ~ 15 ° C ohnepause
, aber nur um ~ 9 mitpause
. (Auf Skylake, wopause
für ~ 100 Zyklen statt ~ 5 geschlafen wird. Ich denke, es würde mehr sparen, wennrdtsc
es 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.
Und auch mit 1 Byte
dec edx
. Derint 0x80
Systemaufruf ABI würde esi / edi nicht verwenden, so dass die Registereinstellung für den Syscall gegenüber lodsb / stosb möglicherweise einfacher ist.quelle
nanosleep
Systemaufruf 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.q / kdb + , 40 Bytes
Lösung:
Beispiel:
Erläuterung:
Hier werden drei Befehle ausgeführt:
.z.ts:{-1($)18h$a+:1}; / override timer function
a:-1; / initialise variable a to -1
(.)"\\t 1000" / start the timer with 1000ms precision
Aufschlüsselung der Timerfunktion:
Bonus:
Alternative 1 für 41 Bytes :
Alternative 2 für 26 + 7 Bytes = 33 Bytes
und
-t 1000
als Argumente zur q-Binärdatei hinzufügen .quelle