Zaimplementuj prosty stoper


25

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:ssformacie. (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:03brakuje 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 kod, najkrótszy kod w bajtach wygrywa!


Uwaga na późniejsze wyzwania, wyjaśnienia w komentarzach to zła rzecz. odniesienie
user202729,

Odpowiedzi:


9

MATL , 17 16 bajtów

`Z`12L/13XOD1Y.T

Wypróbuj w MATL Online!

Jak to działa

`         % 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
Jak, u licha, odpowiedziałeś na to 37 minut po zamknięciu? o_O obwinia buforowanie
Mr. Xcoder,

9
@ Mr.Xcoder Niedawno nauczyłem się korzystać z Mocy
Luis Mendo

29

Operacyjny język skryptowy Flashpoint ,  174  171 bajtów

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"

W akcji:

158 bajtów, jeśli poprzedni czas zostanie zastąpiony następnym razem:

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

Technicznie nie stosuje się powrotu karetki, więc nie jestem pewien, czy ta wersja ogranicza się do zasad.


5
Nie spodziewałem się punktu zapalnego operacji.
Polyducks

10
@Polyducks nikt nie spodziewa się punktu zapalnego operacji
Pureferret


Ponieważ w Unixie CR zastąpi linię, myślę, że druga odpowiedź jest potwierdzona przez: „CR, LF lub CRLF są dozwolone”
Stan Strum

1
@StanStrum Przynajmniej na moim Ubuntu CRnie nadpisze linii. W rzeczywistości CRLF, LFCRa LFsą semantycznie równoważne.

13

Bash + coreutils, 28 26 bajtów

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

Niedrukowalny 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, 38 29 bajtów

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

Obowiązują takie same ograniczenia jak poprzednio. Każdy nowy czas jest wyświetlany w nowym wierszu.


Ponieważ to nie zmienia liczby bajtów, pierwszą oddzielę dateod 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> :-(
Aaron

date -s0wypisuje nowy czas na STDOUT; Używam potoku do wyciszenia tego wyjścia.
Dennis

No dobrze, dziękuję za wyjaśnienie!
Aaron

5

APL (Dyalog Unicode) , 51 bajtów

Pełna treść programu.

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

Wypróbuj online! (Naciśnij Ctrl + Enter, aby rozpocząć, a następnie ponownie, aby zatrzymać).

⎕AICcount I NFORMACJE (identyfikator użytkownika, obliczyć czas, czas połączenia, czasu keying)

s← przypisać s(na s tart czas)
⎕AI-s odjąć sod⎕AI

3⊃ wybierz trzeci element (połącz czas w milisekundach)
0 60 60 1E3⊤przekonwertuj na ten mieszany podstawa
3↑ 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 1D E L Ay jedna sekunda

→2 przejdź do wiersza drugiego


5

R , 59 44 bajtów

Fw R domyślnie jest FALSE, ale jest to zmienna regularna i można ją przedefiniować. Stosowany w arytmetyce FALSEjest zmuszany do 0. W F+1związku z tym prosi o zwrot 1. Przypisujemy Fby być F+1, ładnie go sformatujemy, wydrukujemy i poczekamy sekundę. Trwa w nieskończoność.

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

Nie działa na TIO (z powodu braku hmspakietu), ale oto przykładowe wyjście z mojej maszyny:

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 + sen + data, również 50 49 47 46 45 41 bajtów

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

Aby wziąć czas okrążenia, szybko naciśnij ^ C, uruchom to, a następnie uruchom ponownie powyższe:

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

Zresetować:

s=0; unset laps

Składnia $ [s ++] wydaje się nadal działać, ale nie jest już (AFAICS) udokumentowana na bashstronie podręcznika . I nadal jest o bajt krótszy niż przy użyciu pętli for ((...)), kiedy usunęłem otaczające go cudzysłowy.


AFAICT, $[]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.
Peter Cordes,

s=0nie jest wymagane, ponieważ podstawienie arytmetyczne potraktuje zmienną nieustawioną jako 0 . -unie jest również potrzebny, jeśli przyjmiesz domyślną strefę czasową (UTC).
Dennis

-u jest potrzebne na mojej maszynie :)
Will Crawford

4

Szybki , 144 bajty

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

Wyjaśnienie

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 bajtów

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


2
Dla mnie godziny nie zaczynają się od 0. Przesunięcie zmienia się w zależności od strefy czasowej zegara systemowego. (Win10)
Łukasza

@LukeS Ups, naprawione!
darrylyeo

4

Matlab (R2016b), 50 bajtów

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

Wyjaśnienie:

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

Wersja alternatywna (również 50 bajtów: P):

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

Witamy na stronie! :)
DJMcMayhem

Dzięki kolego:)
Thiago Oleinik,

@LuisMendo Dzięki za sugestię, ale nie zrozumiałem ... W twoim przykładzie, jaka jest zmienna t? Ponadto dane wejściowe datestrsą w dniach, więc musiałbym się podzielić 86400, co zwiększyłoby liczbę bajtów o dwa ...
Thiago Oleinik

3

Julia 0.6 , 75 68 bajtów

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

Wypró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=now()-DateTime(0);Timer(x->println(Dates.format(now()-t,"HH:MM:SS")),0,1)

tto czas, który upłynął od „dnia 0” do uruchomienia programu. now()-tjest momentem w czasie , który jest następnie formatowany za pomocą Dates.format().

t0=now(); ...; now()-t0dałoby różnicę czasu , której nie można użyć Dates.format().

Sam czas jest trywialny z wbudowanym Timer.


3

Python 2 , 85 bajtów

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

Kredyty


Można zapisać jeden bajt zastępując "%02d:%02d:%02d"z(":%02d"*3)[1:]
wnnmaw

1
Nie potrzebujesz %24, zachowanie jest niezdefiniowane 23:59:59.
Erik the Outgolfer,

@EriktheOutgolfer Dobry punkt, zaktualizowano.
Neil

3

JavaScript (ES6), 88 bajtów

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

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.


3

> <> , 82 + 7 = 89 bajtów

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

Wypróbuj online!

+7 bajtów za użycie flagi, -t.0125aby 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

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

Premia:

Jednowierszowa wersja tego samego rozmiaru, 80 + 9 bajtów:

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

Używa -aflagi, aby dodać tiki dla pominiętych instrukcji.


3

PHP 4+, 70 64 bajty

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

PHP 5.3+, 69 63 bajty

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

Otwarte znaczniki PHP można pominąć w odpowiedzi, oszczędzając Ci 6 bajtów.
Daniel W.,

2

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ę.

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

uruchom w bezpośrednim oknie: oczekiwany punkt awarii około 23 milionów lat (rozdzielczość zmiennoprzecinkowa kończy się niepowodzeniem ~ 8,5e9 dni)



2

AWK , 110 87 86 bajtów

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

Nie działa w TIO.


Twój program nie wydaje się drukować 00:00:00w chwili uruchomienia.
user202729,

Naprawione. Dzięki
Noskcaj,


2

Bash + coreutils + data GNU, 50 bajtów

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

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.


2

Czysty , 173 172 168 bajtów

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]

Ten 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 :== 1000000na * nix. Jeśli chcesz, aby był wieloplatformowy, dodaj zamiast tego 8 bajtów, ponieważ musisz użyć CLK_PER_TICKzamiast wartości, którą ma ustawić. ( Link TIO jest większy z powodu powyższego )

Wypróbuj online!


2

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

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

Dział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ę:

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

Oba wymagają przebywania w strefie czasowej UTC. W systemie Linux można to osiągnąć, ustawiając TZzmienną środowiskową. Np TZ= python.


2

> <> , 106 bajtów 82 + 9 = 91 bajtów

Dzięki Jo King za sugestię -aflagi! Sprawdź również ich odpowiedź .

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

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ż -aflaga, 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.


-1 bajt, zastępując v w pierwszym wierszu \!i usuwając dwa dodatkowe <. Kolejna para bajtów, jeśli używasz -aflagi, która liczy białe znaki i pomija instrukcje jako tyknięcia
Jo King,

@ JoKing, -aFlaga 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!
Nie drzewo,

2

Java 8, pełny program, 150 bajtów

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

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:

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, funkcja, 94 bajty

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

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:

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

Oto mały gif, który pokazuje, że działa zgodnie z przeznaczeniem, gdy używane jest 1000 ms:

wprowadź opis zdjęcia tutaj


2

PHP, 59 48 bajtów

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

Zainspirowany odpowiedź Darren H użytkownika .

Stara wersja :

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

Otwarte znaczniki PHP można pominąć w odpowiedzi, oszczędzając Ci 6 bajtów.
Daniel W.,

Świetna myśl, ale 3600 musi wynosić 86400, w przeciwnym razie licznik zacznie się o 23:00, więc niestety zyskujesz bajt, ale wciąż bijesz mnie o 9!
Darren H

@DarrenH Myślę, że to zależy od twojej lokalizacji, nie myślałem o tym. Jestem w GMT + 1, dlatego dodałem 3600, ale myślę, że dla Anglików, możesz -3600całkowicie usunąć , co zaoszczędziłoby 5 bajtów.
roberto06

1

Shell , 177 bajtów

Zauważ, że nie jest to w pełni zgodne z POSIX, ponieważ używa date +%s, co jest powszechnym daterozszerzeniem.

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
Zwykle powinieneś dać ludziom szansę odpowiedzi na twoje wyzwanie, zanim sam je odpowiesz. Polecam tydzień, ponieważ niektóre mogą być tutaj tylko o określonych porach w ciągu tygodnia.
Adám

1
@ Adám Nie zaakceptowałem mojej odpowiedzi, a w tym czasie opublikowałem znacznie krótsze odpowiedzi (takie jak Twoja).
MarkWeston

1

Ruby, 192 117 bajtów (kredyt dla Dady)

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

Jak to działa?

Zamierzam użyć wersji rozszerzonej (konwersja do czasu jest podawana jako osobna funkcja i używa innego formatu wyjściowego):

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
Witamy na stronie! Każda odpowiedź na wyzwanie związane z golfem wymaga gry w golfa. Powinieneś przynajmniej usunąć bezużyteczne białe znaki i użyć 1-znakowych nazw zmiennych. To da ci około 120 bajtów, a użycie printfzamiast putsmoże zaoszczędzić jeszcze kilka bajtów: Wypróbuj online! . Miłej gry w golfa na PPCG!
Dada

1

APL NARS, 109 63 57 znaków

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

3 + 3 + 48 + 3 = 57 (widziałem także inne rozwiązania Apl)

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

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ą „::”

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

Kod maszynowy x86-64 (wywołanie systemowe Linux): 78 bajtów

Czas taktowania pętli RDTSC , Linuxsys_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 edxwysokie 32 bity wyniku.

Podsumowanie :

pchnij 00:00:00\nna stosie. Następnie w pętli:

  • sys_write wywołanie systemowe
  • Pętla ADC nad cyframi (zaczynająca się od ostatniej) w celu zwiększenia czasu o 1. Owijanie / przeprowadzanie obsługiwane za pomocą a cmp/ cmov, przy czym wynik CF zapewnia wprowadzanie następnej cyfry.
  • rdtsc i oszczędzaj czas rozpoczęcia.
  • spin na rdtscmomentu delta> = kleszczy na sekundę częstotliwości RDTSC.

Lista NASM:

 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.

Odkomentuj pauseinstrukcję oszczędzania znacznej mocy: podgrzewa jeden rdzeń o ~ 15 stopni C bez pause, ale tylko o ~ 9 z pause. (Na Skylake, gdzie pauseśpi przez ~ 100 cykli zamiast ~ 5. Myślę, że zaoszczędziłoby więcej, gdyby rdtscnie 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.

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

A także przy użyciu 1-bajtu dec edx. int 0x80Wywołanie systemowe ABI nie użyłby ESI / edi, więc konfiguracja rejestr dla syscall vs. lodsb / stosb może być prostsze.


Mógłbym użyć nanosleepwywoł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.
Peter Cordes

1

q / kdb + , 40 bajtów

Rozwiązanie:

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

Przykład:

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

Wyjaśnienie:

W tym miejscu wykonywane są trzy polecenia:

  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

Podział funkcji timera:

.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

Premia:

Alternatywa 1 dla 41 bajtów :

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

Alternatywa 2 dla 26 + 7 bajtów = 33 bajty

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

i dodawanie -t 1000jako argumentów do binarnego q.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.