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.

Stewie Griffin
46.8k16 gold badges137 silver badges304 bronze badges
asked Feb 18, 2017 at 9:12
\$\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\$ Commented Feb 18, 2017 at 18:26
  • \$\begingroup\$ Can we assume there is always input? \$\endgroup\$ Commented 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\$ Commented Feb 18, 2017 at 18:42
  • 2
    \$\begingroup\$ Should there be a delay before printing the first character? \$\endgroup\$ Commented Feb 18, 2017 at 18:45
  • 1
    \$\begingroup\$ It's that pattern yes @12Me21 \$\endgroup\$ Commented 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.

answered Feb 18, 2017 at 18:37
\$\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\$ Commented Feb 18, 2017 at 19:04
  • \$\begingroup\$ Replace 100000 with 1e5 to shave 3 bytes \$\endgroup\$ Commented 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\$ Commented Feb 19, 2017 at 7:32
  • \$\begingroup\$ @AbelTom For some reason, 1e5 doesn't work on my device \$\endgroup\$ Commented Feb 19, 2017 at 7:40
  • \$\begingroup\$ @KritixiLithos howcome? are you on Linux? \$\endgroup\$ Commented Feb 19, 2017 at 7:48
6
\$\begingroup\$

Jelly, 13 bytes

115D÷5ṁȮœS\@"

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

Verification

How it works

115D÷5ṁȮœS\@" Monadic link. Argument: s (string)
115 Set the return value to 115.
 D Decimal; yield [1, 1, 5].
 ÷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).
answered Feb 18, 2017 at 18:29
\$\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
answered Feb 19, 2017 at 9:37
\$\endgroup\$
1
  • \$\begingroup\$ Can you do printf instead of fprintf? It works on octave-online.net (but it's Octave and not Matlab) \$\endgroup\$ Commented 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>

answered Feb 18, 2017 at 19:13
\$\endgroup\$
5
  • \$\begingroup\$ The snippet doesn't seem to work \$\endgroup\$ Commented Feb 18, 2017 at 19:23
  • \$\begingroup\$ @KritixiLithos Yup, doesn't seem to work on Chrome :-( \$\endgroup\$ Commented Feb 18, 2017 at 19:25
  • \$\begingroup\$ works in firefox tho \$\endgroup\$ Commented 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\$ Commented 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\$ Commented 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...

answered Feb 18, 2017 at 17:31
\$\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\$ Commented Feb 18, 2017 at 23:43
  • \$\begingroup\$ Instead of undo can you just paste? Unsure if that helps at all though \$\endgroup\$ Commented 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\$ Commented 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\$ Commented 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>

answered Feb 19, 2017 at 5:38
\$\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\$ Commented 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\$ Commented Feb 20, 2017 at 2:39
  • \$\begingroup\$ You're welcome. And I'm sorry that your byte count increased. \$\endgroup\$ Commented 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\$ Commented 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)
Suever
11.2k1 gold badge24 silver badges52 bronze badges
answered Feb 19, 2017 at 4:07
\$\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 
answered Feb 19, 2017 at 6:26
\$\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)
answered Feb 18, 2017 at 18:51
\$\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\$ Commented 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\$ Commented 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.

answered Feb 18, 2017 at 18:41
\$\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)))
answered Feb 18, 2017 at 20:04
\$\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

answered Feb 19, 2017 at 20:37
\$\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!

answered Feb 18, 2017 at 19:08
\$\endgroup\$
1
  • 1
    \$\begingroup\$ This doesn't work on TIO. Do it here. On repl.it, you don't even need ,flush=1. \$\endgroup\$ Commented 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.

answered Feb 19, 2017 at 19:46
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Break out the hundred to save two bytes -- sleep -m((1,1,5)[++$i%3]*100) \$\endgroup\$ Commented Feb 20, 2017 at 13:49
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
]
answered Feb 19, 2017 at 15:42
\$\endgroup\$
0
\$\begingroup\$

Bash + coreutils, 57 bytes

for((;k<${#1};k++)){ echo -n ${1:k:1};sleep .$[2&k%3|1];}
answered Feb 20, 2017 at 8:57
\$\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!"
answered Feb 20, 2017 at 16:24
\$\endgroup\$
3
  • 1
    \$\begingroup\$ I haven't tested it, but can you do something like a[0].split("") instead? \$\endgroup\$ Commented Feb 20, 2017 at 16:49
  • \$\begingroup\$ @KritixiLithos Argg.. I always forget that one. Thanks. \$\endgroup\$ Commented Feb 20, 2017 at 18:12
  • \$\begingroup\$ Speaking about which, I should also use split in my Processing answer... \$\endgroup\$ Commented 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

answered Feb 19, 2017 at 11:38
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.