Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

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.

share|improve this question
1  
I'm a little confused. Should the program be a quine, or not? –  Orby Sep 5 at 4:24
5  
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 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 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 at 5:15
1  
This challenge encourages reading of the program's own source code, a practice typically verboten in the construction of quines. –  feersum Sep 5 at 13:01

13 Answers 13

up vote 13 down vote accepted

bash, 51 58

for w in $(<$0);do read -sn 1;printf -- "$w ";done
share|improve this answer
2  
It's bash, not shell: This won't work under dash, (2: read: Illegal option -s) –  F. Hauri Sep 6 at 20:19
1  
Assuming bash, can replace cat $0 and tildes with $(<$0) –  BroSlow Sep 7 at 1:04
    
@broslow thx for feedback; labelled bash, same length –  Will Sep 8 at 5:13
1  
@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 at 6:44
    
@BroSlow how on earth did I miss that? lol you really ought enter yourself ;) Thousand thanks –  Will Sep 8 at 6:50

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.

share|improve this answer
2  
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 at 17:46
1  
@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 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
Term'ReadKey;ReadMode
4;ReadKey,say
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 }.

share|improve this answer
    
Wow. Just wow. Very cool. –  ThisSuitIsBlackNot Sep 6 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 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 at 7:01
1  
@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 at 7:28

Python 3 - 124 bytes - 7 spaces


Code:

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

Ungolfed:

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

Styled version:

from curses import*
s=initscr();noecho();start_color();init_pair(2,COLOR_GREEN,COLOR_BLACK)
for x in open(__file__).read().split(" "):s.getch();s.addstr(x+" ",color_pair(2))
echo();endwin()
share|improve this answer

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.

share|improve this answer

C - 136 135 bytes

*fopen(x,y);**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. At least was able to use int instead of char* for the arguments.

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 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 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 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 at 5:30

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

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

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.

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

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){ }
finally{f.close()}

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

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

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
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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