간단한 스톱워치 구현


25

도전

당신의 임무는 프로그램을 시작하는 순간부터 경과 된 시간을 인쇄하는 프로그램을 1 초에 한 번 (프로그램이 시작될 때 즉시 포함) 작성하는 것입니다.

규칙

  • 시간은 hh:mm:ss형식 으로 인쇄해야 합니다. (한 자리 숫자의 경우 선행 0)
  • 타임 스탬프는 CR, LF 또는 CRLF로 구분해야합니다. (공백 없음)
  • 새로운 시간이 매초마다 나타나야합니다. (stdout은 1 초 동안 버퍼링 할 수 없습니다)
  • 프로그램이 23:59:59 이후에 실행 된 경우 프로그램의 동작은 정의되지 않습니다.
  • 사용자는 사용할 수 sleep(1)특정 둘째는 오버 헤드가 두 번째로, 등등에 축적 계산 루프를 인쇄 할 때마다 스킵 될 수있다하더라도.

출력 예 :

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

참고 00:00:03오버 처리로 인하여 여기 없습니다. 실제로 건너 뛴 값 (있는 경우)은 구현 및 / 또는 시스템에 따라 다릅니다.

C에서의 참조 구현 : (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);
    }
}

우승 기준

이것은 바이트 단위의 , 가장 짧은 코드입니다.


이후의 문제에 대해서는 주석의 설명을 명확히하는 것이 좋지 않습니다. 참조
user202729

답변:


9

MATL , 17 16 바이트

`Z`12L/13XOD1Y.T

MATL Online 에서 사용해보십시오 !

작동 원리

`         % 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
이 문을 닫은 후 37 분 동안 세계에서 어떻게 대답 했습니까? o_O 는 캐싱을 비난합니다
Xcoder Mr. Xcoder

9
@ Mr.Xcoder 최근 강제 사용을 배웠다
루이스 Mendo

29

인화점 스크립팅 언어,  174171  바이트

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"

실제로 :

다음 번에 이전 시간을 덮어 쓴 경우 158 바이트 :

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

기술적으로 캐리지 리턴은 사용되지 않으므로이 버전이 규칙을 준수하는지 확실하지 않습니다.


5
작동 인화점을 기대하지 않았습니다.
Polyducks

10
@Polyducks 아무도 작업 인화점을 기대하지 않습니다
Pureferret


유닉스에서는 CR이 줄을 덮어 쓰므로 두 번째 답변은 'CR, LF 또는 CRLF가 허용됨'으로 확인됩니다.
Stan Strum

1
@StanStrum 적어도 우분투 CR에서는 줄을 덮어 쓰지 않습니다. 사실, CRLF, LFCR그리고 LF모든 의미 동일합니다.

13

Bash + coreutils, 28 26 바이트

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

사이의 인쇄 할 수없는 문자 +%이다 ESC 바이트.

시스템 시간을 00:00:00으로 설정합니다. 하므로 루트 권한이 필요합니다. 또한 표준 시간대가 UTC이고 다른 프로세스가 시스템 시계를 방해하지 않는다고 가정합니다.

각각의 새로운 타이밍은 터미널을 재설정하여 이전의 것을 덮어 씁니다.


Bash + coreutils, 38 29 바이트

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

이전과 동일한 제한 사항이 적용됩니다. 각각의 새로운 타이밍은 새로운 라인에 표시됩니다.


바이트 수를 변경하지 않기 때문에 첫 date줄을 나머지 줄 바꿈으로 구분합니다. 그러나 누군가 당신의 두 번째 해결책과 같은 것을 생각해 낼 수 있다면 너무 좋을 것입니다.> :-(
Aaron

date -s0새 시간을 STDOUT에 인쇄합니다. 파이프를 사용하여 해당 출력을 침묵시킵니다.
Dennis

아, 설명해 주셔서 감사합니다!
Aaron

5

APL (Dyalog Unicode) , 51 바이트

전체 프로그램 본문.

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

온라인으로 사용해보십시오! Ctrl + Enter를 눌러 시작한 다음 다시 중지하십시오.

⎕AIccount의 I nformation (사용자 ID, 계산 시간, 접속 시간, 시간 키잉)

s← 할당 s(대한 타트 시간)
⎕AI-s 빼기 s에서⎕AI

3⊃ 세 번째 요소 (밀리 연결 시간) 선택
0 60 60 1E3⊤이 혼합 기수로 변환을
3↑ (밀리 초 삭제) 제 3을
100+ 백은 (패드 0으로) 각각에 부가
':'@1∘⍕¨ 각각의 문자열 표시의 첫 번째 문자에서 콜론 수정
ε nlist (평평하게)
1↓ 첫 번째 콜론을 삭제 (암시 적으로 stdout에 인쇄)

⎕DL 1D의리터 AY 일초

→2 두 번째 줄로 이동


5

R , 59 44 바이트

FR의 기본값은 FALSE로 설정되지만 일반 변수이므로 재정의 할 수 있습니다. 산술에 사용될 때는 FALSE로 강제 변환됩니다 0. F+1따라서 요청하면을 반환합니다 1. 우리는 지정 FF+1멋지게 형식으로, 인쇄, 1 초 동안 기다립니다. 무기한 계속됩니다.

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

hms패키지 가 없기 때문에 TIO에서 작동하지 않지만 다음은 내 컴퓨터의 샘플 출력입니다.

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 + 날짜, 50 49 47 46 45 41 바이트

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

랩 시간을 가지려면 ^ C를 빠르게 누르고 이것을 실행 한 다음 위의 내용을 다시 실행하십시오.

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

재설정하려면

s=0; unset laps

$ [s ++] 구문은 여전히 ​​작동하는 것으로 보이지만 더 이상 bash매뉴얼 페이지에 설명되어 있지 않습니다 (AFAICS) . 그리고 따옴표를 제거하면 for ((...)) 루프를 사용하는 것보다 여전히 바이트가 짧습니다.


AFAICT $[]는 더 이상 사용되지$(()) 않거나 문서화되지 않았지만 여전히 지원되는 형식입니다 . 코드 골프 응답에 일반적으로 사용되는지 확실하지 않지만 일반적인 규칙은 코드가 언어에 대한 하나 이상의 버전의 인터프리터에서만 작동해야한다는 것입니다. IMO 괜찮습니다.
Peter Cordes

s=0산술 대체는 설정되지 않은 변수를 0 으로 취급하므로 필요하지 않습니다 . -u기본 시간대 (UTC) 만 가정하면 필요하지 않습니다.
Dennis

-u는 컴퓨터 에 필요 합니다 :)
Will Crawford

4

스위프트 , 144 바이트

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

설명

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 바이트

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


2
시간은 0에서 시작하지 않습니다. 오프셋은 시스템 시계 시간대에 따라 변경됩니다. (Win10)
LukeS

@LukeS Whoops, 고정!
darrylyeo

4

Matlab (R2016b), 50 바이트

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

설명:

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

대체 버전 (50 바이트도 : P) :

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

사이트에 오신 것을 환영합니다! :)
DJMcMayhem

고마워 친구:)
Thiago Oleinik

@LuisMendo 제안 해 주셔서 감사하지만 이해하지 못했습니다 ... 귀하의 예에서 변수는 무엇 t입니까? 또한, 입력 datestr은 일 단위이므로,로 나누면 86400바이트 수가 2 씩 증가합니다.
Thiago Oleinik

3

줄리아 0.6 , 75 68 바이트

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

온라인으로 사용해보십시오!

sleep (1)이 허용되면 단순 중첩 된 for- 루프는 Julias 내장 시간 처리 방법을 사용하는 것보다 짧습니다.

DateTime을 사용하여 절전 (1)이없는 오래된 솔루션

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

t'0 일'에서 프로그램이 시작될 때까지 경과 된 시간입니다. now()-t를 사용하여 형식이 지정된 시간Dates.format() 입니다.

t0=now(); ...; now()-t0와 함께 사용할 수없는 시차를 산출합니다 Dates.format().

타이밍 자체는 내장 기능으로 간단합니다 Timer.



3

자바 스크립트 (ES6), 88 바이트

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

본질적으로 동일한 접근 방식 @ darrylyeo 's answer 이지만 모든 시간대에서 작동하며 약간 다른 방식으로 0에 도달합니다.

[편집] 대릴의 답변이 수정되었습니다. 그래도 여전히 짧습니다.


3

> <> , 82 + 7 = 89 바이트

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

온라인으로 사용해보십시오!

플래그 사용을위한 +7 바이트 -t.0125 를 사용하여 각 명령에 1/80 초가 걸리도록 . 각 루프에는 80 개의 명령어가 있으며 각 루프를 1 초 길이로 만듭니다. 계산 시간 때문에 실제로는 실제로 더 길다.

@Not A Tree 's를 볼 때까지 실제로 이것을 최대 100까지 버퍼링해야했습니다. 시간과 분을 생성하여 80보다 작게 트리밍하는 대답 을 해야했습니다.\/ 두 번 실행되는을 루프 당.

작동 원리

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

보너스:

동일한 크기의 한 줄 버전, 80 + 9 바이트 :

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

-a플래그를 사용하여 건너 뛴 명령어에 대한 틱을 추가합니다.


3

PHP 4 이상 70 64 바이트

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

PHP 5.3 이상 69 63 바이트

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

PHP 오픈 태그는 6 바이트를 절약하는 답변에서 생략 할 수 있습니다.
Daniel W.

2

파이썬 3 , 112 바이트

1 초 지연을 사용한다고 가정해도 (아주 드물지만) 1 초를 건너 뛸 수 있습니다.

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

즉시 창에서 실행 : 약 2,300 만 년 어딘가에 예상되는 오류 지점 (부동 소수점 해결에 ~ 8.5e9 일 실패)



2

AWK , 110 87 86 바이트

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

TIO에서는 작동하지 않습니다.


프로그램이 00:00:00시작된 순간 에 인쇄되지 않는 것 같습니다 .
user202729

고쳤다. 감사합니다
Noskcaj


2

배쉬 + coreutils + GNU 날짜, 50 바이트

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

@Dennis에서 영감을 얻은이 솔루션은 시간을 변경하지 않아도됩니다. 초기 오프셋을 지금부터 UNIX 시대 (1970 년 1 월 1 일 00:00:00 UTC)까지 'o'에 저장 한 다음 UTC 날짜에 [-ud 옵션] (현재 시간-오프셋)을 표시하지만 [+ % X 옵션] HH : MM : SS 만 이것은 현재 시간대가 UTC가 아닌 국가에서 작동합니다.


2

면도 , 173 (172) 168 바이트

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]

이것은 Windows Clean 번들에서만 작동합니다.

Clean이 CLK_PER_TICK :== 1000000* nix에있는 것처럼 Linux에서 작동하려면 3 바이트를 추가하십시오 . 크로스 플랫폼이되도록하려면 CLK_PER_TICK설정된 값 대신 사용해야 하는 8 바이트를 추가하십시오 . ( 위로 인해 TIO 링크가 더 큽니다. )

온라인으로 사용해보십시오!


2

파이썬 2 , 69 + 3 ( TZ=) = 72 바이트

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

이것은 잠자 지 않고 연속 루프로 실행되어 매 초마다 새로운 줄을 인쇄하는 대신 동일한 줄의 시간을 업데이트합니다. (여전히 규칙에 따라 허용 되었으면합니다.)

이 약간 긴 버전 (72 + 3 = 75 바이트)은 매 초마다 새 줄에 인쇄됩니다.

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

이 두 가지 모두 UTC 시간대에 있어야합니다. Linux에서는 TZ환경 변수 를 설정하여이를 달성 할 수 있습니다 . 예 TZ= python.


2

> <> , 106 바이트 82 + 9 = 91 바이트

-a깃발 을 제안 해 준 Jo King에게 감사합니다 ! 그들의 답변 도 확인하십시오 .

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

온라인으로 사용해보십시오!(그러나 60 초의 시간 초과를 기다려야합니다).

이전에는 필요하지 않은> <> 기능을 사용해야합니다.이 코드에는 플래그가 필요합니다 -t.0125 는 실행 속도를 틱당 0.0125 초 또는 초당 80 틱으로 설정합니다. 또한있다-a공백이 틱으로 계산되는 플래그 (일부 경우-인터프리터가 이것에 대해 약간 이상합니다).

기본적으로 코드는 물고기가 루프를 통과 할 때마다 증가하는 카운터를 유지하고 나머지 루프는 카운터를 hh:mm:ss 형식으로 인쇄합니다. 루프는 정확히 80 틱이 걸립니다.

이론적으로는 작동하지만 실제로 계산 시간으로 인해 각 틱은 0.0125 초보다 약간 더 깁니다. 변경 \\두 번째 줄에에<<TIO에서보다 정확한 타이밍 제공하기 .

이 통역사가 공백을 공식 통역사와 약간 다르게 처리한다는 점을 제외하고 물고기 놀이터 에서 코드가 실제로 작동하는 것을 볼 수도 있습니다 . 또는 TIO에서 플래그를 제거하여 코드를 최고 속도로 실행하여 1 분 후 시간 동안 동작을 확인할 수 있습니다.


첫 번째 줄의 v를 바꾸고 \!여분의 두 개를 제거 하여 -1 바이트 <. -a공백을 세고 명령어를 틱으로 건너 뛴 플래그 를 사용하는 경우 또 다른 몇 바이트
Jo King

@ JoKing, -a깃발 좀 더 골프시켜 줘서 고마워! \!코드 에서 트릭을 사용할 수 있다고 생각합니다 . 온라인으로 사용해보십시오!
나무가 아님

2

Java 8, 전체 프로그램, 150 바이트

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

여기에서 시도하십시오 (60 초 후에 시간이 초과되므로 더 많은 출력을 보려면 절전 모드를 1로 설정하십시오).

설명:

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

자바 8, 기능, 94 바이트

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

여기에서 시도하십시오 (60 초 후에 시간이 초과되므로 더 많은 출력을 보려면 절전 모드를 1로 설정하십시오).

설명:

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

다음은 1000ms를 사용할 때 의도 한대로 작동하는 작은 gif입니다.

enter image description here


2

PHP, 59 48 바이트

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

대런 H의 답변에서 영감을 얻었습니다 .

이전 버전 :

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

PHP 오픈 태그는 6 바이트를 절약하는 답변에서 생략 할 수 있습니다.
Daniel W.

좋은 생각이지만 3600은 86400이어야합니다. 그렇지 않으면 카운터는 23:00:00에 시작하므로 불행히도 바이트를 얻지 만 여전히 9로 나에게 이겼습니다!
Darren H

@DarrenH 나는 그것이 당신의 지역에 달려 있다고 생각합니다. 나는 GMT + 1에 있는데 3600을 추가 한 이유입니다. 그러나 영어 사람들 -3600에게는 5 바이트를 절약 할 수있는 모든 것을 제거 할 수 있다고 생각 합니다.
roberto06

1

, 177 바이트

이것은 date +%s일반적인 date확장 인을 사용하기 때문에 POSIX 호환 제품이 아닙니다 .

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
일반적으로, 당신은 사람들이 당신의 도전에 스스로 대답하기 전에 대답 할 기회를 주어야합니다. 일주일 동안 특정 시간에만 여기에있을 수 있으므로 일주일을 권장합니다.
Adám

1
@ Adám 나는 대답을 받아들이지 않았고, 나는 당신과 같은 훨씬 짧은 답변을 제출했을 때 제출되었다.
MarkWeston

1

루비, 192117 바이트 (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

어떻게 작동합니까?

확장 버전 사용 (시간으로의 변환은 별도의 함수로 제공되며 다른 출력 형식을 사용함) :

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
사이트에 오신 것을 환영합니다! 코드 골프 챌린지에 대한 모든 답변을 골라야합니다. 최소한 쓸모없는 공백을 제거하고 1 자 변수 이름을 사용해야합니다. 그러면 약 120 바이트를 얻을 수 있으며 printf대신 대신 사용 puts하면 몇 바이트를 더 절약 할 수 있습니다. 온라인으로 사용해보십시오! . PPCG의 행복한 골프!
Dada

1

APL NARS, 109 63 57 자

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

3 + 3 + 48 + 3 = 57 (다른 Apl 솔루션도 보았습니다)

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

해당 문자열의 길이가 1 인 경우 앞에 숫자 '0'을 추가하는 방법으로 숫자 문자열에서 INT ⍵를 변환하십시오.

{∊⍵,¨':: '}

⍵의 배열을 '::'배열과 결합

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 머신 코드 (Linux 시스템 호출) : 78 바이트

RDTSC 스핀 루프 타이밍, Linux sys_write시스템 호출.

x86-64는 런타임에 RDTSC "기준 클록"주파수를 쿼리하는 편리한 방법을 제공하지 않습니다. MSR을 읽을 수는 있지만 (그것을 기반으로 계산을 수행 할 수는 있지만 ) 커널 모드 또는 root + opening이 필요 /dev/cpu/%d/msr하므로 빈도를 빌드 타임 상수로 설정하기로 결정했습니다. ( FREQ_RDTSC필요에 따라 조정 하십시오. 32 비트 상수는 기계 코드의 크기를 변경하지 않습니다)

몇 년 동안 x86 CPU는 RDTSC 주파수를 고정 시켰으므로 시간 소스로 사용할 수는 없습니다. 당신이 비활성화 주파수 변화에 조치를 취할하지 않는 한, 코어 클럭 사이클 성능 카운터. (실제 CPU 사이클을 계산하기위한 실제 성능 카운터가 있습니다.) 일반적으로 터보 또는 절전에 관계없이 공칭 스티커 주파수 (예 : i7-6700k의 경우 4.0GHz)에서 틱합니다. 어쨌든,이 통화 중 대기 타이밍은 (캘리브레이션 된 지연 루프처럼)로드 평균에 의존하지 않으며 CPU 절전에도 민감하지 않습니다.

이 코드는 기준 주파수가 2 ^ 32Hz 미만, 즉 ~ 4.29GHz 인 모든 x86에서 작동합니다. 그 외에도 타임 스탬프의 하위 32 개가 1 초 안에 줄 바꿈되므로edx . 따라서 결과 상위 32 비트도 .

개요 :

00:00:00\n스택을 밀어 넣 습니다. 그런 다음 루프에서 :

  • sys_write 시스템 호출
  • (마지막으로 시작) 숫자를 통해 ADC-루프는 취급 1. 포장 / 반출하여 시간을 증가하기 cmp/cmov , 제공하는 CF 결과로 반입 다음 자리합니다.
  • rdtsc 시작 시간을 저장하십시오.
  • 회전시키다 rdtsc델타가 RDTSC 주파수의 초당 틱이 틱이 될 때까지 .

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.

pause상당한 전력을 절약하기 위한 지시 사항을 주석 해제하십시오 . 이렇게하면 코어 하나가 ~ 15 ° C까지 가열 pause되고 ~ 9로만 가열 됩니다 pause. (Skylake에서는 pause~ 5 대신 ~ 100 사이클 동안 잠을 자고 있습니다.rdtsc CPU 속도가 느려서 시간이 많이 걸리지 않으면 더 많이 .)


32 비트 버전은 몇 바이트 더 짧습니다. 예를 들어 32 비트 버전을 사용하여 초기 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

또한 1 바이트를 사용 dec edx합니다. int 0x80시스템 콜 대 lodsb / stosb의 레지스터 설정이 간단 할 수 있도록 시스템 호출 ABI는 EDI / ESI 사용하지 않을 것입니다.


nanosleep시스템 호출 을 사용할 수 있었지만 더 흥미로 웠습니다. Linux에서 root를 사용하면 올바른 MSR을 읽고 프로그래밍 방식으로 RDTSC 주파수를 얻을 수 있습니다.
Peter Cordes

1

q / kdb + , 40 바이트

해결책:

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

예:

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

설명:

여기에는 세 가지 명령이 실행됩니다.

  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

타이머 기능의 고장 :

.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

보너스:

41 바이트에 대한 대체 1 :

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

26 + 7 바이트 = 33 바이트에 대한 대체 2

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

-t 1000q 바이너리에 인수로 추가 합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.