# Create a “hacker typer” program that renders its own source code

If you are unfamiliar with hacker typer, see hackertyper.net. In short, it is a program that outputs one chunk of a code base per keystroke for comedic effect. BUT, the hackertyper.net 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.

## Details

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

• 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. – Calvin's Hobbies 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? – Calvin's Hobbies 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

### bash, 51 58

for w in $(<$0);do read -sn 1;printf -- "$w ";done  • 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) – user30335 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. – user30335 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): <head></head> <body style="background:#000;color:lime" onload="s=(a=document.all)[i=0].innerHTML" onkeyup="a[3].textContent+=s.split(/(?=\s)/)[i++%6]"> <pre></pre></body>  I've made a demo. It's modified because JS Bin adds a lot of extra code, but the general idea is the same. • 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 use Term'ReadKey;ReadMode 4;open 0;ReadKey,print for <0>  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: use Term'ReadKey;ReadMode 4;open 0;ReadKey,print for<0>;ReadMode 0  ## Bonus: Pure quine, 81 bytes $_=q{use
for
split$/, "$_=q{_};eval"};eval  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: _=q{say"$_=q{$_};eval"};eval


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:

$_=q{use Term'ReadKey;ReadMode 4;ReadKey,print for split/^/, "\$_=q{$_};eval"};eval  Both of these can also be made more terminal-friendly by (joining the last two lines and) inserting: ;ReadMode 0  before the last }. • 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 foo.gs counts as a valid command to run a program written in GolfScript, then perl -M5.010 foo.pl 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

Code:

from curses import*
s=initscr();noecho()
echo();endwin()


Ungolfed:

from curses import*
# init curses
screen=initscr()
noecho()
# split code into spaces
for x in code:
# wait for keypress
screen.getch()
# print a bit
# deactivate curses
echo()
endwin()


Styled version:

from curses import*
s=initscr();noecho();start_color();init_pair(2,COLOR_GREEN,COLOR_BLACK)
echo();endwin()


# Ruby, 85, 71

require"io/console";f=File.open __FILE__;loop{STDIN.raw &:getc;print f.read(3)||exit}


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

### Improvement

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


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

# 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. ## Powershell, 89 (gc$MyInvocation.MyCommand.Path).split(" ")|%{$l+="$_ ";write-host "$l";read-host ;cls}  ## Python 3 - 299 a="""from curses import* s=initscr() raw() noecho() for x in e: s.getch() s.addstr(x+' ') nocbreak() echo() endwin() """;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(' ') exec(a)  Its a quine. Shortened from 507 by using exec and moving some statements around. # 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++);} S(T(S(p)))  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" \ "S(T(S(p)))";\ main(){\ initscr();\ noecho(); /* don't echo input */ \ while(*s)\ if(~getch()) /*true if character has been typed */ \ addch(*s++);\ } S(T(S(p)))  compile with: gcc -o h h.c -lncurses  # 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. • 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 # 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.

node.js with LiveScript:

#!/usr/local/bin/lsc
console.log <| require \fs .readFileSync __filename, encoding: \utf8


asynchronous version:

#!/usr/local/bin/lsc
require \fs .readFile __filename, encoding: \utf8, -> console.log &1


# Cobra - 147

class P
def main


CobraCore.exePath is so useful!

# 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
c=console,
window.onkeydown=function(){    // on each key down event
c.clear();                  // clear the output
s=s||"";
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
if(i<0){
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.

• 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")
catch(Exception e){ }
finally{f.close()}

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

## 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");}


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

# SmileBASIC, 79 75 bytes

LOAD"PRG1:"+PRGNAME$() PRGEDIT 1 @L IF BUTTON(2)THEN?PRGGET$();
WAIT
GOTO@L


It's very easy to get a specific LINE of a program in SmileBASIC, so I just put the spaces before each line break. I thought I was so clever, putting the spaces before each line break, but apparently we're allowed to use line breaks instead of spaces...

Explanation:

LOAD "PRG1:"+PRGNAME$() 'load the code into slot 1 so we can easily read 1 line at a time PRGEDIT 1 'Edit slot 1 @LOOP IF BUTTON(2) THEN 'When a button is pressed... PRINT PRGGET$(); 'get a line of code and print it
WAIT 'delay so we don't detect the same press multiple times in a single frame.
GOTO @LOOP


{-# LANGUAGE CPP #-}
`