Output Keystrokes

14

2

In any programming language, create a program that takes input and animates the text being typed on a keyboard.

The delay between each character should be varying to simulate true typing on a keyboard. The delay shall be 0.1, 0.1, 0.5, 0.1, 0.1, 0.5 ... seconds, until the last character is printed. The final output shall be left on the screen.

You must overwrite the current line of text you can't have the text be printed on new rows.

Example, the input "Hello, PPCG! Goodbye Earth!" should result in the following animation (note that the sampling rate of the gif-maker was low, so the true result is slightly different):

enter image description here

Since this is code golf, the smallest amount of bytes win.

Olly Britton

Posted 2017-02-18T09:12:39.140

Reputation: 151

"You must overwrite the current line of text you can't have the text be printed on new rows." - is this implying that the program must clear the input and produce output in it's place? (Side note: your animation looks faster than specified.) – Jonathan Allan – 2017-02-18T18:26:13.530

Can we assume there is always input? – Metoniem – 2017-02-18T18:39:37.573

And can we exit with an error after the animation is done? – Metoniem – 2017-02-18T18:41:44.137

1Is the delay supposed to be random, or a repeating pattern of 0.1, 0.1, 0.5? – 12Me21 – 2017-02-18T18:42:17.877

2Should there be a delay before printing the first character? – user41805 – 2017-02-18T18:45:31.340

1It's that pattern yes @12Me21 – Metoniem – 2017-02-18T18:47:22.657

I'm not sure if I can time stuff that accurately on the Commodore 64 (without a SuperCPU, I might be able to with) or Sinclair ZX81, would it be okay if I don't hit these timings on that basis? – Shaun Bebbers – 2017-02-20T15:34:21.293

I should have added Commodore and Sinclair ZX81 BASIC - assembly would be a different beast – Shaun Bebbers – 2017-02-20T20:11:20.453

Answers

8

C 108 93 89 78 73 80 bytes

f(char *s){for(int i=0;s[i];fflush(0),usleep(100000*(i++%3?1:5)))putchar(s[i]);}

Ungolfed version:

 void f(char *s)
 {
  for( int i=0;s[i];)
  {
    putchar(s[i]);
    fflush(0);
    usleep(100000*(i++%3?1:5));
 }
}

@Kritixi Lithos @Metoniem Thanks for your input! saved some bytes.

Somehow, just int i gave me a segmentation error on running, so I initialized it with 0.

Abel Tom

Posted 2017-02-18T09:12:39.140

Reputation: 1 150

1Wether you use my improvements or not: Your delays should be the other way around. if i%3 the delay should be 5. – Metoniem – 2017-02-18T19:04:17.410

Replace 100000 with 1e5 to shave 3 bytes – Albert Renshaw – 2017-02-19T04:08:49.600

@AlbertRenshaw Thanks for the tip, updated. I have used it in some of my other solutions too don't know why I forgot here. – Abel Tom – 2017-02-19T07:32:44.187

@AbelTom For some reason, 1e5 doesn't work on my device – user41805 – 2017-02-19T07:40:30.270

@KritixiLithos howcome? are you on Linux? – Abel Tom – 2017-02-19T07:48:02.930

@AbelTom No, I'm on macOS – user41805 – 2017-02-19T07:49:37.793

@KritixiLithos According to man usleep, the function takes unsigned int as argument, I don't even get a warning. May be compiler does the typecasting implicitly. – Abel Tom – 2017-02-19T08:06:33.493

C only default-initialises global variables to 0, not local variables. – Neil – 2017-02-19T08:53:36.420

@Neil Thanks, did not know that, learnt something new, :) updated! – Abel Tom – 2017-02-19T09:26:31.437

I think this is 72 bytes not 73 – Albert Renshaw – 2017-02-20T03:04:21.433

Also you can get down to 68 bytes by moving the putchar into your for-loop's conditional section. Will return false if there is nothing to putchar. i;f(char *s){for(;putchar(s[i]);fflush(0),usleep(1e5*(i++%3?5:1)));} Note: I could not find an online C IDe that supported usleep in the output so I wasn't able to test this and see if it works in terms of the animation, but the logic part of it did work. – Albert Renshaw – 2017-02-20T03:07:45.627

1. The delays are wrong. i++%3?5:1 will return 5 twice and 1 once. It should be backwards. 2. Without including unistd.h, the compiler cannot possibly know that usleep expects an int, so it will pass a float. There is no conversion there; the byte representation of 1e5 gets used as is. 3. Per meta consensus, functions have to be reusable, so you have to reset your counter to 0. – Dennis – 2017-02-20T06:54:45.567

@Dennis Thanks for the feedback! 1. I was right the first time I implemented the delay with if else. 2. I have unistd.h included, so that explains the type conversion of 1e5.If one does not have it included, then the representation should be in int format. 3. Re-wrote the code such that i is local and initialized to 0. – Abel Tom – 2017-02-20T11:58:12.913

The sleep times still don't seem quite right, as it should sleep 0.1 seconds after the first character, 0.5 seconds after the third. This works and it's a bit shorter. i;f(char*s){for(i=0;putchar(*s++);usleep(100000*(++i%3?1:5)))fflush();} It prints a null byte at the end, but since this challenge is about visual output, I think that's OK. – Dennis – 2017-02-20T18:17:01.020

6

Jelly, 13 bytes

115D÷⁵ṁȮœS¥@"

This is a monadic link/function. Due to implicit output, it doesn't work as a full program.

Verification

How it works

115D÷⁵ṁȮœS¥@"  Monadic link. Argument: s (string)

115            Set the return value to 115.
   D           Decimal; yield [1, 1, 5].
    ÷⁵         Divide all three integers by 10.
      ṁ        Mold; repeat the items of [0.1, 0.1, 0.5] as many times as
               necessary to match the length of s.
          ¥@"  Combine the two links to the left into a dyadic chain and apply it
               to each element in s and the corr. element of the last return value.
       Ȯ         Print the left argument of the chain (a character of s) and sleep
                 as many seconds as the right argument indicates (0.1 or 0.5).

Dennis

Posted 2017-02-18T09:12:39.140

Reputation: 196 637

6

MATLAB, 74 bytes

c=input('');p=[1,1,5]/10;for i=c;fprintf('%s',i);p=p([2,3,1]);pause(p);end

Explanation:

I used quite a while to make the fprintf version shorter than disp() with clc. The breakthrough was when I found out / remembered that pause can take a vector as argument, in which case it will just pick the first value. This makes it possible to leave out a counter.

c=input('');    % Take input as 'Hello'
p=[.1,.1,.5];   % The various pause times

for i=c;            % For each of the characters in the input c
  fprintf('%s',i);  % Print the character i, without any trailing newline or whitespace
                    % No need to clear the screen, it will just append the new character 
                    % after the existing ones
  pause(p);         % pause for p(1) seconds. If the input to pause is a vector, 
                    % then it will choose the first value
  p=p([2,3,1]);     % Shift the pause times
end

The shortest I got using disp was 81 bytes:

c=input('');p=[1,1,5]/10;for i=1:nnz(c),clc;disp(c(1:i));pause(p(mod(i,3)+1));end

Stewie Griffin

Posted 2017-02-18T09:12:39.140

Reputation: 43 471

Can you do printf instead of fprintf? It works on https://octave-online.net/ (but it's Octave and not Matlab)

– user41805 – 2017-02-19T11:58:01.320

4

V, 20 19 18 bytes

1 byte saved thanks to @DJMcMayhem

saved 1 byte by removing ò at the end

òD1gÓulD1gÓulDgÓul

Terribly ungolfy, I know, it's just that strict undo preventing me to use nested loops.

Explanation

The cursor starts in the beginning of the buffer, which is the first character of the input.

ò                      " Start recursion
 D                     " Deletes everything from the cursor's position to the end of line
  1gÓ                  " Sleep for 100ms
     u                 " Undo (now the deletion is reverted)
      l                " Move cursor one to the right
       D1gÓul          " Do it again
             D         " Same as before but...
              gÓ       " Sleep for 500ms this time
                ul     " Then undo and move right
                       " Implicit ò

Gif coming soon...

user41805

Posted 2017-02-18T09:12:39.140

Reputation: 16 320

without a count defaults to 500 ms, so you can save a byte there. Also, remember that you don't need the second ò! – James – 2017-02-18T23:43:49.667

Instead of undo can you just paste? Unsure if that helps at all though – nmjcman101 – 2017-02-19T01:45:37.070

@DJMcMayhem I don't know why I missed the default 500, thanks! But I need the second ò because otherwise the program terminates early on account of the implicit newline at the end causing a breaking error. – user41805 – 2017-02-19T07:16:06.267

@nmjcman101 I was also thinking about using paste, but alas it moves the cursor to the end of the line and to go back I would need something like \`` which would only increase my bytecount further – user41805 – 2017-02-19T07:19:47.473

4

JavaScript (ES6), 67 bytes

f=(i,o,n=0)=>i[n]&&(o.data+=i[n],setTimeout(f,++n%3?100:500,i,o,n))
<form><input id=i><button onclick=f(i.value,o.firstChild)>Go!</button><pre id=o>

Neil

Posted 2017-02-18T09:12:39.140

Reputation: 95 035

The snippet doesn't seem to work – user41805 – 2017-02-18T19:23:33.307

@KritixiLithos Yup, doesn't seem to work on Chrome :-( – Metoniem – 2017-02-18T19:25:43.937

works in firefox tho – Conor O'Brien – 2017-02-19T01:40:58.587

2It works for me in Chrome, but the console says Blocked form submission to '' because the form's frame is sandboxed and the 'allow-forms' permission is not set. – numbermaniac – 2017-02-19T01:41:54.993

@numbermaniac I changed the snippet to use a different event. (I'm so old I can actually remember when hitting Enter in a form field didn't trigger the following button but went straight to form submission.) – Neil – 2017-02-19T08:51:28.623

4

MATL, 16 bytes

"@&htDTT5hX@)&Xx

Try it at MATL Online!

Explanation

"        % Implicitly input string. For each char of it
  @      %   Push current char
  &h     %   Concatenate everything so far into a string
  tD     %   Duplicate and display
  TT5h   %   Push array [1 1 5]
  X@)    %   Get the k-th element modularly, where k is current iteration.
         %   So this gives 1, 1, 5 cyclically
  &Xx    %   Pause for that many tenths of a second and clear screen
         % Implicit end. Implicitly display the final string, again (screen
         % was deleted at the end of the last iteration)

Luis Mendo

Posted 2017-02-18T09:12:39.140

Reputation: 87 464

4

Noodel, 18 bytes

ʋ115ṡḶƙÞṡạḌ100.ṡ€ß

Try it:)


How it works

                   # Input is automatically pushed to the stack.
ʋ                  # Vectorize the string into an array of characters.
 115               # Push on the string literal "115" to be used to create the delays.
    ṡ              # Swap the two items on the stack.

     ḶƙÞṡạḌ100.ṡ€  # The main loop for the animation.
     Ḷ             # Loops the following code based off of the length of the string.
      ƙ            # Push on the current iteration's element of the character array (essentially a foreach).
       Þ           # Pop off of the stack and push to the screen.
        ṡ          # Swap the string "115" and he array of characters (this is done because need array of characters on the top for the loop to know how many times to loop)
         ạ         # Grab the next character in the string "115" (essentially a natural animation cmd that every time called on the same object will access the next item looping)
                   # Also, turns the string into an array of characters.
          Ḍ100.    # Pop the character off and convert to a number then multiply by 100 to get the correct delay. Then delay for that many ms.
               ṡ   # Swap the items again to compensate for the one earlier.
                €  # The end of the loop.

                 ß # Clears the screen such that when implicit popping of the stack occurs it will display the correct output.

19 byte code snippet that loops endlessly.

<div id="noodel" cols="30" rows="2" code="ʋ115ṡḷḶƙÞṡạḌ100.ṡ€ß" input='"Hello, PPCG! Goodbye Earth!"'/>
<script src="https://tkellehe.github.io/noodel/release/noodel-2.5.js"></script>
<script src="https://tkellehe.github.io/noodel/ppcg.min.js"></script>

tkellehe

Posted 2017-02-18T09:12:39.140

Reputation: 605

1For some reason, the delay seems off. The delay is 100ms, 100ms, 500ms. You seem to have 100ms all the time. – Ismael Miguel – 2017-02-19T20:23:20.957

@IsmaelMiguel Good eye. After looking through the source there is an add instead of a multiply. I might keep it that way though in case I need that because I could see where it might be useful. Thanks a lot for that! – tkellehe – 2017-02-20T02:39:26.063

You're welcome. And I'm sorry that your byte count increased. – Ismael Miguel – 2017-02-20T09:08:33.817

@IsmaelMiguel, it's fine because when I make the next version of Noodel I can make an 11 byte solution (because of basics I need to add). It will obviously be noncompeting, but this is a new language and has a long ways to go before it is as good as some of the top golfing languages:) – tkellehe – 2017-02-20T10:58:20.550

3

C#, 131 bytes

Not much to explain. It just takes a string (wrapped in "") as argument and prints each character using the correct delay pattern. After the animation it exits with an OutOfRangeException because the loop doesn't stop after it looped over all characters. Since it's an infinite loop, that also means I can use int Main instead of void Main ;-)

Golfed

class C{static int Main(string[]a){for(int i=0;){System.Console.Write(a[0][i]);System.Threading.Thread.Sleep(i++%3<1?500:100);}}}

Ungolfed

class C
{
    static int Main(string[] a)
    {
        for (int i = 0; ;)
        {
            System.Console.Write(a[0][i]);
            System.Threading.Thread.Sleep(i++ % 3 < 1 ? 500 : 100);
        }
    }
}

Edits

  • Saved 1 byte by moving incrementing i inside of the Sleep() method instead of in the for loop. (Thanks Maliafo)

Metoniem

Posted 2017-02-18T09:12:39.140

Reputation: 387

1I'm not a C# programmer, but can't you do something like Sleep(i++ [...]) to save an extra byte in the for loop ? – Maliafo – 2017-02-19T22:43:05.500

@Maliafo You might be right! I'll run it to make sure if it still runs correctly and then update my post. Thanks! – Metoniem – 2017-02-20T08:22:43.707

3

APL, 23 bytes

⊢{⍞←⍺⊣⎕DL⍵÷10}¨1 1 5⍴⍨⍴

Explanation:

               1 1 5⍴⍨⍴  ⍝ repeat the values [1,1,5] to match the input length
⊢                        ⍝ the input itself
 {           }¨          ⍝ pairwise map
      ⎕DL⍵÷10            ⍝ wait ⍵÷10 seconds, where ⍵ is the number
     ⊣                   ⍝ ignore that value, and
  ⍞←⍺                    ⍝ output the character   

marinus

Posted 2017-02-18T09:12:39.140

Reputation: 30 224

2

SmileBASIC, 61 bytes

LINPUT S$FOR I=0TO LEN(S$)-1?S$[I];
WAIT 6+24*(I MOD 3>1)NEXT

I think the delay calculation could be a lot shorter.

12Me21

Posted 2017-02-18T09:12:39.140

Reputation: 6 110

2

Python 3, 83 75 bytes

import time;i=0
for c in input():i+=1;print(end=c);time.sleep(i%3and.1or.5)

Try it online!

ovs

Posted 2017-02-18T09:12:39.140

Reputation: 21 408

1

This doesn't work on TIO. Do it here. On repl.it, you don't even need ,flush=1.

– mbomb007 – 2017-02-20T15:17:55.417

2

Clojure, 81 bytes

#(doseq[[c d](map vector %(cycle[100 100 500]))](Thread/sleep d)(print c)(flush))

Loops over the input string zipped with a infinite list of [100 100 500].

(defn typer [input]
  ; (map vector... is generally how you zip lists in Clojure 
  (doseq [[chr delay] (map vector input (cycle [100 100 500]))]
    (Thread/sleep delay)
    (print chr) (flush)))

Carcigenicate

Posted 2017-02-18T09:12:39.140

Reputation: 3 295

2

Bash (+utilities), 32 byte

Note, this will beep in the process, but who said submissions can not have fancy sound effects !

Golfed

sed 's/.../&\a\a\a\a/g'|pv -qL10

Demo

enter image description here

zeppelin

Posted 2017-02-18T09:12:39.140

Reputation: 7 884

1

Powershell, 66 65 63 Bytes

[char[]]$args|%{sleep -m((1,1,5)[++$i%3]*100);Write-Host $_ -N}

enter image description here

-1 removed unneeded white space after -m

-2 thanks to AdmBorkBork - used 1,1,5 and * end result by 100 instead of using 100,100,500

takes $args as a char array, loops through sleeping as specified, Write-Host with the -NoNewline argument is used to write the chars out on the same line.

Improvements?

  • use [0..99] instead of [char[]] to save 1 byte, but wont work on strings over 100 chars.
  • use 100,500 and [(++$i%3)-gt1] but make it shorter somehow.
  • combine it into a single string and clear between outputs, eliminating the long Write-Host

can't find any way to make the last two work, and the first one isn't valid by any particular rule.

colsw

Posted 2017-02-18T09:12:39.140

Reputation: 3 195

1Break out the hundred to save two bytes -- sleep -m((1,1,5)[++$i%3]*100) – AdmBorkBork – 2017-02-20T13:49:26.137

@AdmBorkBork smart one - thanks! – colsw – 2017-02-20T15:04:35.660

0

Processing, 133 131 bytes

int i;void setup(){for(String c:String.join("",args).split(""))p{try{Thread.sleep(i++%3<1?500:100);}catch(Exception e){}print(c);}}

I tried doing args[0] and wrapping the argument in "" instead, but it does not work for some reason.

Anyways... this is the first time I've written a Processing program that takes arguments. Unlike Java, you don't need to declare the arguments using String[]args, but the variable args will automatically be initialised to the arguments.

Put it in a file called sketch_name.pde under a folder called sketch_name (yes, same name for folder and sketch). Call it like:

processing-java --sketch=/full/path/to/sketch/folder --run input text here

cheese

user41805

Posted 2017-02-18T09:12:39.140

Reputation: 16 320

0

Perl, 63 bytes

foreach(split//,pop){$|=++$i;print;select('','','',$i%3?.1:.5)}

tourdetour

Posted 2017-02-18T09:12:39.140

Reputation: 31

0

Python 3, 88 Bytes

import time;s=''
for x in input():s+=x;time.sleep(.1+.4*(len(s)%3==0));print('\n'*25+s)

Tristan Batchler

Posted 2017-02-18T09:12:39.140

Reputation: 121

0

Rebol, 65 bytes

s: input t:[.1 .1 .5]forall s[prin s/1 wait last append t take t]

Ungolfed:

s: input
t: [.1 .1 .5]

forall s [
    prin s/1
    wait last append t take t
]

draegtun

Posted 2017-02-18T09:12:39.140

Reputation: 1 592

0

Bash + coreutils, 57 bytes

for((;k<${#1};k++)){ echo -n ${1:k:1};sleep .$[2&k%3|1];}

Mitchell Spector

Posted 2017-02-18T09:12:39.140

Reputation: 3 392

0

Java 7, 151 149 bytes

class M{public static void main(String[]a)throws Exception{int n=0;for(String c:a[0].split("")){System.out.print(c);Thread.sleep(n++%3>0?100:500);}}}

-2 bytes thanks to @KritixiLithos for something I always forget..

Explanation:

class M{
  public static void main(String[] a) throws Exception{ // throws Exception is required due to the Thread.sleep
    int n = 0;                                          // Initialize counter (and set to 0)
    for(String c : a[0].split("")){                     // Loop over the characters of the input
      System.out.print(c);                              // Print the character
      Thread.sleep(n++ % 3 > 0 ?                        // if (n modulo 3 != 0)
                                 100                    //   Use 100 ms
                               :                        // else (n modulo 3 == 0):
                                 500);                  //   Use 500 ms
    }
  }
}

Usage:

java -jar M.jar "Hello, PPCG! Goodbye Earth!"

Kevin Cruijssen

Posted 2017-02-18T09:12:39.140

Reputation: 67 575

1I haven't tested it, but can you do something like a[0].split("") instead? – user41805 – 2017-02-20T16:49:22.603

@KritixiLithos Argg.. I always forget that one. Thanks. – Kevin Cruijssen – 2017-02-20T18:12:41.453

Speaking about which, I should also use split in my Processing answer... – user41805 – 2017-02-20T18:14:29.097