Basit Bir Kronometre Uygula


25

Meydan okuma

Göreviniz, saniyede bir kez (programınız başlatıldığında hemen dahil olmak üzere) geçen zamanı programınızın başladığı zamandan itibaren basan bir program yazmaktır.

kurallar

  • Zaman hh:mm:ssformatta basılmalıdır . (tek basamaklı değerler için baştaki sıfırlar)
  • Zaman damgaları CR, LF veya CRLF ile ayrılmalıdır. (önde gelen boşluk yok)
  • Her saniye yeni bir zaman ortaya çıkmalı. (stdout bir saniye tamponlanamaz)
  • Programın 23:59:59 tarihinden sonra çalıştırılması durumunda davranış tanımlanamaz.
  • sleep(1)Yazdırma, hesaplama, döngü vb. Ek yük bir saniyeye biriktiğinde, belirli bir saniye atlanabilir olsa bile kullanabilirsiniz .

Örnek çıktı:

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

00:00:03Genel gider işlemleri nedeniyle burada eksik olduğuna dikkat edin . Gerçek atlanan değerler (eğer varsa) elbette uygulamaya ve / veya sisteme bağlıdır.

C’de referans uygulaması: (sadece POSIX uyumlu sistemler)

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

Kazanan kriterler

Bu , bayt cinsinden en kısa kod kazanır!


Daha sonraki zorluklar için not alın, açıklamalardaki açıklama yapılması kötü bir şeydir. başvuru
user202729

Yanıtlar:


9

MATL , 17 16 bayt

`Z`12L/13XOD1Y.T

MATL Online'da deneyin !

Nasıl çalışır

`         % 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
Kapattıktan 37 dakika sonra bu dünyada nasıl cevap verdiniz? o_O önbelleklemeyi suçluyor
Bay Xcoder,

9
@ Mr.Xcoder Geçenlerde Gücü kullanmayı öğrendim
Luis Mendo

29

İşlem Flashpoint kodlama dili,  174  171 bayt

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"

Eylemde:

158 bayt, önceki zaman bir sonraki zamanın üzerine yazılırsa:

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

Teknik olarak, hiçbir satır başı kullanılmaz, bu nedenle bu sürümün kurallara uyup uymadığından emin değilim.


5
Operasyon parlama noktası beklemiyordum.
Polyducks,

10
@ Polyducks kimse operasyon parlama noktası
beklemiyor


Unix'te bir CR satırın üzerine yazacağından, ikinci cevabın 'ya CR, LF ya da CRLF'ye izin verildiğini' 'doğruladığını düşünüyorum
Stan Strum

1
@StanStrum En azından Ubuntu'mda CRsatırın üzerine yazılmayacak. Aslında CRLF, LFCRve LFtüm anlama sahip.

13

Bash + coreutils, 28 26 bayt

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

Arasındaki basılamaz karakter +ve %bir olan ESC bayt.

Bu, sistemin saatini 00:00:00 olarak ayarlar ve bu nedenle kök ayrıcalıkları gerektirir. Ayrıca, saat diliminin UTC olduğunu ve başka hiçbir işlemin sistem saatini etkilemeyeceğini varsayar.

Her yeni zamanlama terminali sıfırlar, böylece öncekinin üzerine yazar.


Bash + coreutils, 38 29 bayt

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

Daha önce olduğu gibi aynı kısıtlamalar geçerlidir. Her yeni zamanlama yeni bir satırda gösterilir.


Bytecount değerini değiştirmediği için, ilkini datediğerlerinden güzel bir küçük çekişmeyle ayıracağım . Fakat ikinci çözümünüz gibi bir şeyle karşılaşabilecek biri için çok iyi olabilir> :-(
Aaron

date -s0yeni saati STDOUT'a yazdırır; Bu çıkışı susturmak için boruyu kullanıyorum.
Dennis,

Ah doğru, açıklama için teşekkürler!
Aaron,

5

APL (Dyalog Unicode) , 51 bayt

Tam program gövdesi.

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

Çevrimiçi deneyin! (Başlatmak için Ctrl + Enter, durdurmak için tekrar basın.)

⎕AIBir ccount I bilgisi (kullanıcı kimliği, hesaplama zamanı, bağlantı zamanı, anahtarlama zamanı)

s← atamak siçin ( s ekşi süresi)
⎕AI-s çıkarma sdan⎕AI

3⊃ Üçüncü eleman (milisaniye olarak bağlantı süreli)
0 60 60 1E3⊤bu karma radix için dönüştürme
3↑ (milisaniye damlaları) ilk 3 almak
100+ yüz (ped sıfırlara) her bir göze ilave
':'@1∘⍕¨ her dize gösterimi ilk karakteri bir nokta ile tadil
£ değerinin nlist (düzleştir)
1↓ ilk sütunu bırakır ( ve dolaylı olarak stdout'a yazdırır)

⎕DL 1D E l ay bir saniye

→2 iki numaralı satıra git


5

R , 59 44 bayt

FR varsayılan olarak FALSE, ancak normal bir değişken ve yeniden tanımlanabilir. Aritmetik kullanıldığında FALSEzorlanır 0. F+1Bu nedenle sormak geri döner 1. Biz atamak Folmak F+1, güzel biçimi onu, baskı ve bir saniye bekleyin. Süresiz devam eder.

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

TIO üzerinde çalışmıyor ( hmspaketin yetersizliğinden dolayı ), ancak işte makinemden bir örnek çıktı:

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 + uyku + tarih, ayrıca 50 49 47 46 45 41 bayt

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

Bir tur atmak için, hızlıca ^ C tuşuna basın, şunu çalıştırın ve yukarıdakileri tekrar çalıştırın:

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

Sıfırlamak:

s=0; unset laps

$ [S ++] sözdizimi hala çalışıyor gibi görünüyor, ancak bashman sayfasında artık belgelenmemiş (AFAICS) . Ve hala etrafındaki tırnak işaretlerini kaldırdığımda, for ((...)) döngüsünü kullanmaktan daha kısa bir bayt.


AFAICT, $[]kullanımdan kaldırılmış / belgelenmemiş ancak yine de desteklenen bir şeklidir$(()) . Kod-golf cevaplarında yaygın olarak kullanılıp kullanılmadığından emin değilim, ancak genel kural, kodunuzun dilinizin tercümanının en az bir sürümü üzerinde çalışması gerektiğidir. IMO iyi.
Peter Cordes

s=0aritmetik ikame, belirsiz bir değişkeni 0 olarak kabul edeceği için gerekli değildir . -uyalnızca varsayılan zaman dilimini (UTC) kabul ederseniz de gerekli değildir.
Dennis,

-u benim makinede gerekli :)
Will Crawford

4

Swift , 144 bayt

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

açıklama

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 bayt

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


2
Saatler benim için 0'dan başlamıyor. Ofset, sistemin saat dilimine bağlı olarak değişir. (Win10)
Luke

@LukeS Whoops, düzeltildi!
darrylyeo

4

Matlab (R2016b), 50 bayt

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

Açıklama:

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

Alternatif sürüm (50 bayt da: P):

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

Siteye Hoşgeldiniz! :)
DJMcMayhem

Teşekkürler dostum:)
Thiago Oleinik

@LuisMendo Öneri için teşekkürler, ama anlamadım ... Örneğinizde, değişken tnedir? Ayrıca, girdi datestrgün cinsinden, böylelikle bölmek zorunda kalacağım 86400ki bu da bayt sayısını iki kat artıracak ...
Thiago Oleinik

3

Julia 0.6 , 75 68 bayt

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

Çevrimiçi deneyin!

Uyku (1) izin verildiğinde, basit iç içe geçmiş döngüler, Julias yerleşik zaman işleme yöntemlerinden daha kısadır.

DateTime kullanarak uyku olmadan eski çözüm (1)

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

t'0 gününden' programın başlatıldığı zamana kadar geçen süre. now()-tbir an , sonra kullanılarak biçimlendirilir Dates.format().

t0=now(); ...; now()-t0birlikte kullanılamayan bir zaman farkı verirdi Dates.format().

Zamanlamanın kendisi, yerleşik olarak önemsizdir Timer.



3

JavaScript (ES6), 88 bayt

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

Temelde @ darrylyeo'nun cevabıyla aynı yaklaşım , ancak tüm zaman dilimleri için çalışır ve 0'a ulaşmak için biraz farklı bir yol kullanır.

[Düzenle] Darryl'in cevabı düzeltildi. Yine de bu daha kısa.


3

> <> , 82 + 7 = 89 bayt

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

Çevrimiçi deneyin!

-t.0125Her komutun saniyenin 1 / 80'ini almasını sağlamak için bayrağı kullanmak için +7 bayt . Her bir döngü 80 saniyedir, her döngü bir saniye uzunluğundadır. Hesaplama zamanı nedeniyle, bu aslında pratikte daha uzun.

Ben @Not Bir Tree'nin görene kadar aslında 100 bu tüm yol kadar tampon zorunda cevabı mayın saat ve dakika oluşturmak için 7'den bayt daha iyi bir yol vardı Onlar da kullanımını ilham 80 altına kırparak, \/iki kez idam edildiği döngü başına.

Nasıl çalışır

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:

Aynı büyüklükteki bir çizgi sürümü, 80 + 9 bayt:

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

Bu, -aatlanan talimatlara keneler eklemek için bayrağı kullanır .


3

PHP 4+, 70 64 bayt

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

PHP 5.3+, 69 63 bayt

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

PHP açık etiketleri 6 bayt tasarruf cevabında atlanabilir.
Daniel W.

2

Python 3 , 112 bayt

1 saniyelik gecikmeler kullanmanın normal olduğunu varsayalım, (nadiren) bir saniyeyi atlasa bile.

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

hemen pencerede koş: beklenen hata noktası yaklaşık 23 milyon yıl (bir kayan nokta çözünürlüğü ~ 8,59 gün başarısız oluyor)



2

AWK , 110 87 86 bayt

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

TIO'da çalışmıyor.


Programınız 00:00:00başladığı anda yazdırılmıyor gibi görünüyor .
user202729

Onu düzeltti. Thanks
Noskcaj


2

Bash + coreutils + GNU tarihi, 50 bayt

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

@Dennis'den ilham alan bu çözüm, zamanın değiştirilmesini gerektirmiyor. İlk ofseti şu andan itibaren UNIX dönemine (1 Ocak 1970 00:00:00 UTC) 'o' içinde saklar ve ardından [-ud seçenekleri] (şu anki saat - ofset) UTC tarihinde görüntüler, ancak sadece [+% X seçeneği] HH: MM: SS. Bu, geçerli zaman diliminin UTC olmadığı ülkelerde çalışmalıdır.


2

Temiz , 173 172 168 bayt

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]

Bu, yalnızca Windows Temiz paketlerinde çalışır.

Linux altında çalışmasını istiyorsanız, CLK_PER_TICK :== 1000000Temiz'in * nix'teki gibi 3 bayt ekleyin . Platformlar arası olmasını istiyorsanız, CLK_PER_TICKayarlandığı değer yerine kullanmanız gerektiğine bunun yerine 8 bayt ekleyin . ( Yukarıdaki TIO bağlantısı daha büyüktür )

Çevrimiçi deneyin!


2

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

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

Bu, sürekli bir döngü halinde, uyku olmadan, her saniye yeni bir satır yazdırmak yerine, aynı satırdaki zamanı günceller. (Hala kurallara izin veriliyor, umarım.)

Bu biraz daha uzun versiyon (72 + 3 = 75 bytes) her saniye yeni bir satıra basılıyor:

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

Bunların her ikisi de UTC saat diliminde olmanızı gerektirir. Linux'ta bunu TZortam değişkenini ayarlayarak yapabilirsiniz . Örn TZ= python.


2

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

-aBayrak önerdiğiniz için Jo King'e teşekkür ederiz ! Check out yanıtlarını da.

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

Çevrimiçi deneyin!(ancak 60 saniyelik zaman aşımını beklemeniz gerekecek).

Daha önce hiç ihtiyacım olmadı>>> özelliğini kullanmalıyım: bu kod -t.0125, yürütme hızını kene başına 0,0125 saniyeye veya saniyede 80 kene ayarlayan bayrağı gerektirir . Aynı zamanda -aboşlukları kene olarak sayan bayrak da var (bazı durumlarda - tercüman bu konuda biraz tuhaf).

Temel olarak, kod, balığın her döngüden geçtiğinde artan bir sayacı tutar ve döngünün kalan kısmı sayacı hh:mm:ssbiçimlendirmek ve yazdırmak için dönüştürür . Döngü tam 80 tik alır.

Bu teoride çalışmalıdır, ancak pratikte, her bir kene hesaplama süresi nedeniyle 0.0125 saniyeden biraz daha uzundur. Değişen \\ikinci satırda için<< TIO daha doğru zamanlamaları verir.

Ayrıca , bu oyun alanı beyaz alanı resmi tercümandan biraz farklı şekilde ele alması dışında , kodu oyun alanında da izleyebilirsiniz . Alternatif olarak, bir dakika sonra davranışı doğrulamak için kodu en yüksek hızda çalıştırmak için TIO'daki bayrakları kaldırabilirsiniz.


-1 bayt ilk satırında v ile değiştirerek \!ve iki ekstra kaldırarak <. -aBayrağı başka bir çift bayrağını kullanırsanız, boşlukları sayan ve talimatları atladı olarak işaretlersiniz
Jo King

@JoKing, -aBayrak biraz daha golf yapmama izin verdi, teşekkür ederim! \!Numarayı kodunuzda da kullanabileceğinizi düşünüyorum : Çevrimiçi deneyin!
Ağaç değil

2

Java 8, tam program, 150 bayt

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

Burada deneyin (60 saniye sonra zaman aşımına uğrar, bu yüzden daha fazla çıktı almak için uykuyu 1'e ayarlarım).

Açıklama:

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, işlev, 94 bayt

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

Burada deneyin (60 saniye sonra zaman aşımına uğrar, bu yüzden daha fazla çıktı almak için uykuyu 1'e ayarlarım).

Açıklama:

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

1000 ms kullanıldığında beklendiği gibi çalıştığını görmek için küçük bir gif:

görüntü tanımını buraya girin


2

PHP, 59 48 bayt

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

Darren H'nin cevabından ilham aldı .

Eski versiyon :

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

PHP açık etiketleri 6 bayt tasarruf cevabında atlanabilir.
Daniel W.

Harika düşünce, ama 3600 86400 olmalı, aksi halde sayaç 23:00: 00'da başlıyor, bu yüzden ne yazık ki bir bayt kazanıyorsunuz, yine de beni 9'da yendi!
Darren H,

@DarrenH Bence bu sizin yerelinize bağlı, bunun hakkında hiç düşünmemiştim. Ben GMT + 1'deyim, bu yüzden 3600 ekledim, ama İngilizler için -3600tamamen kaldırılabilir, 5 bayt kurtarabilir.
roberto06

1

Kabuk , 177 bayt

Bunun tamamen POSIX uyumlu olmadığına dikkat edin, çünkü date +%syaygın bir dategenişleme olan kullanır .

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
Normalde, kendinize cevap vermeden önce insanlara mücadelenizi cevaplama şansı vermelisiniz. Bazıları yalnızca hafta boyunca belirli zamanlarda burada olabileceğinden bir hafta öneriyorum.
Adám

1
@ Adám cevabımı kabul etmedim ve o sırada çok kısa cevaplar verdim (sizinki gibi) gönderildi.
MarkWeston

1

Ruby, 192 117 bayt (Dada'ya Kredi)

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

O nasıl çalışır?

Genişletilmiş sürümü kullanmaya gitmek (Bir zamana dönüşüm ayrı bir işlev olarak verilmiştir ve farklı bir çıktı formatı kullanır):

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
Siteye Hoşgeldiniz! Kod-golf mücadelesine verilen her cevap golfe atılmalıdır. En azından işe yaramaz boşlukları kaldırmalı ve 1 karakter değişken isimleri kullanmalısınız. Bu size yaklaşık 120 byte kazandıracak ve printfyerine kullanmak putsbirkaç byte'tan daha fazla tasarruf sağlayabilecektir: Çevrimiçi deneyin! . PPCG'de mutlu golf!
Dada

1

APL NARS, 109 63 57 karakter

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

3 + 3 + 48 + 3 = 57 (diğerleri Apl çözümleri de gördü)

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

INT'yi rakam dizesindeki bir dizgenin uzunluğu 1'in önüne bir '0' eklemek yerine 1 ise, dönüştürün.

{∊⍵,¨':: '}

array 'deki diziyi' :: 'dizisiyle birleştirin

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 makine kodu (Linux sistem çağrısı): 78 bayt

RDTSC spin-loop zamanlaması, Linuxsys_write sistem çağrısı.

x86-64, çalışma zamanında RDTSC "referans saati" frekansını sorgulamak için uygun bir yol sağlamaz. Şunları yapabilirsiniz Bir MSR'yi okumak (ve buna dayanarak bir hesaplama yapmak) , ama bu çekirdek modu veya kök + açılmasını gerektirir /dev/cpu/%d/msrFrekansı bir yapı zamanı sabiti yapmaya karar. (ayarlayınFREQ_RDTSC Gerektiği gibi : 32 bit sabitler makine kodunun boyutunu değiştirmez)

Birkaç yıl boyunca x86 CPU'ların sabit RDTSC frekansına sahip olduğunu, bu nedenle bir zaman kaynağı olarak kullanılabileceğini unutmayın. frekans değişikliklerini devre dışı bırakmak için adımlar atmadığınız sürece bir çekirdek saat döngüsü performans sayacı . (Gerçek CPU çevrimlerini saymak için gerçek perf sayaçları vardır.) Genellikle nominal çıkartma sıklığını işaretler, örneğin turbo veya güç tasarrufundan bağımsız olarak i7-6700k için 4.0 GHz. Yine de, bu meşgul bekleme zamanlaması yük ortalamasına bağlı değildir (kalibre edilmiş bir gecikme döngüsü gibi) ve ayrıca CPU güç tasarrufuna duyarlı değildir.

Bu kod referans frekansı 2 ^ 32 Hz'nin altında olan, yani ~ 4.29 GHz'e kadar olan herhangi bir x86 için çalışacaktır. Bunun ötesinde, zaman damgasının düşük 32'si 1 saniyede tümüyle kayıyordu, bu yüzden edxsonucun yüksek 32 bitine de bakmak zorunda kaldım .

özet :

00:00:00\nYığını itin . Sonra bir döngüde:

  • sys_write sistem çağrısı
  • Süreyi 1 arttırmak için rakamlar üzerinden ADC döngü (sondan başlayarak), 1 / 'yi artırmak için a cmp/ ile sarılmış / sarma işlemi cmov, CF sonucu bir sonraki haneye geçişi sağlar.
  • rdtsc ve başlangıç ​​zamanından tasarruf edin.
  • spin rdtscö kadar> = RDTSC frekansının saniyede keneler.

NASM listesi:

 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.

pauseÖnemli güçten tasarruf etme talimatının engellenmesi : Bu, bir çekirdeği ~ 15 derece C olmadan pause, ancak sadece ~ 9 ile ısıtır pause. (Skylake'de, pause~ 5 yerine ~ 100 döngü için uyur. Ben rdtscde yavaş olmazsa daha fazla tasarruf edeceğini düşünüyorum, bu nedenle CPU çok fazla zaman harcamaz).


32 bitlik bir sürüm birkaç bayt daha kısa olacaktır, örneğin bunun başlangıçtaki 00: 00: 00 \ n dizesini itmek için bunun 32 bitlik bir versiyonunu kullanmak.

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

Ve ayrıca 1 bayt kullanarak dec edx. int 0x80Syscall vs lodsb / stosb için kayıt kurulum basit olabilir böylece sistem çağrı ABI, edi / esi kullanmak ister.


Ben kullanmış olabilir nanosleepsistem çağrısı, ancak bu daha ilginç oldu. Linux'taki root ile doğru MSR'yi okumak ve programatik olarak RDTSC frekansını elde etmek mümkündür.
Peter Cordes

1

q / kdb + , 40 bayt

Çözüm:

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

Örnek:

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

Açıklama:

Burada yürütülen üç komut var:

  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

Zamanlayıcı işlevinin dağılımı:

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

41 bayt için alternatif 1 :

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

26 + 7 bayt için alternatif 2 = 33 bayt

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

ve -t 1000q ikiliye argümanlar olarak ekleme .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.