Wyzwanie
Twoim zadaniem jest napisanie programu, który raz na sekundę (w tym natychmiast po uruchomieniu programu) drukuje czas, który upłynął od momentu uruchomienia programu.
Zasady
- Czas musi być wydrukowany w
hh:mm:ss
formacie. (wiodące zera dla wartości jednocyfrowych) - Znaczniki czasu muszą być oddzielone CR, LF lub CRLF. (brak wiodących białych znaków)
- Nowy czas musi pojawiać się co sekundę. (standardowe wyjście nie może być buforowane przez sekundę)
- Zachowanie programu, jeśli jest uruchamiany po 23:59:59, jest niezdefiniowane.
- Możesz użyć,
sleep(1)
nawet jeśli określona sekunda może zostać pominięta, ilekroć narzut na wydrukowanie, obliczenie, zapętlenie itp. Narasta do sekundy.
Przykładowe dane wyjściowe:
00:00:00
00:00:01
00:00:02
00:00:04
00:00:05
⋮
Zauważ, że 00:00:03
brakuje go tutaj z powodu narzutu przetwarzania. Rzeczywiste pominięte wartości (jeśli istnieją) są oczywiście zależne od implementacji i / lub systemu.
Referencyjna implementacja w C: (tylko systemy zgodne z POSIX)
#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);
}
}
Kryteria wygranej
To jest golfowy kod, najkrótszy kod w bajtach wygrywa!
Odpowiedzi:
MATL ,
1716 bajtówWypróbuj w MATL Online!
Jak to działa
źródło
Operacyjny język skryptowy Flashpoint ,
174171 bajtówW akcji:
158 bajtów, jeśli poprzedni czas zostanie zastąpiony następnym razem:
Technicznie nie stosuje się powrotu karetki, więc nie jestem pewien, czy ta wersja ogranicza się do zasad.
źródło
CR
nie nadpisze linii. W rzeczywistościCRLF
,LFCR
aLF
są semantycznie równoważne.Bash + coreutils,
2826 bajtówNiedrukowalny znak między
+
i%
jest bajtem ESC .To ustawia czas systemowy na 00:00:00, a zatem wymaga uprawnień roota. Zakłada również, że strefą czasową jest UTC i że żadne inne procesy nie będą zakłócały działania zegara systemowego.
Każde nowe taktowanie resetuje terminal, zastępując w ten sposób poprzedni.
Bash + coreutils,
3829 bajtówObowiązują takie same ograniczenia jak poprzednio. Każdy nowy czas jest wyświetlany w nowym wierszu.
źródło
date
od reszty za pomocą ładnego, małego wiersza. Ale może to być zbyt miłe dla kogoś, kto może wymyślić coś takiego jak twoje drugie rozwiązanie> :-(date -s0
wypisuje nowy czas na STDOUT; Używam potoku do wyciszenia tego wyjścia.APL (Dyalog Unicode) , 51 bajtów
Pełna treść programu.
Wypróbuj online! (Naciśnij Ctrl + Enter, aby rozpocząć, a następnie ponownie, aby zatrzymać).
⎕AI
Ccount I NFORMACJE (identyfikator użytkownika, obliczyć czas, czas połączenia, czasu keying)s←
przypisaćs
(na s tart czas)⎕AI-s
odjąćs
od⎕AI
3⊃
wybierz trzeci element (połącz czas w milisekundach)0 60 60 1E3⊤
przekonwertuj na ten mieszany podstawa3↑
weź pierwsze 3 (upuszcza milisekundy)100+
sto dodane do każdego (aby uzupełnić zera)':'@1∘⍕¨
popraw dwukropkiem pierwszy znak reprezentujący ciąg każdego∊
ϵ nlist (spłaszcz)1↓
upuść pierwszy dwukropek (i domyślnie wypisz na standardowe wyjście)⎕DL 1
D E L Ay jedna sekunda→2
przejdź do wiersza drugiegoźródło
R ,
5944 bajtówF
w R domyślnie jestFALSE
, ale jest to zmienna regularna i można ją przedefiniować. Stosowany w arytmetyceFALSE
jest zmuszany do0
. WF+1
związku z tym prosi o zwrot1
. PrzypisujemyF
by byćF+1
, ładnie go sformatujemy, wydrukujemy i poczekamy sekundę. Trwa w nieskończoność.Nie działa na TIO (z powodu braku
hms
pakietu), ale oto przykładowe wyjście z mojej maszyny:źródło
bash + sen + data,
również 504947464541 bajtówAby wziąć czas okrążenia, szybko naciśnij ^ C, uruchom to, a następnie uruchom ponownie powyższe:
Zresetować:
Składnia $ [s ++] wydaje się nadal działać, ale nie jest już (AFAICS) udokumentowana na
bash
stronie podręcznika . I nadal jest o bajt krótszy niż przy użyciu pętli for ((...)), kiedy usunęłem otaczające go cudzysłowy.źródło
$[]
jest przestarzałą / nieudokumentowaną, ale nadal obsługiwaną formą$(())
. Nie jestem pewien, czy jest powszechnie używany w odpowiedziach na golfa, ale ogólna zasada mówi, że Twój kod musi działać tylko na co najmniej jednej wersji interpretera dla twojego języka. IMO jest w porządku.s=0
nie jest wymagane, ponieważ podstawienie arytmetyczne potraktuje zmienną nieustawioną jako 0 .-u
nie jest również potrzebny, jeśli przyjmiesz domyślną strefę czasową (UTC).Szybki , 144 bajty
Wyjaśnienie
źródło
JavaScript (ES6), 99 bajtów
źródło
Matlab (R2016b), 50 bajtów
Wyjaśnienie:
Wersja alternatywna (również 50 bajtów: P):
źródło
:)
t
? Ponadto dane wejściowedatestr
są w dniach, więc musiałbym się podzielić86400
, co zwiększyłoby liczbę bajtów o dwa ...Julia 0.6 ,
7568 bajtówWypróbuj online!
Przy dozwolonym sleep (1) proste zagnieżdżone pętle for są krótsze niż przy użyciu wbudowanych metod obsługi czasu Julias.
Stare rozwiązanie bez uśpienia (1) przy użyciu DateTime
t
to czas, który upłynął od „dnia 0” do uruchomienia programu.now()-t
jest momentem w czasie , który jest następnie formatowany za pomocąDates.format()
.t0=now(); ...; now()-t0
dałoby różnicę czasu , której nie można użyćDates.format()
.Sam czas jest trywialny z wbudowanym
Timer
.źródło
Python 2 , 85 bajtów
Kredyty
źródło
"%02d:%02d:%02d"
z(":%02d"*3)[1:]
%24
, zachowanie jest niezdefiniowane23:59:59
.JavaScript (ES6), 88 bajtów
Zasadniczo takie samo podejście jak odpowiedź @ darrylyeo , ale działa dla wszystkich stref czasowych i używa nieco innego sposobu na uzyskanie 0.
[Edytuj] Odpowiedź Darryla została naprawiona. Jest to jednak jeszcze krótsze.
źródło
> <> , 82 + 7 = 89 bajtów
Wypróbuj online!
+7 bajtów za użycie flagi,
-t.0125
aby każda instrukcja trwała 1/80 sekundy. Każda pętla ma 80 instrukcji, dzięki czemu każda pętla trwa jedną sekundę. Ze względu na czas obliczeń jest to w rzeczywistości dłuższe w praktyce.I rzeczywiście miał do bufora to przez całą drogę aż do 100 Widziałem @Not drzewa za odpowiedź , która miała 7 bajt lepszy sposób niż kopalnia generowania godziny i minuty, przycinanie go poniżej 80. zainspirowały one również stosowanie
\/
które są wykonywane dwa razy na pętlę.Jak to działa
Premia:
Jednowierszowa wersja tego samego rozmiaru, 80 + 9 bajtów:
Używa
-a
flagi, aby dodać tiki dla pominiętych instrukcji.źródło
PHP 4+,
7064 bajtyPHP 5.3+,
6963 bajtyźródło
Python 3 , 112 bajtów
Zakładanie, że użycie 1-sekundowych opóźnień jest w porządku, nawet jeśli (rzadko) może pominąć sekundę.
źródło
VBA, 90
uruchom w bezpośrednim oknie: oczekiwany punkt awarii około 23 milionów lat (rozdzielczość zmiennoprzecinkowa kończy się niepowodzeniem ~ 8,5e9 dni)
źródło
Galaretka , 23 bajty
Wypróbuj online!
źródło
AWK ,
1108786 bajtówNie działa w TIO.
źródło
00:00:00
w chwili uruchomienia.APL (Dyalog) , 37 bajtów
Wypróbuj online!
Pełny program
Całkiem podobne do odpowiedzi Adáma, jednak niezależnie napisane i
⎕AI
oparte na podejściu nieopartym na podstawach.źródło
Bash + coreutils + data GNU, 50 bajtów
Zainspirowane @Dennis, to rozwiązanie nie wymaga czasu na zmianę. Przechowuje początkowe przesunięcie od teraz do epoki UNIX (1 stycznia 1970 r. 00:00:00 UTC), w „o”, a następnie wyświetla [opcje -ud] (bieżący czas - przesunięcie), w dacie UTC, ale tylko [opcja +% X] GG: MM: SS. Powinno to działać w krajach, w których bieżąca strefa czasowa nie jest zgodna z UTC.
źródło
Czysty ,
173172168 bajtówTen działa tylko w pakietach Windows Clean.
Dodaj 3 bajty, jeśli chcesz, aby działało pod Linuksem, tak jak Clean
CLK_PER_TICK :== 1000000
na * nix. Jeśli chcesz, aby był wieloplatformowy, dodaj zamiast tego 8 bajtów, ponieważ musisz użyćCLK_PER_TICK
zamiast wartości, którą ma ustawić. ( Link TIO jest większy z powodu powyższego )Wypróbuj online!
źródło
Python 2 , 69 + 3 (
TZ=
) = 72 bajtyDziała to w ciągłej pętli, bez uśpienia, aktualizując czas na tej samej linii, zamiast drukować nową linię co sekundę. (Mam nadzieję, że nadal są dozwolone przez reguły).
Ta nieco dłuższa wersja (72 + 3 = 75 bajtów) drukuje w nowej linii co sekundę:
Oba wymagają przebywania w strefie czasowej UTC. W systemie Linux można to osiągnąć, ustawiając
TZ
zmienną środowiskową. NpTZ= python
.źródło
> <> ,
106 bajtów82 + 9 = 91 bajtówDzięki Jo King za sugestię
-a
flagi! Sprawdź również ich odpowiedź .Wypróbuj online!(ale musisz poczekać 60 sekund).
Muszę użyć funkcji> <>, której nigdy wcześniej nie potrzebowałem: ten kod wymaga flagi
-t.0125
, która ustawia szybkość wykonywania na 0,0125 sekundy na tik lub 80 tyknięć na sekundę. Jest też-a
flaga, która powoduje, że białe znaki są liczone jako tyknięcie (w niektórych przypadkach - tłumacz jest nieco dziwny).Zasadniczo kod utrzymuje licznik, który jest zwiększany za każdym razem, gdy ryba przechodzi przez pętlę, a reszta pętli konwertuje licznik na
hh:mm:ss
format i drukuje go. Pętla zajmuje dokładnie 80 tyknięć.Powinno to działać w teorii, ale w praktyce każdy tik jest nieco dłuższy niż 0,0125 sekundy, z powodu czasu obliczeń. Zmiana
\\
drugiej linii w celu<<
dokładniejszego pomiaru czasu w TIO.Możesz także obejrzeć kod w akcji na placu zabaw dla ryb , z tym wyjątkiem, że ten interpreter traktuje białe znaki nieco inaczej niż oficjalny tłumacz. Ewentualnie możesz usunąć flagi w TIO, aby kod działał z najwyższą prędkością, aby zweryfikować zachowanie czasów po minucie.
źródło
\!
i usuwając dwa dodatkowe<
. Kolejna para bajtów, jeśli używasz-a
flagi, która liczy białe znaki i pomija instrukcje jako tyknięcia-a
Flaga pozwala mi zagrać w golfa trochę więcej, dziękuję! Myślę, że możesz także użyć tej\!
sztuczki w kodzie: wypróbuj online!Java 8, pełny program, 150 bajtów
Wypróbuj tutaj (upłynie limit czasu po 60 sekundach, więc ustawiłem sen na 1, aby zobaczyć więcej wyników).
Wyjaśnienie:
Java 8, funkcja, 94 bajty
Wypróbuj tutaj (upłynie limit czasu po 60 sekundach, więc ustawiłem sen na 1, aby zobaczyć więcej wyników).
Wyjaśnienie:
Oto mały gif, który pokazuje, że działa zgodnie z przeznaczeniem, gdy używane jest 1000 ms:
źródło
PHP,
5948 bajtówZainspirowany odpowiedź Darren H użytkownika .
Stara wersja :
źródło
-3600
całkowicie usunąć , co zaoszczędziłoby 5 bajtów.Shell , 177 bajtów
Zauważ, że nie jest to w pełni zgodne z POSIX, ponieważ używa
date +%s
, co jest powszechnymdate
rozszerzeniem.źródło
Ruby,
192117 bajtów (kredyt dla Dady)Jak to działa?
Zamierzam użyć wersji rozszerzonej (konwersja do czasu jest podawana jako osobna funkcja i używa innego formatu wyjściowego):
źródło
printf
zamiastputs
może zaoszczędzić jeszcze kilka bajtów: Wypróbuj online! . Miłej gry w golfa na PPCG!APL NARS,
109 6357 znaków3 + 3 + 48 + 3 = 57 (widziałem także inne rozwiązania Apl)
przekonwertować INT ⍵ w ciągu cyfr w taki sposób, jeśli długość tego ciągu wynosi 1, niż dodać jedno „0” przed nim
łączyć tablicę w ⍵ z tablicą „::”
źródło
Kod maszynowy x86-64 (wywołanie systemowe Linux): 78 bajtów
Czas taktowania pętli RDTSC , Linux
sys_write
wywołanie systemowe .x86-64 nie zapewnia wygodnego sposobu sprawdzania częstotliwości „zegara referencyjnego” RDTSC w czasie wykonywania. Możesz odczytać MSR (i wykonać na tej podstawie obliczenia) , ale wymaga to trybu jądra lub otwarcia roota +
/dev/cpu/%d/msr
, więc postanowiłem, że częstotliwość będzie stała. (DostosowaćFREQ_RDTSC
odpowiednio: dowolna 32-bitowa stała nie zmieni rozmiaru kodu maszynowego)Zauważ, że procesory x86 od kilku lat mają stałą częstotliwość RDTSC, więc można je wykorzystać jako źródło czasu, a nie a licznik wydajności taktowania rdzenia, chyba że podejmiesz kroki w celu wyłączenia zmian częstotliwości. (Istnieją rzeczywiste liczniki perf do zliczania rzeczywistych cykli procesora.) Zwykle tyka przy nominalnej częstotliwości naklejki, np. 4,0 GHz dla mojego i7-6700k, niezależnie od turbo lub oszczędzania energii. W każdym razie ten czas oczekiwania na zajęcie nie zależy od średniego obciążenia (jak skalibrowana pętla opóźniająca), a także nie jest wrażliwy na oszczędność energii procesora.
Ten kod będzie działał dla każdego x86 o częstotliwości odniesienia poniżej 2 ^ 32 Hz, tj. Do ~ 4,29 GHz. Poza tym niski 32 znacznik czasu zawinąłby się do końca w ciągu 1 sekundy, więc musiałbym też spojrzeć na
edx
wysokie 32 bity wyniku.Podsumowanie :
pchnij
00:00:00\n
na stosie. Następnie w pętli:sys_write
wywołanie systemowecmp
/cmov
, przy czym wynik CF zapewnia wprowadzanie następnej cyfry.rdtsc
i oszczędzaj czas rozpoczęcia.rdtsc
momentu delta> = kleszczy na sekundę częstotliwości RDTSC.Lista NASM:
Odkomentuj
pause
instrukcję oszczędzania znacznej mocy: podgrzewa jeden rdzeń o ~ 15 stopni C bezpause
, ale tylko o ~ 9 zpause
. (Na Skylake, gdziepause
śpi przez ~ 100 cykli zamiast ~ 5. Myślę, że zaoszczędziłoby więcej, gdybyrdtsc
nie było również spowolnienie, więc procesor nie zajmuje dużo czasu).Wersja 32-bitowa byłaby o kilka bajtów krótsza, np. Przy użyciu 32-bitowej wersji do wypchnięcia początkowego ciągu 00: 00: 00 \ n.
A także przy użyciu 1-bajtu
dec edx
.int 0x80
Wywołanie systemowe ABI nie użyłby ESI / edi, więc konfiguracja rejestr dla syscall vs. lodsb / stosb może być prostsze.źródło
nanosleep
wywołania systemowego, ale to było bardziej interesujące. Dzięki rootowi w Linuksie można odczytać właściwy MSR i programowo uzyskać częstotliwość RDTSC.q / kdb + , 40 bajtów
Rozwiązanie:
Przykład:
Wyjaśnienie:
W tym miejscu wykonywane są trzy polecenia:
.z.ts:{-1($)18h$a+:1}; / override timer function
a:-1; / initialise variable a to -1
(.)"\\t 1000" / start the timer with 1000ms precision
Podział funkcji timera:
Premia:
Alternatywa 1 dla 41 bajtów :
Alternatywa 2 dla 26 + 7 bajtów = 33 bajty
i dodawanie
-t 1000
jako argumentów do binarnego q.źródło