14
\$\begingroup\$

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.

\$\endgroup\$
8
  • \$\begingroup\$ "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.) \$\endgroup\$ Feb 18, 2017 at 18:26
  • \$\begingroup\$ Can we assume there is always input? \$\endgroup\$
    – Metoniem
    Feb 18, 2017 at 18:39
  • 1
    \$\begingroup\$ Is the delay supposed to be random, or a repeating pattern of 0.1, 0.1, 0.5? \$\endgroup\$
    – 12Me21
    Feb 18, 2017 at 18:42
  • 2
    \$\begingroup\$ Should there be a delay before printing the first character? \$\endgroup\$
    – user41805
    Feb 18, 2017 at 18:45
  • 1
    \$\begingroup\$ It's that pattern yes @12Me21 \$\endgroup\$
    – Metoniem
    Feb 18, 2017 at 18:47

20 Answers 20

8
\$\begingroup\$

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.

\$\endgroup\$
14
  • 1
    \$\begingroup\$ Wether you use my improvements or not: Your delays should be the other way around. if i%3 the delay should be 5. \$\endgroup\$
    – Metoniem
    Feb 18, 2017 at 19:04
  • \$\begingroup\$ Replace 100000 with 1e5 to shave 3 bytes \$\endgroup\$ Feb 19, 2017 at 4:08
  • \$\begingroup\$ @AlbertRenshaw Thanks for the tip, updated. I have used it in some of my other solutions too don't know why I forgot here. \$\endgroup\$
    – Abel Tom
    Feb 19, 2017 at 7:32
  • \$\begingroup\$ @AbelTom For some reason, 1e5 doesn't work on my device \$\endgroup\$
    – user41805
    Feb 19, 2017 at 7:40
  • \$\begingroup\$ @KritixiLithos howcome? are you on Linux? \$\endgroup\$
    – Abel Tom
    Feb 19, 2017 at 7:48
6
\$\begingroup\$

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).
\$\endgroup\$
6
\$\begingroup\$

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
\$\endgroup\$
1
  • \$\begingroup\$ Can you do printf instead of fprintf? It works on octave-online.net (but it's Octave and not Matlab) \$\endgroup\$
    – user41805
    Feb 19, 2017 at 11:58
4
\$\begingroup\$

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>

\$\endgroup\$
5
  • \$\begingroup\$ The snippet doesn't seem to work \$\endgroup\$
    – user41805
    Feb 18, 2017 at 19:23
  • \$\begingroup\$ @KritixiLithos Yup, doesn't seem to work on Chrome :-( \$\endgroup\$
    – Metoniem
    Feb 18, 2017 at 19:25
  • \$\begingroup\$ works in firefox tho \$\endgroup\$ Feb 19, 2017 at 1:40
  • 2
    \$\begingroup\$ It 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. \$\endgroup\$ Feb 19, 2017 at 1:41
  • \$\begingroup\$ @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.) \$\endgroup\$
    – Neil
    Feb 19, 2017 at 8:51
4
\$\begingroup\$

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

\$\endgroup\$
4
  • \$\begingroup\$ without a count defaults to 500 ms, so you can save a byte there. Also, remember that you don't need the second ò! \$\endgroup\$
    – DJMcMayhem
    Feb 18, 2017 at 23:43
  • \$\begingroup\$ Instead of undo can you just paste? Unsure if that helps at all though \$\endgroup\$
    – nmjcman101
    Feb 19, 2017 at 1:45
  • \$\begingroup\$ @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. \$\endgroup\$
    – user41805
    Feb 19, 2017 at 7:16
  • \$\begingroup\$ @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 \$\endgroup\$
    – user41805
    Feb 19, 2017 at 7:19
4
\$\begingroup\$

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>

\$\endgroup\$
4
  • 1
    \$\begingroup\$ For some reason, the delay seems off. The delay is 100ms, 100ms, 500ms. You seem to have 100ms all the time. \$\endgroup\$ Feb 19, 2017 at 20:23
  • \$\begingroup\$ @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! \$\endgroup\$
    – tkellehe
    Feb 20, 2017 at 2:39
  • \$\begingroup\$ You're welcome. And I'm sorry that your byte count increased. \$\endgroup\$ Feb 20, 2017 at 9:08
  • \$\begingroup\$ @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:) \$\endgroup\$
    – tkellehe
    Feb 20, 2017 at 10:58
4
\$\begingroup\$

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)
\$\endgroup\$
3
\$\begingroup\$

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   
\$\endgroup\$
3
\$\begingroup\$

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)
\$\endgroup\$
2
  • 1
    \$\begingroup\$ I'm not a C# programmer, but can't you do something like Sleep(i++ [...]) to save an extra byte in the for loop ? \$\endgroup\$
    – Maliafo
    Feb 19, 2017 at 22:43
  • \$\begingroup\$ @Maliafo You might be right! I'll run it to make sure if it still runs correctly and then update my post. Thanks! \$\endgroup\$
    – Metoniem
    Feb 20, 2017 at 8:22
2
\$\begingroup\$

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.

\$\endgroup\$
2
\$\begingroup\$

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)))
\$\endgroup\$
2
\$\begingroup\$

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

\$\endgroup\$
2
\$\begingroup\$

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!

\$\endgroup\$
1
  • 1
    \$\begingroup\$ This doesn't work on TIO. Do it here. On repl.it, you don't even need ,flush=1. \$\endgroup\$
    – mbomb007
    Feb 20, 2017 at 15:17
1
\$\begingroup\$

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.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Break out the hundred to save two bytes -- sleep -m((1,1,5)[++$i%3]*100) \$\endgroup\$ Feb 20, 2017 at 13:49
  • \$\begingroup\$ @AdmBorkBork smart one - thanks! \$\endgroup\$
    – colsw
    Feb 20, 2017 at 15:04
0
\$\begingroup\$

Perl, 63 bytes

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

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)
\$\endgroup\$
0
\$\begingroup\$

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
]
\$\endgroup\$
0
\$\begingroup\$

Bash + coreutils, 57 bytes

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

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!"
\$\endgroup\$
3
  • 1
    \$\begingroup\$ I haven't tested it, but can you do something like a[0].split("") instead? \$\endgroup\$
    – user41805
    Feb 20, 2017 at 16:49
  • \$\begingroup\$ @KritixiLithos Argg.. I always forget that one. Thanks. \$\endgroup\$ Feb 20, 2017 at 18:12
  • \$\begingroup\$ Speaking about which, I should also use split in my Processing answer... \$\endgroup\$
    – user41805
    Feb 20, 2017 at 18:14
0
\$\begingroup\$

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

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.