Введите алфавит - так быстро, как вы можете!


44

Ваша задача - составить программу, которая измеряет, как быстро вы сможете набирать буквы английского алфавита.

  • Программа должна принимать только строчные буквы aв zв алфавитном порядке.
  • Каждая буква отображается как набранная в той же строке (без новой строки или каких-либо других разделителей между буквами).
  • Если вы введете недопустимый символ, программа выведет Fail новую строку и завершит работу.
  • Если вы введете все 26 букв, программа в новой строке выведет время в миллисекундах, которое прошло с первой до последней буквы, и завершится.
  • Таймер запускается при вводе первой буквы a.

Пример выходов:

b
Fail

abcdefgg
Fail

abcdefghijklmnopqrstuvwxyz
6440

Это , поэтому выигрывает самый короткий ответ в байтах.


4
Соответствующий проект я сделал некоторое время назад. (15-й уровень в основном такой)
ETHproductions

4
Можем ли мы вывести Failбез заголовка новой строки? (например, abdFail\nили abd Fail\n))
Скоттинет

1
@scottinet, нет, результат ( Failили миллисекунды) должен быть в новой строке, как в примере. Большинство ответов уже предполагают это.
Данко Дурбич

2
-1, поскольку это «новое» правило не было в исходной спецификации и лишает законной силы мои предложения по одному из ответов Python, который был в исходных правилах.
ElPedro

Я ожидал, что это будет самая быстрая задача печати алфавита.
ATaco

Ответы:


40

HTML (JavaScript (ES6)), 129 126 117 байт

<input id=i onfocus=l=0,n=Date.now onkeypress=event.which-97-l?i.outerHTML='Fail':24<l?i.outerHTML=n()-t:t=l++?t:n()>

Нажмите на вход и начните печатать! Кроме того, мой набор текста отстой; Я занимаю около 5 секунд, даже с практикой. Редактировать: Сохранено 2 байта благодаря @HermanLauenstein путем переключения языка. Сохранено 3 байта благодаря @ qw3n. Сохранено 9 байт благодаря @tsh.


1
-2 байта с использованием html с тегом script: <input id=i><script>l=0;n=Date.now;i.onkeypress=e=>e.charCode-97-l?i.outerHTML='Fail':l>24?i.outerHTML=n()-t:t=l++?t:n()</script>-11 байтов, если закрывающий тег не нужен
Herman L

@HermanLauenstein Закрывающий тег, кажется, необходим для фрагмента, по крайней мере, так что я оставлю его.
Нил

2
Это слишком бешено и весело одновременно.
Зенон

1
Как насчет поставить событие на входе? <input id=i onkeypress=event.which-97-l?i.outerHTML='Fail':24<l?i.outerHTML=n()-t:t=l++?t:n() onfocus=l=0,n=Date.now>
17

1
Не повторяет текст на новой строке
дкудрявцев

33

6502 машинный код (C64 PAL), 189 165 байтов

00 C0 A9 17 8D 18 D0 A9 40 85 FE E6 FE 20 E4 FF F0 FB 20 D2 FF C5 FE 38 D0 38
C9 5A 18 F0 33 C9 41 D0 E8 A9 00 85 FC 85 FD A9 18 85 FB A9 7F 8D 0D DD A9 7F
8D 18 03 A9 C0 8D 19 03 A9 D8 8D 04 DD A9 03 8D 05 DD A9 01 8D 0E DD A9 81 8D
0D DD D0 B9 A9 7F 8D 0D DD A9 47 8D 18 03 A9 FE AD 19 03 CE 0E DD B0 14 A9 0D
20 D2 FF A4 FC A5 FD 20 91 B3 20 DD BD A9 01 A8 D0 04 A9 9D A0 C0 4C 1E AB 48
AD 0D DD 29 01 F0 14 E6 FC D0 02 E6 FD C6 FB D0 0A A9 18 85 FB CE 0E DD EE 0E
DD 68 40 0D C6 41 49 4C 00
  • -24 байта за счет встроенных функций и не заботясь о других прерываниях CIA2

Интернет демо (Usage:sys49152)

Скриншот


Объяснение:

Это была бы крошечная программа, если бы не проблема точного измерения миллисекунд на C64. Системное прерывание происходит примерно 60 раз в секунду, что даже близко не происходит. Таким образом, мы должны использовать аппаратный таймер, который получает свои входные сигналы от системных часов.

На машине PAL системные часы составляют ровно 985248 Гц. Следовательно, установка таймера в 985 дает около миллисекундных тиков, но это слишком быстро, мы должны считать 986 циклов для каждого четвертого такта или держать таймер для одного цикла. Это невозможно, но мы можем провести таймер на 6 циклов с последовательностью DEC $DD0E, INC $DD0E: $DD0Eэто регистр управления таймером с битом 0 переключения его включением и выключением, и обе инструкции принимают 6 циклов, поэтому точные пишет , что остановка и начать таймер ровно 6 циклов. Поэтому мы должны выполнять эту последовательность каждые 6 * 4 = 24-й тик. Это все еще не совсемточнее, таймер будет отставать на 1 миллисекунду после 8 минут и 12 секунд, но, вероятно, он достаточно хорош - для компенсации этого потребуется много кода.

редактирование : начальное значение для таймера должно быть 984, а не 985, потому что эти таймеры срабатывают "при недостаточном расходе", поэтому значение 0 будет подсчитывать еще один цикл до срабатывания. Код исправлен, число байтов не изменилось.

Вот прокомментированный список разборки:

         00 C0       .WORD $C000        ; load address
.C:c000  A9 17       LDA #$17           ; mode for upper/lower text
.C:c002  8D 18 D0    STA $D018          ; set in graphics chip
.C:c005  A9 40       LDA #$40           ; initialize expected character
.C:c007  85 FE       STA $FE            ; to 'a' - 1
.C:c009   .mainloop:
.C:c009  E6 FE       INC $FE            ; increment expected character
.C:c00b   .getchar:
.C:c00b  20 E4 FF    JSR $FFE4          ; read character from keyboard
.C:c00e  F0 FB       BEQ .getchar       ; until actual character entered
.C:c010  20 D2 FF    JSR $FFD2          ; output this character
.C:c013  C5 FE       CMP $FE            ; compare with expected
.C:c015  38          SEC                ; set carry as marker for error
.C:c016  D0 38       BNE .result        ; wrong character -> output result
.C:c018  C9 5A       CMP #$5A           ; compare with 'z'
.C:c01a  18          CLC                ; clear carry (no error)
.C:c01b  F0 33       BEQ .result        ; if 'z' entered, output result
.C:c01d  C9 41       CMP #$41           ; compare with 'a'
.C:c01f  D0 E8       BNE .mainloop      ; if not equal repeat main loop
.C:c021  A9 00       LDA #$00           ; initialize timer ticks to 0
.C:c023  85 FC       STA $FC
.C:c025  85 FD       STA $FD
.C:c027  A9 18       LDA #$18           ; counter for adjusting the timer
.C:c029  85 FB       STA $FB
.C:c02b  A9 7F       LDA #$7F           ; disable all CIA2 interrupts
.C:c02d  8D 0D DD    STA $DD0D
.C:c030  A9 7F       LDA #<.timertick   ; set NMI interrupt vector ...
.C:c032  8D 18 03    STA $0318
.C:c035  A9 C0       LDA #>.timertick
.C:c037  8D 19 03    STA $0319          ; ... to our own timer tick routine
.C:c03a  A9 D9       LDA #$D8           ; load timer with ...
.C:c03c  8D 04 DD    STA $DD04
.C:c03f  A9 03       LDA #$03
.C:c041  8D 05 DD    STA $DD05          ; ... 985 (-1) ticks (see description)
.C:c044  A9 01       LDA #$01           ; enable timer
.C:c046  8D 0E DD    STA $DD0E
.C:c049  A9 81       LDA #$81           ; enable timer interrupt
.C:c04b  8D 0D DD    STA $DD0D
.C:c04e  D0 B9       BNE .mainloop      ; repeat main loop
.C:c050   .result:
.C:c050  A9 7F       LDA #$7F           ; disable all CIA2 interrupts
.C:c052  8D 0D DD    STA $DD0D
.C:c055  A9 47       LDA #$47           ; set NMI interrupt vector ...
.C:c057  8D 18 03    STA $0318
.C:c05a  A9 FE       LDA #$FE
.C:c05c  AD 19 03    LDA $0319          ; ... back to system default
.C:c05f  CE 0E DD    DEC $DD0E          ; disable timer
.C:c062  B0 14       BCS .fail          ; if carry set, output fail
.C:c064  A9 0D       LDA #$0D           ; load newline
.C:c066  20 D2 FF    JSR $FFD2          ; and output
.C:c069  A4 FC       LDY $FC            ; load timer value in
.C:c06b  A5 FD       LDA $FD            ; A and Y
.C:c06d  20 91 B3    JSR $B391          ; convert to float
.C:c070  20 DD BD    JSR $BDDD          ; convert float to string
.C:c073  A9 01       LDA #$01           ; load address of
.C:c075  A8          TAY                ; string buffer
.C:c076  D0 04       BNE .out           ; and to output
.C:c078   .fail:
.C:c078  A9 9D       LDA #<.failstr     ; load address of "Fail" string
.C:c07a  A0 C0       LDY #>.failstr     ; in A and Y
.C:c07c   .out:
.C:c07c  4C 1E AB    JMP $AB1E          ; done; OS routine for string output
.C:c07f   .timertick:
.C:c07f  48          PHA                ; save accu
.C:c080  AD 0D DD    LDA $DD0D          ; load interrupt control register
.C:c083  29 01       AND #$01           ; to know whether it was a timer NMI
.C:c085  F0 14       BEQ .tickdone      ; if not -> done
.C:c087  E6 FC       INC $FC            ; increment timer ticks ...
.C:c089  D0 02       BNE .adjusttick
.C:c08b  E6 FD       INC $FD            ; high byte only on overflow
.C:c08d   .adjusttick:
.C:c08d  C6 FB       DEC $FB            ; decrement counter for adjusting
.C:c08f  D0 0A       BNE .tickdone      ; not 0 yet -> nothing to do
.C:c091  A9 18       LDA #$18           ; restore counter for adjusting
.C:c093  85 FB       STA $FB
.C:c095  CE 0E DD    DEC $DD0E          ; halt timer for exactly
.C:c098  EE 0E DD    INC $DD0E          ; 6 cycles
.C:c09b   .tickdone:
.C:c09b  68          PLA                ; restore accu
.C:c09c  40          RTI
.C:c09d   .failstr:
.C:c09d  0D C6 41    .BYTE $0D,"Fa"
.C:c0a0  49 4C 00    .BYTE "il",$00

6
Ну, теперь у меня есть несколько приличных миллисекундных таймеров в моем наборе инструментов;) может быть когда-нибудь пригодится.
Феликс Пальмен

11
Обратите внимание, сценарий детишек. Это настоящий гольф.
J ...

1
@J ... Я мог бы сыграть в эту игру дальше, вставив .starttimer- скоро сделаю :) (и даже дальше, используя систему, TIподобную этому основному ответу , но я не уверен, что это действительно так, потому что вы можете добиться большего в машинном коде )
Феликс Пальмен

Вау, я пропустил коэффициент 985 при первом вычислении ошибки в моем измерении времени - это на самом деле очень хорошо (если я допустил еще одну ошибку в моих вычислениях, пожалуйста, укажите!) :)
Феликс Пальмен,

И вы видите, что этот парень имеет в GITHUB ?: восстановление загрузки Android .... он совершенно безумен! одобрил его профиль.
Лучано Андресс Мартини

13

Bash + coreutils, 103 99 98 байт

for((;c==p%26;r=`date +%s%3N`-(s=s?s:r),c=62#$c-9,p++))
{
read -N1 c
}
((c==p))||r=Fail
echo "
$r"

Должен быть запущен в терминале.

Тестовый забег

$ bash type.sh
abcdefghijklmnopqrstuvwxyz
3479
$ bash type.sh
abcz
Fail
$ bash type.sh 2>&- # typing '@' would print to STDERR
ab@
Fail
$ bash type.sh
A
Fail

4
3479довольно быстро! молодец :)
RobAu

Требуется ли конкретная версия Bash или что-то? На 4.4.12 набор aсразу дает мне line 1: ((: r=15094100773N: value too great for base (error token is "15094100773N")и выходит.
номер человека

@numbermaniac Версия Bash не должна иметь значения, но должна dateбыть. Мой из GNU coreutils 8.23. Что date +%s%3Nпечатает в вашей системе?
Деннис

@ Деннис выводит 15094104833N- это встроенная dateутилита в macOS, если это имеет значение.
Numbermaniac

1
@numbermaniac BSD, dateкажется, использует strftime, который не распознает %N.
Деннис

9

Python 2 + getch , 116 байт

import time,getch
t=[i+97-ord(getch.getche())and exit("Fail")or time.time()for i in range(26)]
print(t[-1]-t[0])*1e3

Спасибо ovs и ElPedro за исправление кода и сохранение 57 байт.


7

SOGL V0.12 , 35 байт

"ζ¦F‘→I
]I!}Su[I:lzm≠?■Fail←z=?Suκ←

Попробуй здесь! - нажмите кнопку «Выполнить» и введите алфавит в поле ввода. Обратите внимание, что это может быть немного запаздывающим, потому что SOGL делает паузу только для ввода каждые 100 выполненных токенов (а SOGL довольно медленный). Если это вас беспокоит, запустите sleepBI=trueв консоли.

примечание: не запускайте это в режиме совместимости - это будет просто цикл навсегда.

Объяснение:

"ζ¦F‘    push "inputs.value" (yes, that is a word in SOGLs english dictionary)
     →   execute as JS, pushing the inputs contents
      I  named function I


]  }                do while POP is truthy
 I                    execute I
  !                   negate it - check if it's empty
    Su              push the current milliseconds since start
[                   loop
 I                    execute I
  :                   duplicate the result
   l                  let its length
    zm                mold the alphabet to that size
      ≠?              if that isn't equal to one of the result copies
        ■Fail           push "Fail"
             ←          and exit, implicitly outputting that
              z=?     if the other copy is equal to the alphabet
                 Su     push the milliseconds since start
                   κ    subtract the starting milliseconds from that
                    ←   and exit, implicitly outputting the result

@HyperNeutrino Я знал, что это пригодится: p
dzaima

Кто бы мог ожидать, что SOGL сможет это сделать ... кстати, не является ли слово "Fail" в словаре?
Эрик Outgolfer

@EriktheOutgolfer хорошо, SOGL должен был быть универсальным языком, но это не сработало: p
dzaima

Кстати, я не знаю, является ли это полностью действительным, но опять же я думаю, что это может быть проблема с интерфейсом, а не с интерпретатором позади ...
Эрик Outgolfer

@EriktheOutgolfer, да, я не знаю, насколько это оправданно, наверное, я жду ОП. Сначала я думал, что это что-то вроде HTML-ответа, но теперь я смотрю на него совсем иначе
dzaima

7

Паскаль (FPC) , 176 байт

Uses CRT,SysUtils;Var c:char;a:Real;Begin
for c:='a'to'z'do
if c=ReadKey then
begin Write(c);if c='a'then a:=Now;end
else
begin
Write('Fail');Halt;end;Write((Now-a)*864e5)
End.

Попробуйте онлайн!

Некоторые трюки, используемые в коде для игры в гольф:

  • Используйте Realв качестве более короткой альтернативы TDateTime, потому что, как здесь определено , TDateTime= Double, который является типом с плавающей точкой.
  • Вместо того, чтобы использовать MilliSecondsBetweenдля вычисления промежутка времени, этот код умножает разницу между двумя значениями с плавающей запятой на 864e5, что работает из-за способа кодирования Free Pascal, TDateTimeописанного здесь .

Заметка:

  • ReadKeyФункция на самом деле не печатает ключ на консоли, поэтому ручная запись в консоль Write(c)необходима.
  • TIO набирают очки 0за ввод алфавита по понятной причине.
  • Программа печатает время в формате с плавающей точкой, я думаю, это разрешено.

Добро пожаловать на сайт!
Caird Coneheringaahing

Вы можете сохранить 1 байт, переместив в for c:='a'to'z'doту же строку, что и a:=Time;.
Исмаэль Мигель

Может быть, вы должны попробовать, Nowа не Timeкак это короче.
TSH

Почему 86398338?? Я могу понять, умножаете ли вы 864e5, так как в день 864e5 миллисекунд. но как получается это магическое число?
TSH

@tsh Я тоже не знаю. При ручном тестировании я нахожу этот «магический» номер, и я не знаю, как хранить Паскаль TDateTimeкак Double. 864e5звучит правильнее, я исправлю проблемы.
user75648

5

Java, 404 388 354 348 320 318 байт

import java.awt.*;import java.awt.event.*;interface M{static void main(String[]a){new Frame(){{add(new TextArea(){{addKeyListener(new KeyAdapter(){long t,i=64;public void keyPressed(KeyEvent e){t=t>0?t:e.getWhen();if(e.getKeyChar()!=++i|i>89){System.out.print(i>89?e.getWhen()-t:"Fail");dispose();}}});}});show();}};}}

И здесь я подумал, что консоль Java уже многословна.
Поскольку у Java нет способа прослушивания нажатий клавиш в консоли, я использую GUI java.awt.

-78 байт благодаря @ OlivierGrégoire .

Объяснение:

import java.awt.*;                 // Required import for Frame and TextField
import java.awt.event.*;           // Required import for KeyAdapter and KeyEvent
interface M{                       // Class
  static void main(String[]a){     //  Mandatory main-method
    new Frame(){                   //   Create the GUI-Frame
      {                            //    With an initialization-block
        add(new TextArea(){        //     Add an input-field
          {                        //      With it's own initialization-block
            addKeyListener(new KeyAdapter(){
                                   //       Add a KeyAdapter to the input-field
              long t,              //        Long to save the time
                   i=64;           //        Previous character, starting at code of 'a' -1
              public void keyPressed(KeyEvent e){ 
                                   //        Override the keyPressed-method:
                t=t>0?             //         If `t` is already set:
                   t               //          Leave it the same
                  :                //         Else:
                   e.getWhen();    //          Save the current time (== start the timer)
                if(e.getKeyCode()!=++i
                                   //         As soon as an incorrect character is pressed,
                   |i>89){         //         or we've reached 'z':
                  System.out.print(i>89?
                                   //          If we're at 'z':
                    e.getWhen()-t  //           Print the end-time in ms to the Console
                   :               //          Else (an incorrect character was pressed)
                    "Fail");       //           Print "Fail" to the Console
                  dispose();}      //          And exit the application
              }                    //        End of keyPressed-method
            });                    //       End of KeyAdapter
          }                        //      End of input-field initialization-block
        });                        //     End of input-field
        show();                    //     Initially show the Frame
      }                            //    End of Frame initialization-block
    };                             //   End of Frame 
  }                                //  End of main-method
}                                  // End of class

Пример GIF успеха: (Да, я набираю алфавит довольно медленно здесь ..)
Примечание: Это старый GIF. Текущая версия больше не печатает нажатия клавиш на консоли. И он больше не печатает время с цифрами после десятичной точки.

введите описание изображения здесь
Пример gif сбоя:
Примечание: это старый gif. Текущая версия больше не печатает нажатия клавиш на консоли.

введите описание изображения здесь


2
Впечатляющий ответ, учитывая, что у него есть графический интерфейс!
Pureferret

1
388 байт . Я позволил себе исправить ваш код в дополнение к игре в гольф, потому что вы использовали setVisible(false)вместо выхода.
Оливье Грегуар

@ OlivierGrégoire Спасибо. Забыл про showи dispose, который еще короче setVisible. Я почти никогда не использую графический интерфейс Java. И умно использовать инициализацию класса вместо того, чтобы помещать его в метод main. Я должен помнить это.
Кевин Круйссен

1
@KevinCruijssen Спасибо, и никаких проблем ;-) Хотя некоторые более общие комментарии: вам не нужно выводить буквы дважды. Повторение уже предоставлено TextField. Кроме того, вы можете использовать TextAreaвместо того, TextFieldчтобы получить два байта. Наконец, KeyEventесть getWhenметод, который дает время между эпохой и событием в миллисекундах. Просто нужно использовать их вместо того, System.nanoTime()чтобы получить еще больше байтов.
Оливье Грегуар

1
Пожалуйста! Но я сократил его до 320 байтов . ;-)
Оливье Грегуар,

4

C # (.NET Core), 245 + 13 183 + 41 177 + 41 байт

+41 байт для using System;using static System.Console.

Не проверял, так как я на мобильном телефоне, и это не работает на TIO.

n=>{int c=ReadKey().KeyChar,x=0;try{if(c!=97)x/=x;var s=DateTime.Now;while(c<149)if(ReadKey().KeyChar!=c++)x/=x;Write((DateTime.Now-s).TotalMilliseconds);}catch{Write("Fail");}}

1
+1 за создание работающей программы без возможности ее тестирования. Игра в гольф: 1) Один короткий путь, который я нашел, чтобы произвести исключение: int x=0;и затем сделайте x=1/x;. Это должно сэкономить 14 байтов. К сожалению, вам нужно x. Если вы попытаетесь сделать это, 1/0вы получите деление на постоянную нулевую ошибку компилятора. 2) -5 байтов для объединения объявления cс первым ReadKey. 3) Изменение состояния во внутренней , ifчтобы ReadKey!=++cи удалить c++;elseдля другого -9 байт.
Разнагул

@raznagul Спасибо! x=1/xможет быть уменьшен до x/=x. И я добавил, using static System.Console;чтобы сохранить еще несколько байтов :)
Ян Х.

Еще несколько байтов могут быть сохранены путем удаления iи использования cв условии цикла вместо этого.
Разнагул

3

MSX-BASIC, 126 символов

1C=97:GOSUB3:TIME=0
2IFASC(C$)<>CTHEN?"Fail":ENDELSEIFC=122THEN?TIME*20:ENDELSEC=C+1:GOSUB3:GOTO2
3C$=INKEY$:IFC$=""GOTO3
4RETURN

TIME является внутренней переменной MSX-BASIC, которая увеличивается на единицу каждые 20 миллисекунд.


3

C # (.NET Core) , 184 + 13 = 197 173 + 13 = 186 байт

()=>{var s=DateTime.Now;var i=97;while(i<123&&Console.ReadKey().KeyChar==i)if(i++<98)s=DateTime.Now;Console.Write(i>122?$"\n{(DateTime.Now-s).TotalMilliseconds}":"\nFail");}

Попробуйте онлайн!

К сожалению, TIO не может запустить это, но это удобно для подсчета байтов.

+13 за using System;

-1, изменив i==123на i>122. Я был соблазн сделать это i>'z'.

Подтверждения

-10 байт благодаря @raznagul

Ungolfed

()=>{
    var s=DateTime.Now;
    var i=97;

    while(i<123&&Console.ReadKey().KeyChar==i)
        if(i++<98)
            s=DateTime.Now;

    Console.Write(i>122?
        $"\n{(DateTime.Now-s).TotalMilliseconds}":
        "\nFail"
    );
} 

1
Вы можете сохранить несколько байтов, переместив ReadKeyих в условие цикла, чтобы вы могли удалить первый ifи break.
Разнагул

3

Node.js, 240 213 байт

require('readline',{stdin:i,stdout:o,exit:e}=process).emitKeypressEvents(i)
w=s=>o.write(s)
n=0
i.on('keypress',c=>w(c)&&c.charCodeAt()-97-n?e(w(`
Fail`)):!n++?s=d():n>25&&e(w(`
`+(d()-s)))).setRawMode(d=Date.now)

РЕДАКТИРОВАТЬ: Сохранено 27 байтов благодаря Иордании

Безголовая версия:

const readline = require('readline')

let index = 0
let start

readline.emitKeypressEvents(process.stdin)
process.stdin.setRawMode(true)

process.stdin.on('keypress', character => {
  process.stdout.write(character )

  // Lookup character in ASCII table
  if (character !== String.fromCharCode(97 + index) {
    process.stdout.write('\nFail')
    process.exit()
  }

  index++

  if (index === 1) {
    start = Date.now()
  }

  if (index === 26) {
    process.stdout.write('\n' + (Date.now() - start))
    process.exit()
  }
})

3

C (gcc) , 303 байта

Работает на * nix системах. Автономный код, удаляющий канонический режим текущего терминала, чтобы позволить чтение символов без ожидания перевода строки:

/! \ Запуск этой программы сделает терминал практически непригодным для использования.

#import <stdlib.h>
#import <termios.h>
#define x gettimeofday(&t,0)
#define r t.tv_sec*1000+t.tv_usec/1000
c,i=97;main(){long s=0;struct termios n;struct timeval t;cfmakeraw(&n);n.c_lflag|=ECHO;tcsetattr(0,0,&n);for(;i<'d';){c=getchar();if(c!=i++)puts("\nFail"),exit(0);x;s=s?:r;}x;printf("\n%ld",r-s);}

Развернулся и прокомментировал:

// needed in order to make gcc aware of struct termios
// and struct timeval sizes
#import <stdlib.h>
#import <termios.h>

// gets the time in a timeval structure, containing
// the number of seconds since the epoch, and the number
// of µsecs elapsed in that second
// (shorter than clock_gettime)
#define x gettimeofday(&t,0)
// convert a timeval structure to Epoch-millis
#define r t.tv_sec*1000+t.tv_usec/1000

// both integers
// c will contain the chars read on stdin
// 97 is 'a' in ASCII
c,i=97;

main(){
  long s=0; // will contain the timestamp of the 1st char entered
  struct timeval t; // will contain the timestamp read from gettimeofday

  // setting up the terminal
  struct termios n;
  cfmakeraw(&n);//create a raw terminal configuration
  n.c_lflag|=ECHO;//makes the terminal echo each character typed
  tcsetattr(0,0,&n);//applies the new settings

  // from 'a' to 'z'...
  for(;i<'{';){
    // read 1 char on stdin
    c=getchar();

    // if int value of the input char != expected one => fail&exit
    if(c!=i++)puts("\nFail"),exit(0);

    // macro x: get current timestamp
    x;

    // if not already set: set starting timestamp
    s=s?:r;
  }

  // get end of sequence timestamp
  x;

  // prints the end-start timestamps difference
  printf("\n%ld",r-s);
}

Альтернативное решение (218 байт):

Если предварительная настройка терминала разрешена, то мы можем избавиться от части кода, обрабатывающей эту часть.

Вот тот же код без терминальной манипуляции:

#import <stdlib.h>
#define x gettimeofday(&t,0)
#define r t.tv_sec*1000+t.tv_usec/1000
c,i=97;main(){long s=0;struct timeval t;for(;i<'{';){c=getchar();if(c!=i++)puts("\nFail"),exit(0);x;s=s?:r;}x;printf("\n%ld",r-s);}

Чтобы это работало:

$ gcc golf.c
$ stty -icanon
$ a.out

пример выполнения: введите описание изображения здесь


3

Commodore BASIC v2 - 113 байт

Заглавные буквы должны быть сдвинуты.
Спасибо Феликсу Палмену за указание на некоторые опечатки, спецификации
попробуйте

0d=64
1on-(f=26)gO5:gEa$:ifa$=""tH1
2iff=0tHt=ti
3f=f+1:ifa$<>cH(d+f)tH6
4?cH(14)a$;:gO1
5?:?(ti-t)/60*1000:eN
6?"Fail"

Нажмите edit, чтобы увидеть исправленный код уценки.
NieDzejkob

Добро пожаловать на сайт! Не могли бы вы добавить ссылку на интерпретатор (если он существует), чтобы другие могли проверить ваш код?
Caird Coneheringaahing

Ну, это использует систему IRQ ( TIувеличивается в ней), которую я счел неподходящей из- за ее недостаточной точности, но я думаю, что это справедливая игра здесь, потому что просто нет способа добиться большего успеха в Бейсике :) Тем не менее, вставив это в тиски, я получаю синтаксическая ошибка в 1- любая помощь?
Феликс Пальмен

Сам разобрался, у вас есть опечатка в первой строке, должны быть 1on-(f=26)gO4:gEa$:ifa$=""tH1Nitpicks: 1.) вывод находится в той же строке, 2.) вывод - все заглавные - я думаю, вы должны исправить это, не займет много байтов В любом случае :)
Феликс Пальмен

Устранены проблемы, остались опечатки?
mondlos

2

Perl 5, 79 93 +31 (-MTerm :: ReadKey -MTime :: HiRes = время) байтов

$|=1;map{ReadKey eq$_||exit print"
Fail";$s||=time}a..z;print$/,0|1e3*(time-$s)

$|=1недостаточно для установки терминала в режиме raw, stty -icanonдолжен быть запущен до или

ReadMode 3;map{ReadKey eq$_||exit print"
Fail";print;$s||=time}a..z;print$/,0|1e3*(time-$s)

чтобы увидеть символы в терминале после запуска команды: stty echoилиstty echo icanon


Старый добрый ReadKey! Вы можете сохранить несколько байтов здесь и там, 1e3для 1000, $s||=timeи если вы установите $sсначала, а затем вызов ReadKey, вы можете заменить на mapпостфикс for. Я хотел бы сказать dieвместо exit print, но я думаю, что вы тут же ... Я возился с этим, printf"\n%i"но это закончилось большим, и я подумал об использовании $-вместо $s, но это было глупо! :)
Дом Гастингс

@DomHastings, спасибо за вашу помощь, я мог бы сохранить 4 байта, но я добавил 5 байтов, чтобы установить небуферизованный ввод $|=1;, также $ s || = время не может быть заменено на карте, потому что таймер должен запускаться после первого нажатия клавиши, и dieбудет эхо Failна stderr вместо стандартного вывода.
Науэль Фуйе

Рад помочь, надеюсь, вы не возражаете, я предлагаю идеи! Да, это позор, exit printэто так долго! К сожалению, я не думаю , что я объяснил свою мысль для forправильно: $s||=time,ReadKey eq$_||exit print" Fail"for a..zдолжны работать , я думаю , что ... Может быть , даже , $|=$s||=...или $|=map...если вы предпочитаете такой подход! Думаю, ты в значительной степени прибил это все же!
Дом Гастингс

$|=map..не устанавливает небуферизованный ввод в новом терминале (у меня была ошибка при удалении, ReadMode 3, потому что я тестировал в том же сеансе), и $s||=timeдо того, как первый ReadKey запустил таймер слишком рано
Науэль Фуийе

Ааа, я неправильно понял, я понял это сейчас, не ждал достаточно долго после запуска сценария, чтобы проверить это ... :) Позор $|, но опять же, он запоминает после цикла, который слишком поздно! Ты на шаг впереди!
Дом Гастингс

2

Aceto , 70 байт

d'|d 't9
$z=p zp1
!=   >#v
d,   1 +
cTpaXpn3
Io$'p"*F
|'!=ilnu
@ad,aF"

Я начну с установки метки и зеркального отражения по горизонтали ( @|), если значение в стеке верно. Это не изначально, а позже всегда будет. Мы вернемся сюда позже, если будет введен неправильный ключ. Затем мы нажимаем a в стеке ( 'a), затем дублируем его и читаем один символ из user ( d,). Если два символа не равны ( =!), мы «сбой» ( $) и вернуться к метке. В противном случае мы нажимаем другое «а» и печатаем его, затем устанавливаем текущее время ( 'apT).

Затем мы вводим наш «основной цикл»: «увеличиваем» текущий символ и «увеличиваем» символ ( 'apToIc), затем дублируем его, читаем новый символ, сравниваем его и «сбиваем», если символы не идентичны ( d,=!$). Если мы не потерпели крах, мы сравниваем текущий символ с «z» ( d'z=|), если он не равен, мы печатаем символ, затем нажимаем 1 и «условно» (в данном случае: всегда) переходим к только oв коде (начало нашего основного цикла). Если он был равен z, мы отразили по горизонтали какое-то пустое пространство сверху. Мы печатаем «z», затем нажимаем текущее время (минус время начала; t), а затем умножаем на него число 1000 (полученное поднятием 10 до третьей степени; 91+3F), потому что мы получаем секунды, не миллисекунды). Затем мы печатаем новую строку, время и выход (pX).

Если мы когда-нибудь потерпим крах (плохой ввод пользователем), мы прыгнем до самого начала. Так как теперь у нас будет некоторое истинное значение в стеке, мы будем зеркально отображать горизонталь в направлении u, которое меняет направление, в котором мы двигаемся. nПечатает символ новой строки, затем мы толкаем "Fail"стек, печатаем его и выходим ( pX).


1

Mathematica (записная книжка), 248 байт

DynamicModule[{x={},s=0,t=0},EventHandler[Framed@Dynamic[If[x=={"a"}&&s<1,s=SessionTime[]];Which[x==a,If[t==0,t=SessionTime[]-s];1000t,x==a~Take~Length@x,""<>x,1>0,"Fail"]],Table[{"KeyDown",c}:>x~AppendTo~CurrentValue@"EventKey",{c,a=Alphabet[]}]]]

Как это работает

DynamicModule[{x={},s=0,t=0},
  EventHandler[
    Framed@Dynamic[
      If[x=={"a"} && s<1,s=SessionTime[]];
      Which[
        x==a,If[t==0,t=SessionTime[]-s];1000t,
        x==a~Take~Length@x,""<>x,
        1>0,"Fail"]],
    Table[{"KeyDown",c}:>x~AppendTo~CurrentValue@"EventKey",
      {c,a=Alphabet[]}]]]

A DynamicModuleс EventHandlerответом на строчные буквы. Переменные x, sи tудерживайте нажатыми до сих пор буквы, время начала и время окончания соответственно. Как только мы заметим, xчто мы равны {"a"}, мы начинаем время; мы отображаем либо общее потраченное время, либо построенную строку, либо в "Fail"зависимости от того, какое условие выполнено.

Мы могли бы сохранить другой байт t<1вместо того, t==0чтобы предположить, что никто не достаточно быстр, чтобы набрать алфавит менее чем за одну секунду :)

Если вы пробуете это в записной книжке Mathematica, имейте в виду, что вы должны щелкнуть внутри рамки, прежде чем ваши нажатия клавиш будут зарегистрированы. (Это причина того, что нам нужен кадр для начала; если Framedего там нет, то весь выбранный объект изменяется при нажатии клавиши, поэтому он перестает быть выбранным, и вам придется нажимать снова.)


1

C #, 154 152 + 13 = 165 байт

Сохранено 2 байта благодаря комментариям Ayb4btu

x=>{
  long t=0,c=97;
  for(;Console.ReadKey().KeyChar==c++&&c<123;t=t<1?DateTime.Now.Ticks:t);
  Console.Write(c>122?"\n"+(DateTime.Now.Ticks-t)/1e4:"\nFail");
}

В приведенном выше коде есть пробел, чтобы он поместился в SE без полосы прокрутки. Пробелы не входят в число байтов

и 13 байт для using System;

Это похоже на версию Ayb4btu, но со следующими отличиями:

  • Хранение datetime как long позволяет нам также делать clong и сокращать объявление

  • Петля не нуждается в отдельном перерыве

  • На самом деле это не короче, по $"interpreted strings"сравнению с добавлением необходимого "\ n" в миллисекундах, чтобы сделать его строкой для встроенного, если

  • Использование forцикла иногда позволяет нам сохранять символы в течение некоторого времени, хотя я думаю, что этот не будет сохранять по сравнению с эквивалентнымwhile

Из Айб4бту:

  • s=s==0может стать s=s<1и c==123может статьc>122

Ungolfed

long t=0,c=97;

for (;                                         //no loop vars declared
  Console.ReadKey().KeyChar == c++ && c < 123; //loop test
  t = t < 1 ? DateTime.Now.Ticks : t          //post-loop assigns
) ;                                            //empty loop body!

//now just need to turn ticks into millis, 10,000 ticks per millis
Console.Write(c>122?"\n"+(DateTime.Now.Ticks-t)/1e4:"\nFail");

Хорошее решение с тем, как вы использовали DateTime. Вы можете сохранить еще пару байтов, изменив s=s==0на s=s<1(рассчитывая на то, что s не будет отрицательным), и изменив i==123на i>122.
Ayb4btu

Кроме того, это было проверено? Как я обнаружил, что i<123должен был идти перед ReadKey(), в противном случае он ждет другого символа после z, прежде чем отображать время.
Ayb4btu

Странно, потому что в конце алфавита zдолжно означать, что readkey.keychar возвращает 122, когда пользователь вводит z, c также равен 122, следовательно, 'z' == 122успешно, c затем увеличивается, затем c (теперь 123) проверяется c<123и завершается неудачей, останавливая петля ..?
Caius Jard

Вы правы, я пропустил c++приращение, когда я смотрел на это. Тем не менее, я только что попробовал это, и когда я набираю, abcdefghijklmnopqrstuvwxysэто дает мне время, а не неудачу. Я полагаю, что это потому, что cвсе еще увеличивается, хотя KeyCharпроверка не проходит, поэтому проходит c>122проверку.
Ayb4btu

Хороший вопрос - возможно, перемещение ++ к проверке c <123 сохранит байтовый счет таким же и предотвратит увеличение c, если последний символ неправильный - сейчас нет времени на отладку, но я посмотрю на это! ура :)
Caius Jard

0

Processing.org 133 142

первый код не вышел

char k=97;int m;void draw(){if(key==k){m=m<1?millis():m;print(key=k++,k>122?"\n"+(millis()-m):"");}if(m>0&&key!=k-1){print("\nFail");exit();}}

0

GCC, windows, 98 байт

t;main(i){for(;i++<27;t=t?:clock())if(95+i-getche())return puts("\nFail");printf("\n%d",clock()-t);}

Не требует мгновенного ввода для первой клавиши

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.