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):
Since this is code golf, the smallest amount of bytes win.
-
\$\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\$Jonathan Allan– Jonathan Allan2017年02月18日 18:26:13 +00:00Commented Feb 18, 2017 at 18:26
-
\$\begingroup\$ Can we assume there is always input? \$\endgroup\$Mika– Mika2017年02月18日 18:39:37 +00:00Commented 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– 12Me212017年02月18日 18:42:17 +00:00Commented Feb 18, 2017 at 18:42
-
2\$\begingroup\$ Should there be a delay before printing the first character? \$\endgroup\$user41805– user418052017年02月18日 18:45:31 +00:00Commented Feb 18, 2017 at 18:45
-
1\$\begingroup\$ It's that pattern yes @12Me21 \$\endgroup\$Mika– Mika2017年02月18日 18:47:22 +00:00Commented Feb 18, 2017 at 18:47
20 Answers 20
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.
-
1\$\begingroup\$ Wether you use my improvements or not: Your delays should be the other way around. if
i%3the delay should be 5. \$\endgroup\$Mika– Mika2017年02月18日 19:04:17 +00:00Commented Feb 18, 2017 at 19:04 -
\$\begingroup\$ Replace
100000with1e5to shave 3 bytes \$\endgroup\$Albert Renshaw– Albert Renshaw2017年02月19日 04:08:49 +00:00Commented 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– Abel Tom2017年02月19日 07:32:44 +00:00Commented Feb 19, 2017 at 7:32
-
\$\begingroup\$ @AbelTom For some reason,
1e5doesn't work on my device \$\endgroup\$user41805– user418052017年02月19日 07:40:30 +00:00Commented Feb 19, 2017 at 7:40 -
\$\begingroup\$ @KritixiLithos howcome? are you on Linux? \$\endgroup\$Abel Tom– Abel Tom2017年02月19日 07:48:02 +00:00Commented Feb 19, 2017 at 7:48
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).
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
-
\$\begingroup\$ Can you do
printfinstead offprintf? It works on octave-online.net (but it's Octave and not Matlab) \$\endgroup\$user41805– user418052017年02月19日 11:58:01 +00:00Commented Feb 19, 2017 at 11:58
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>
-
\$\begingroup\$ The snippet doesn't seem to work \$\endgroup\$user41805– user418052017年02月18日 19:23:33 +00:00Commented Feb 18, 2017 at 19:23
-
\$\begingroup\$ @KritixiLithos Yup, doesn't seem to work on Chrome :-( \$\endgroup\$Mika– Mika2017年02月18日 19:25:43 +00:00Commented Feb 18, 2017 at 19:25
-
\$\begingroup\$ works in firefox tho \$\endgroup\$Conor O'Brien– Conor O'Brien2017年02月19日 01:40:58 +00:00Commented 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\$numbermaniac– numbermaniac2017年02月19日 01:41:54 +00:00Commented 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– Neil2017年02月19日 08:51:28 +00:00Commented Feb 19, 2017 at 8:51
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...
-
\$\begingroup\$
gÓ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– DJMcMayhem2017年02月18日 23:43:49 +00:00Commented Feb 18, 2017 at 23:43 -
\$\begingroup\$ Instead of
undo can you justpaste? Unsure if that helps at all though \$\endgroup\$nmjcman101– nmjcman1012017年02月19日 01:45:37 +00:00Commented 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– user418052017年02月19日 07:16:06 +00:00Commented 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– user418052017年02月19日 07:19:47 +00:00Commented Feb 19, 2017 at 7:19
Noodel, 18 bytes
ʋ115ṡḶƙÞṡạḌ100.ṡ€ß
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>
-
1\$\begingroup\$ For some reason, the delay seems off. The delay is 100ms, 100ms, 500ms. You seem to have 100ms all the time. \$\endgroup\$Ismael Miguel– Ismael Miguel2017年02月19日 20:23:20 +00:00Commented 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– tkellehe2017年02月20日 02:39:26 +00:00Commented Feb 20, 2017 at 2:39
-
\$\begingroup\$ You're welcome. And I'm sorry that your byte count increased. \$\endgroup\$Ismael Miguel– Ismael Miguel2017年02月20日 09:08:33 +00:00Commented 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– tkellehe2017年02月20日 10:58:20 +00:00Commented Feb 20, 2017 at 10:58
MATL, 16 bytes
"@&htDTT5hX@)&Xx
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)
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
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
iinside of theSleep()method instead of in theforloop. (Thanks Maliafo)
-
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– Maliafo2017年02月19日 22:43:05 +00:00Commented 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\$Mika– Mika2017年02月20日 08:22:43 +00:00Commented Feb 20, 2017 at 8:22
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.
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)))
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
Powershell, (削除) 66 (削除ここまで) (削除) 65 (削除ここまで) 63 Bytes
[char[]]$args|%{sleep -m((1,1,5)[++$i%3]*100);Write-Host $_ -N}
-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,500and[(++$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.
-
1\$\begingroup\$ Break out the hundred to save two bytes --
sleep -m((1,1,5)[++$i%3]*100)\$\endgroup\$AdmBorkBork– AdmBorkBork2017年02月20日 13:49:26 +00:00Commented Feb 20, 2017 at 13:49
Perl, 63 bytes
foreach(split//,pop){$|=++$i;print;select('','','',$i%3?.1:.5)}
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)
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
]
Bash + coreutils, 57 bytes
for((;k<${#1};k++)){ echo -n ${1:k:1};sleep .$[2&k%3|1];}
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!"
-
1\$\begingroup\$ I haven't tested it, but can you do something like
a[0].split("")instead? \$\endgroup\$user41805– user418052017年02月20日 16:49:22 +00:00Commented Feb 20, 2017 at 16:49 -
\$\begingroup\$ @KritixiLithos Argg.. I always forget that one. Thanks. \$\endgroup\$Kevin Cruijssen– Kevin Cruijssen2017年02月20日 18:12:41 +00:00Commented Feb 20, 2017 at 18:12
-
\$\begingroup\$ Speaking about which, I should also use
splitin my Processing answer... \$\endgroup\$user41805– user418052017年02月20日 18:14:29 +00:00Commented Feb 20, 2017 at 18:14
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