Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

If you are unfamiliar with hacker typer, see In short, it is a program that outputs one chunk of a code base per keystroke for comedic effect. BUT, the version is far too easy to implement. It simply outputs three characters at a time from an arbitrary piece of code. For this challenge, a program must output its own source code, and print one space delimited chunk of code per keystroke.


  • One cannot hard code a file name for the program; it must determine its name dynamically. If the program compiles to an executable, it may append the standard file extension to the name of the executable (excluding the .exe if using Windows) and assume that the source file is within the executable's directory. For example, if a C executable is named "hacker", it should pull its source code from a file named "hacker.c" in its same directory. If a compiled program has an extension, it should be dropped before determining the name of its source code ("typer.exe" -> "typer.cs").
  • Programs must contain at least 5 spaces, with at least one character between each space. This means that the smallest possible size for this challenge is 9 bytes. The spaces do not have to be crucial to the functioning of the program.
  • Any formatting (indentation, new lines, etc.) must be maintained in the output. This formatting may either be printed with the code that proceeds it or follows it, what matters is that the formatting be maintained.
  • Avoid using comments to satisfy the 5 space requirement unless there is no other way to implement the spaces in your language of choice.

EDIT: New lines can be used in place of, or in addition to, spaces as chunk separators.

share|improve this question
I'm a little confused. Should the program be a quine, or not? – Orby Sep 5 '14 at 4:24
The way you've described it makes it sound as if its acceptable to read the code from the original source file, which would not be a quine. I think it would be a better contest if the program had to be an actual quine. – Orby Sep 5 '14 at 4:32
@Orby I'd say the program is not a quine in the traditional sense, regardless of if reading the source is allowed or not. Quines don't have input but these programs clearly do. – Helka Homba Sep 5 '14 at 5:14
@DrJPepper Your third bullet point makes it sound like any sequence of whitespace counts as a delimiter but you specifically say that only space is. Can you clarify? – Helka Homba Sep 5 '14 at 5:15
This challenge encourages reading of the program's own source code, a practice typically verboten in the construction of quines. – feersum Sep 5 '14 at 13:01

18 Answers 18

up vote 13 down vote accepted

bash, 51 58

for w in $(<$0);do read -sn 1;printf -- "$w ";done
share|improve this answer
It's bash, not shell: This won't work under dash, (2: read: Illegal option -s) – F. Hauri Sep 6 '14 at 20:19
Assuming bash, can replace cat $0 and tildes with $(<$0) – BroSlow Sep 7 '14 at 1:04
@broslow thx for feedback; labelled bash, same length – Will Sep 8 '14 at 5:13
@Will No problem. Is the IFS=\ actually needed if you omit the shebang? Default IFS is something like IFS=$'\n\t ', and since you no longer have a newline, I don't think you need to limit it to just space. – BroSlow Sep 8 '14 at 6:44
for w in `<$0`;{ read \-sn1;printf $w\ ;} – jimmy23013 Jan 6 '15 at 11:14

HTML & JavaScript, 123

<head></head><body onload="s=(a=document.all)[i=0].innerHTML" onkeyup="a[2].textContent += s.split(/(?= )/)[i++%6]"></body>

This works similarly to hacker typer, but with its own source code. Let me know if I've misunderstood the rules.

And here's a styled version (170 characters):

<body style="background:#000;color:lime" onload="s=(a=document.all)[i=0].innerHTML" onkeyup="a[3].textContent+=s.split(/(?=\s)/)[i++%6]">

I've made a demo. It's modified because JS Bin adds a lot of extra code, but the general idea is the same.

share|improve this answer
I'd be surprised if this didn't render correctly without the <html> and <head> tags, and without a closing </body>. You'd be surprised how very forgiving all browsers are in this regard. – Will Sep 5 '14 at 17:46
@Will Thanks. The reason I included <head> was that the browser will add it if it's not there, so it will always get displayed. I forgot about <html> though. – grc Sep 6 '14 at 1:23

Perl + Term::ReadKey, 56 bytes


Thanks to ThisSuitIsBlackNot for the original inspiration, and to primo for suggesting open 0 and <0>.

Note that the newline after for is actually unnecessary, except that I need to include one extra newline somewhere to bring the whitespace count up to the specified minimum of five.

Also note that, like ThisSuitIsBlackNot's submission, this program requires the Term::ReadKey module from CPAN. On Debian / Ubuntu Linux, this module, if not already present, can be easily installed with the command sudo apt-get install libterm-readkey-perl.

Also, to save a few characters, this program does not restore the input mode to normal on exit, so you may find yourself unable to see what you're typing afterwards. Executing the shell command stty sane or reset should fix that. This issue could be fixed, at the cost of 10 extra bytes, with:


Bonus: Pure quine, 81 bytes


Again, the newline after the comma is only needed to meet the five whitespace minimum.

Unlike the 56-byte program above, this version doesn't actually need to read its own source code, since it's based on a quine — specifically, on this quine:


The nice thing about this quine is that it can easily carry an arbitrary "payload" within the q{ } block, without having to repeat it. While it can't quite beat <0> in shortness, it does get pretty close.

Note: This program uses the Perl 5.10+ say feature, and thus needs to be invoked with the -M5.010 (or -E) command line switch. Per established consensus on meta, such switches used to enable modern language features do not count as extra characters. The shortest solution I can find without say is 83 bytes:


Both of these can also be made more terminal-friendly by (joining the last two lines and) inserting:


before the last }.

share|improve this answer
Wow. Just wow. Very cool. – ThisSuitIsBlackNot Sep 6 '14 at 5:38
+1, but I recommend to have the habit to type stty sane instead of reset (which could, on some os, sometimes be doing something more than just resetting some terminal parameters ^^) – Olivier Dulac Sep 6 '14 at 8:44
Very nice solution. FWIW, open F,$0 and <F> could be replaced with open 0 and <0>. Also, I would argue that one post in meta doesn't really constitute a consensus. The option -M5.01 doesn't "bring the language to a specific point", as the author suggests, it enables features. There is no version of perl for which these features are enabled by default. – primo Sep 7 '14 at 7:01
@primo: Please do post your own answer to the meta thread, if you disagree with the existing one. The fact that nobody's done so in three and a half years, so far, does suggest a reasonable degree of consensus, at least among the regulars here who actively visit meta, but consensus can always change. (Anyway, the way I see it, if ruby golfscript.rb counts as a valid command to run a program written in GolfScript, then perl -M5.010 should count as a valid command to run a program written in "Perl 5.10". But such arguments really belong on meta, not here.) – Ilmari Karonen Sep 7 '14 at 7:28

Python 3 - 124 bytes - 7 spaces


from curses import*
for x in open(__file__).read().split(" "):s.getch();s.addstr(x+" ")


from curses import*
# init curses
# split code into spaces
code = open(__file__).read().split(" ")
for x in code:
    # wait for keypress
    # print a bit
    screen.addstr(x+" ")
# deactivate curses

Styled version:

from curses import*
for x in open(__file__).read().split(" "):s.getch();s.addstr(x+" ",color_pair(2))
share|improve this answer

Ruby, 85, 71

require"io/console"; __FILE__;loop{STDIN.raw &:getc;print||exit}

Too bad that IO#raw is not part of the standard library.


require"io/console";24.times{|q|STDIN.raw &:getc;$><<$0,3,q*3)}

This one eliminates the call to Kernel#exit and uses global variables to shorten the code.

share|improve this answer

Befunge - 21

~ $ g , 1 +:54*`#@_:0

I'm fairly pleased with this, as I just found out about Befunge. If you don't mind "typing" into a popup window, you can run it here or here until I find a better online interpreter.

share|improve this answer

Python 3 - 299

a="""from curses import*
for x in e:
 s.addstr(x+' ')
""";b="""e=(a+'a=#%s#;b=#%s#;%s'%(a,b,b.replace('#','""''"',4))+'exec(a)').split(' ')
""";e=('a="""%s""";b="""%s""";%s'%(a,b,b.replace('#','""''"',4))+'exec(a)').split(' ')

Its a quine. Shortened from 507 by using exec and moving some statements around.

share|improve this answer

C, 211 186 bytes

My solution in C using the curses library. It may be longer than the other C solution, but it is a quine. Although not required by the question, it's still pretty nice. It also works quite nicely:

#define R(x)#x
#define T(x)R(x)
#define S(p)char*s="#define R(x)#x\n#define T(x)R(x)\n#define S(p)"p"\nS(T(S(p)))";main(){initscr();noecho();while(*s)if(~getch())addch(*s++);}

A more readable version with some comments and stuff:

#define R(x)#x /* macros to convert the source code in S into a C-string */
#define T(x)R(x)
#define S(p) char*s="#define R(x)#x\n" \
                    "#define T(x)R(x)\n" \
                    "#define S(p) " p "\n" \
        noecho(); /* don't echo input */ \
            if(~getch()) /*true if character has been typed */ \

compile with:

gcc -o h h.c -lncurses
share|improve this answer

C - 136 135 132 bytes (Windows only)

*fopen();**v;b[ 1<<20];main(p,q){v=q; strcpy(b,*v);strcat(b,".c") ;for(*v=fopen(b,"r");~fscanf(*v,"%s",b);printf("%s ",b))getch();} 

Note: there is a space at the end of the program, which probably won't show up.

I can't guarantee this program will work on a single computer other than my own as it is awesomely hacky. Things would have been a lot simpler back when everyone only had 32-bit machines. Then I would not need to worry about sizeof(int*) being 8 (which it definitely is; I printed it out to make sure) while sizeof(int) is 4.

Happily, the name of the executable is stored in the first string in argv. However, putting a pointer as an argument to a function means that I have to explicitly specify the type of ALL the arguments to the function--meaning I would have to type int twice--a huge waste of characters. Fortunately I found a workaround. I had the second argument to main, q, be just another int. Then assigning q to a variable of type int** somehow managed to grab all the necessary bytes from the stack.

I was unsuccessful in finding any such tricks to interpret the return type of fopen as a pointer without declaring the function.

Edit: Noticed I should use ~fscanf(*v,"%s",b) instead of fscanf(*v,"%s",b)>0 since the return is -1 when EOF is reached.

share|improve this answer
This segfaults for me so I can't test it, but you should be able to declare a void pointer (void **v;) instead of prototyping fopen(). – Comintern Sep 6 '14 at 3:34
@Comintern this change didn't help me to correctly store the result of fopen. I don't see why substituting void for int should make a difference, as all pointers are the same size anyway. – feersum Sep 6 '14 at 4:11
Good point. Still shorter and more stable to just declare a pointer though - this actually runs for me: b[1<<20];main(int *c,char **v){strcpy(b,*v);strcat(b,".c");c=fopen(b,"r");for(;fscanf(c,"%s",b)>0;printf("%‌​s ",b))getch();} (I had to substitute getchar() for getch() though). – Comintern Sep 6 '14 at 4:42
@Comintern your code still crashes on my system, but nice job getting it to work. I guess it is like I said--each version of the program will run on 1 computer. – feersum Sep 6 '14 at 5:30
Why don't you use K&R prototypes? E.g. *fopen() instead of *fopen(a,b)? – FUZxxl Feb 17 '15 at 12:13

Powershell, 89

(gc $MyInvocation.MyCommand.Path).split(" ")|%{$l+="$_ ";write-host "$l";read-host ;cls}
share|improve this answer

Perl - 87 bytes

#!/usr/bin/perl -040
use Term::ReadKey;open F,$0;ReadMode 3;print''.<F>while ReadKey 0

I didn't see anything in the rules about what to do once the file has been read to the end, so it simply sits waiting for input after printing the last chunk.

share|improve this answer

node.js with LiveScript:

console.log <| require \fs .readFileSync __filename, encoding: \utf8

asynchronous version:

require \fs .readFile __filename, encoding: \utf8, -> console.log &1
share|improve this answer

Cobra - 147

class P
    def main
        while 1,for a in File.readLines(CobraCore.exePath[:-4]+'.cobra'),print if('[Console.readKey]'and (Console.cursorLeft=0)<1,a,'')*

CobraCore.exePath is so useful!

share|improve this answer

Javascript ES6, 154

Firefox 154:

(a= (i=1,b="(a= "+a+")()",s="") => {window.onkeydown=()=>{clear();i=b.indexOf(" ",i+1),d=b.slice(0,i<0?b.length:i);console.log(s+d);if(i<0){i=0,s+=d}}})()

Chrome 175:

( a= function (i,s){b="( a= "+a+")()";c=console,window.onkeydown=function(){c.clear();s=s||"",i=b.indexOf(" ",i+1),d=b.slice(0,i<0?b.length:i);c.log(s+d);if(i<0){i=0,s+=d}}})()

Both 274:

( a= function (i,s){b="( a= "+a+")()";c=console,window.onkeydown=function(){(clear)?clear():c.clear?c.clear():0;s=s||"",i=b.indexOf(" ",i+1),d=b.slice(0,i<0?b.length:i);c.log(s+d);if(i<0){i=0,s+=d}}})()

Ungolfed (chrome):

( a= function (i,s){        // starting index | undefined, output string
    b="( a= "+a+")()";      // get a string representation of the function
    window.onkeydown=function(){    // on each key down event
        c.clear();                  // clear the output 
        i=b.indexOf(" ",i+1);       // get the index of next space
        d=b.slice(0,i<0?b.length:i);// get the string part wanted
        c.log(s+d);                 // print the string
            i=0,                    // reset counters
            s+=d                    // adding the string to the main output

Has two versions, because Chrome does not handle arrow function and the console is not cleared with the same method

The Firefox one work with firebug, it seem that the default developer console can't be cleared from a script.

share|improve this answer
Did you miss the requirement that the user has to press random keys to get the output printed ? – Optimizer Jan 9 '15 at 17:03
sure !, gonna rewrite this. – Hacketo Jan 9 '15 at 17:05

Groovy - 379

import java.nio.file.*
Path p = Paths.get(System.getProperty("user.dir"))
DirectoryStream<Path> f = Files.newDirectoryStream(p,"*.groovy")
try{for(e in f){read(e.toAbsolutePath().toString())}}
catch(Exception e){ }

void read(String x){
    def s = new File(x).text
    for(e in s.replace("%n"," %n").split(" ")) 
        print e + " " 

Since there is no getch() or equivalent in Java and Java-esque languages like Groovy... basically my code doesn't handle keypresses. That's all :D

share|improve this answer

C, 248 characters

True quine

Only works in unix, in windows it would be implemented using _getch.

main(){char *p="main(){char *p=\"%s\",s[400];sprintf(s,p,p);system(\"stty raw\");for(p=s;*p!=0;putchar(*p++))getchar();system(\"stty cooked\");}",s[400];sprintf(s,p,p);system("stty raw");for(p=s;*p!=0;putchar(*p++))getchar();system("stty cooked");}
share|improve this answer

HTML and Javascript, 232 bytes

<body><script>var n=0;var f=function (){document.onkeypress=function(){document.body.innerHTML+=("&lt;body>&lt;script>var n=0;var f="+f.toString()+"f()&lt;/script>&lt;/body>").split(" ")[n]+" ";n++;}};f()</script></body>

The traditional Javascript quine, but modified.

JSFiddle here.

share|improve this answer


main = readFile __FILE__ >>= putStrLn
share|improve this answer

protected by ProgramFOX Feb 18 '15 at 16:19

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

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