An Interview Question That Prints Out Its Own Source Code (In Ruby)

by Alan Skorkin on March 17, 2010

A program that prints out its own source code (without reading in and outputting it's source file) is known as a quine. I've known about these things for years, but never really bothered trying to work it out. It requires thinking in a circular fashion which makes your head hurt :). However, a little while ago a realized that this would actually make a great programming interview question, so I thought I had better give this a crack, using Ruby – of course.

Why It's A Great Interview Question

Before we get to the Ruby quine hackery that I came up with, here is why I think it is a great question. You see, the good thing about this question is the fact that it is relatively small (doesn't take too much time) but at the same time it is not binary (i.e. not yes/no or knows/doesn't know or can do/can't do). Here is how I see it potentially panning out and what it means.

You ask the question, and they draw up an answer for you almost instantly without batting an eyelid.

  • Clearly they have heard of this before, which shows they have an interest and some involvement in the wider programming community.
  • Having heard of it they were sufficiently intrigued to dig further, which shows an interest and passion for their craft and a willingness to invest time and tackle interesting/challenging problems.
  • If they explain it with gusto and a twinkle in their eyes :), you can be pretty sure they solved it themselves rather than looking it up, which shows they can think creatively and are actually able to solve the problems they tackle.
  • If they muddle their way through it and/or can't really explain why/how something like their solution works, they probably looked it up rather than solving it themselves. This is not such a big deal, they have thought about it and can reproduce code they've seen and have a general understanding of how it works. Those are all good qualities.

Regardless, if you're here, then as far as this question is concerned, you have at least a decent and potentially very good candidate on your hands – a positive result.

You ask the question and they've clearly never heard of it before, but they're quickly able to arrive at a working solution.

  • You potentially have a closet superstar on your hands. They may not be as engaged in the community, since they haven't heard the question before, but this is probably because they spent the majority of time doing what they love – coding. You next job is to find out if this is infact so.

Regardless, solving this question off-the-bat like this is praise-worthy – a positive result.

You ask the question and they've never heard of it, can't come up with a solution, but are at least able to get towards the right track and can explain their thought process well and succinctly.

  • They're likely not a superstar, but they do have some reasoning skills and they are a decent communicator which means they are still potentially a solid developer.

It may not be as positive a result as you would like – but it is not a total failure and it does tell you what kind of role this person would be more suited for if you were to hire them.

You ask the question and they've never heard of it, can't solve it, and can't come up with anything logical and end up confusing themselves repeatedly.

You can probably guess what the deal is with this situation. Total fail, you can still ask a question or two for due diligence, but chances are you have a dud on your hands.

See what I mean about being able to get a lot of information about a person from such a little question. I know you guys are already awesome - since you're following this blog and if you're not you better start :) – and would ace this question anyway. But for academic purposes, here is what I came up with using Ruby.

A Ruby Quine

The first version I did looked like this:

def method;"def method;;end;puts method()[0, 11] + 34.chr + method + 34.chr + method()[11, method.length-11]";end;puts method()[0, 11] + 34.chr + method + 34.chr + method()[11, method.length-11]

Put it in a file and run it and we get the following output:

def method;"def method;;end;puts method()[0, 11] + 34.chr + method + 34.chr + method()[11, method.length-11]";end;puts method()[0, 11] + 34.chr + method + 34.chr + method()[11, method.length-11]

Perfect!

To things easier to understand, lets indent it a little bit (which will un-quinefy :) it, but doesn't matter for study purposes):

def method;
  "def method;;end;puts method()[0, 11] + 34.chr + method + 34.chr + method()[11, method.length-11]";
end;
 
puts method()[0, 11] + 34.chr + method + 34.chr + method()[11, method.length-11]

The way it works is as follows. As some point you need to have a string which will contain all the code before and after itself, but will obviously not contain itself. It doesn't really matter what you have before the string, but it does matter what you have after. You need to have repeated access to the string. You will then cut a substring from it which will be everything before the string itself. Following this, you need a quote (") then the string itself then another quote and then cut everything else out of the string that you hadn't cut before. You concatenate all this together and then output the whole thing. It makes it easier to have all of it on one line so you don't have to deal with spaces. I realize it is not the best explanation, but you really do need to spend a little bit of time and think through this yourself – you will get it for sure.

Last thing left to do was to make my quine a little shorter (apparently with quines, the shorter they are the better, or so I've heard). Here is what I got:

def s;"def s;;end;puts s()[0,6]+34.chr+s+34.chr+s()[6,s.length-6]";end;puts s()[0,6]+34.chr+s+34.chr+s()[6,s.length-6]

This can be made slightly shorter still, can you see how?

Here is a challenge if you're up for it. Try and come up with a quine in Ruby that will output its source formatted/indented, perhaps using a heredoc. Is it even possible? Either way it's good code kata.

If you can't be bothered coming up with your own solution there is a whole bunch of them in different languages on the quine page, (but no Ruby ones that I can see).

Well, there we go, now the only thing left is to ask yourself how you think you would go, if got this kind of question in an interview?

Image by Neil Crosby

{ 4 trackbacks }

Dew Drop – March 17, 2010 | Alvin Ashcraft's Morning Dew
March 18, 2010 at 2:01 am
Best of RubyFlow: 12 Ruby Links From March 2010 « Особое программирование
March 20, 2010 at 5:41 am
My Mother Would Be So Proud « Grumpy Old Programmer
March 25, 2010 at 11:52 pm
O Melhor do RubyFlow – 12 Links sobre Ruby de Março de 2010
April 15, 2010 at 11:02 pm

{ 70 comments… read them below or add one }

Brian Yamabe March 18, 2010 at 1:08 am

Thanks, I hadn’t heard of this and found it interesting. I’m somewhere between a developer and a programmer so I’ve now heard of it, I could explain the thought process, but I’ve got so many other programming tasks that I want to get done that it’s unlikely that I’ll dig any further.

Reply

Alan Skorkin March 18, 2010 at 9:49 am

Hi Brian,

I feel your pain, I have to constantly put interesting things on the back burner because there are so many more interesting things to look at.

Reply

Mike Woodhouse March 18, 2010 at 3:38 am

How about

puts File.read(__FILE__)

or

puts File.read($0)

Reply

Alan Skorkin March 18, 2010 at 10:01 am

Hi Mike,

Yeah, but I did say at the start that reading in the file is not allowed :), i.e.

“A program that prints out it’s own source code (without reading in and outputting it’s source file)”

Reply

Mike Woodhouse March 18, 2010 at 9:02 pm

Well, duh. I must be italic-blind.

Reply

Bill Sorensen March 18, 2010 at 5:19 am

I don’t think this is a best practice. See the following post on Eric Lippert’s blog:

http://blogs.msdn.com/ericlippert/archive/2010/03/01/attracting-talent.aspx

Search for “We used to do that at Microsoft” to see his comments about puzzle questions.

Reply

Alan Skorkin March 18, 2010 at 10:04 am

Hi Bill,

I do see your point, but this is not really a puzzle question. It is a legitimate coding problem, albeit a small one. It requires knowledge of the language you’re using, analytical skills etc. Plus being aware of ti helps which as I mentioned shows a level of involvement and interest in your profession.

Reply

Korny March 18, 2010 at 7:01 am

Of course, javascript would make this trivial…

Reply

Alan Skorkin March 18, 2010 at 10:05 am

That sounds intriguing. If you would like to whip one up quickly and post it, I’d love to see it.

Reply

lee doolan March 18, 2010 at 1:19 pm

lee@stjohn:~$ ruby q.rb
_=”_=%p;puts _%%_”;puts _%_

Reply

Alan Skorkin March 18, 2010 at 6:03 pm

Oh very nice, using string format, I didn’t even think of that, works a treat :)

Reply

lee doolan March 19, 2010 at 7:17 am

I agree with the others further down in this thread, that this does not make a very good interview question. In fact, I am opposed to any kind of coding activity during an interview.

I am curious, though, Alan. If you had asked your question in an interview and you had gotten a response similar to mine, what would you think? First, it does not use a method as your example does. Secondly, it is somewhat abstruse. I would bet that if you put this solution in front of most people thay would not get it until they looked up the meaning of the ‘%p’ format conversion, and possibly String#% as well.

Reply

Alan Skorkin March 19, 2010 at 10:23 pm

Hi Lee,

If you’re interviewing a developer I do believe that a coding component is important to have in an interview.

If you came up with this answer in an interview, I would view it in a generally positive light. If I already knew about the % operator in Ruby, that would be cool, but if not I would ask you to explain how it worked and if your explanation made sense and was coherent you would get bonus points for that as well.

Reply

Peter Donis March 18, 2010 at 1:25 pm

I’m not sure why it needs to be one line. In Python, at least, you can do a multi-line quine easily:

[code]
#!/usr/bin/env python
import os
lines = ['#!/usr/bin/env python', 'import os', 'lines = ', 'lines[2] += str(lines)', 'print os.linesep.join(lines)']
lines[2] += str(lines)
print os.linesep.join(lines)
[/code]

(Note that the line assigning the ‘lines’ variable is all one line; not sure how it will format.)

Reply

Alan Skorkin March 18, 2010 at 6:05 pm

He Peter,

I don’t believe they have to be one line, you can write a multiline quine in any language, including Ruby. It’s just that my ones happen to be one line :) and historically speaking I believe there has been a lot of emphasis on writing the shortest possible quines, hence the one line thing.

Reply

Matthew March 19, 2010 at 1:51 am

That’s pretty neat.

The ruby equivalent would be:

def quine;lines = ["def quine", "", "lines[1] = %q{lines = } + lines.inspect”, “puts lines.join(‘;’)”, “end”];lines[1] = %q{lines = } + lines.inspect;puts lines.join(‘;’);end

(and one line too!)

Reply

Alan Skorkin March 19, 2010 at 10:20 pm

I like this one :).

Reply

wes March 21, 2010 at 7:35 am

I disagree that this is one line! Using the semi-colon is the equivalent of writing another line of code.

Reply

Rich Collins March 18, 2010 at 2:21 pm

In Io from the repl:

thisMessage

from an executed file:

thisMessage println

Reply

Pant Darkin March 18, 2010 at 2:25 pm

No offense but that is a silly interview question.

Reply

Alan Skorkin March 18, 2010 at 6:09 pm

Hi Pant,

None taken. I don’t believe it is silly as I explained in the post. However even is the question you get asked in an interview is not to your liking it is surely worth having a decent answer for it. After all you’ll be damn lucky to ever get an interview where every question is something you would find awesome and fascinating. Unless you’re prepared to walk out of every interview where one of the questions is not palatable for some reason (which you may be), it won’t hurt being prepared for any contingency.

Plus it is an interesting concept regardless and lets you flex your thinking muscles a little bit, and that’s never a bad thing.

Reply

Stevie Graham March 18, 2010 at 4:09 pm

how about:

m=”m=;puts m[0,2]+34.chr+m+34.chr+m[2,m.length-2]“;puts m[0,2]+34.chr+m+34.chr+m[2,m.length-2]

Reply

Alan Skorkin March 18, 2010 at 6:11 pm

Hi Stevie,

Definitely, and if you count the actual characters rather than using (m.length – 2) it will be even shorter (but harder to understand). Still won’t be as short as the one given by lee doolan in the comments above :).

Reply

Michael Shapiro March 18, 2010 at 4:49 pm

I wish this counted, but DATA is a seeked File object. :(

$ cat a.rb
a = DATA.read
eval a
__END__
puts ‘a = DATA.read’
puts ‘eval a’
puts ‘__END__’
puts a

Reply

Alan Skorkin March 18, 2010 at 6:13 pm

Hi Michael,

Still interesting though.

Reply

James Sanders March 19, 2010 at 11:48 am

File objects are just IO objects, hurrah!

DATA.rewind
puts DATA.read
__END__

This is nearly as “bad” as the File.read(__FILE__) solution though (since it is, in fact, identical in functionality)

Reply

David Lee March 18, 2010 at 4:55 pm

golf?
echo > quine.rb && ruby quine.rb

Reply

Michael Shapiro March 18, 2010 at 5:01 pm

Ah, here we are.

a = <<-doc
puts 'a = <<-doc'
puts a
puts 'doc'
puts 'eval a'
doc
eval a

:)

Reply

Michael Shapiro March 18, 2010 at 5:02 pm

And by it’s nature, will handle any kind of formatting that you decide to throw into the ‘a’ variable, indent away! :)

Reply

Alan Skorkin March 18, 2010 at 6:16 pm

That’s awesome, very cool indeed, and once again, I can’t believe I didn’t think of it :).

Reply

David March 18, 2010 at 6:10 pm

> “An Interview Question That Prints Out It’s Own Source Code (In Ruby)”

> “A program that prints out it’s own source code (without reading in and outputting it’s source file..”

> ” Try and come up with a quine in Ruby that will output it’s source formatted/indented..”

Learn the difference between `it’s` and `its`.

Here’s how to use an apostrophe: http://theoatmeal.com/comics/apostrophe. It’s simultaneously humorous and educational; you obviously missed it when it was on reddit, so here’s another chance.

Reply

Alan Skorkin March 18, 2010 at 6:30 pm

Hi David,

I guess I probably deserved that :). I try to be somewhat pedantic about my spelling and grammar, but I also try not to get hung up about it. In my defense, it was late and I was in a rush, so didn’t proof it.

I’d like to hope that it is clear from most of my posts that it was an honest oversight (alright an honest several oversights :)) rather than stupidity.

Anyway, I’ve updated the post – off to grammar school for me.

Reply

E March 19, 2010 at 9:38 am

David,

I would have expected that as the creator of a framework I use a lot you would have better manners.
Very rude man…

E

Reply

E March 19, 2010 at 9:40 am

And…

Zed Shaw was correct in his rant.
Some people in the ruby/rails community are really up their own arse..
DHH seems to be one of these.

e

Reply

Clay Shentrup May 7, 2010 at 8:13 am

David,

You should explain the difference between “it’s” and “its” to who ever wrote the docs for this Tolk plugin you authored:

“As tolk stores all the keys and translated strings in the database, you need to ask Tolk to update it’s database from the primary yml file”.
http://github.com/dhh/tolk

Reply

Jon March 18, 2010 at 7:29 pm

All very interesting from an academic point of view, but I really don’t see this being a good interview question. I much prefer to use questions with some relevance to the real world, and this (at least on the face of it) has none.

When I’m interviewing developers, I’m not just looking for people who are awesome technically, I’m after people who can balance that off with an understanding of the business problems they are trying to solve, and who understand when it’s appropriate to make compromises on one side or the other.

I also want to know how good they are at structuring their code well, applying SOLID principles and so on. I’ve met people in the past who are amazing with the language, but couldn’t do design if their lives depended on it – and as we know, programming is all design (http://jockeholm.wordpress.com/2010/01/29/programming-is-all-design/)

I won’t get either of these things from that question, so I’d prefer to use a question that will tell me a bit more about their overall level of ability when it comes to working a developer solving business problems on a daily basis.

Reply

Alan Skorkin March 19, 2010 at 10:19 pm

Hi Jon,

I already described why I think it is a decent question, so I won’t go over it again, I do agree that you need to ask other types of questions as well, coding, design etc. But it is not like we’re restricted to one question in an interview. Asking a diverse range of question like this one and others will help you form a more complete picture of the person you’re interviewing. It is not just about what they say as a response, it’s about how they say it.

Reply

Sean McLemon March 18, 2010 at 11:25 pm

I am a filthy, dirty cheat:

smclemo@edin-angus /c/analog/dev/work/B-REL-VDSP5_0/DSPLIB
$ cat short.rb
b0rked
smclemo@edin-angus /c/analog/dev/work/B-REL-VDSP5_0/DSPLIB
$ ruby short.rb
short.rb:1: undefined local variable or method `b0rked’ for main:Object (NameError)

Reply

Abhinay Mehta March 19, 2010 at 12:47 am

4 characters smaller: def s;”def s;;end;puts s()[0,6]+34.chr+s+34.chr+s()[6,s.length]“;end;puts s()[0,6]+34.chr+s+34.chr+s()[6,s.length]

Reply

E.Pirogov March 19, 2010 at 4:37 am

obfuscated derivative from lee doolan (save as q.rb without end if line and end of file)
ruby q.rb >qq.rb; diff q.rb qq.rb; cat q.rb; echo ”; ls -l q.rb qq.rb
_=”_=%p;$><<<_%_
25 2010-03-18 13:35 qq.rb
25 2010-03-18 13:32 q.rb

Reply

Alan Skorkin March 19, 2010 at 10:21 pm

Oh, that’s brilliant, if someone came up with that in an interview I am not quite sure how I would look at it :).

Reply

Korny March 19, 2010 at 7:33 am

Sorry, the javascript quine was your interview question :)
Actually probably a valid interview question, if you are checking for javascript knowledge. The key is that a javascript function’s toString() method returns it’s source code, so you can say:
(function quine(){return ‘(‘+quine+’)();’;})();

Reply

Alan Skorkin March 19, 2010 at 10:26 pm

That’s pretty nice, another good question for javascript knowledge would be to ask them to talk about why they hate the language and go into specifics. If they can’t talk your eat off for at least 30 minutes don’t hire them :).

Reply

Jeremy March 19, 2010 at 11:49 am

Here’s my effort, using an array instead of a string:

a=['a=[',';puts [a[0],a[0],”,”, a[1],”]”,a[1]].join(39.chr)’];puts [a[0],a[0],”,”, a[1],”]”+a[1]].join(39.chr)

Reply

Jeremy March 19, 2010 at 12:01 pm

whoops, typo: a=['a=[',';puts [a[0],a[0],”,”, a[1],”]”+a[1]].join(39.chr)’];puts [a[0],a[0],”,”, a[1],”]”+a[1]].join(39.chr)

Reply

Alan Skorkin March 19, 2010 at 10:24 pm

Similar but different, pretty cool.

Reply

Aaron Thomson March 19, 2010 at 2:19 pm

40 chars shorter:
s=”s=;puts s[0,2]+34.chr+s+34.chr+s[2,36]“;puts s[0,2]+34.chr+s+34.chr+s[2,36]

Reply

Alan Skorkin March 19, 2010 at 10:28 pm

Hehe, nice, it’s pretty awesome how you can get them so short in Ruby.

Reply

Jeff March 20, 2010 at 2:18 am

#!/bin/cat
There. No, I’m not trying to be a smart ass, I think this is a valid answer. First of all, you can make it executable, and execute it, and it doesn’t read it’s own source (if you say it does, you’ll have to accept that that’s what the ruby interpreter does when you start a program).

There are three main advantages to this solution:
1) Extensible: You can edit the “source”, and it will work without further modification, in fact, if it wasn’t clear, this whole post is part of the solution.
2) Clear: It’s very obvious what will happen. The others you pretty much need knowledge of Quines to understand without running (it doesn’t make obvious why though, that will be in V2, after I figure it out for myself).
3) The right tool: Would you hire someone who spent time making tools to do stuff that every *nix already comes with a tool to do? During an interview, if you asked someone how to compile C, and they answered you use (gcc|ming|compiler of choice) you would probably be happier than if they started to describe how to write a C compiler.

Cheers.

Reply

Alan Skorkin March 20, 2010 at 2:26 am

Hey Jeff,

It is kinda cheating, but if you explained in interview like you did here and I was the interviewer, I reckon I would give you points for creativity and having the balls to use it as a solution in the first place since you probably knew that it wasn’t quite what I was after :).

Creative and ballsy answers can often get you just as far in an interview as “correct” ones, especially if the creative ones also solve the problem.

Reply

Paul Damer March 20, 2010 at 4:46 am

You can avoid the quote char codes by using inspect:

s=”s=;puts s[0,2]+s.inspect+s[2,30]“;puts s[0,2]+s.inspect+s[2,30]

Reply

Alan Skorkin March 20, 2010 at 1:28 pm

Hi Paul,

That’s a great tip, I like it.

Reply

Jasim May 5, 2010 at 10:37 am

Something in the same vein, a little more direct:

c=”c=#; puts c.sub(‘#’,c.inspect)”; puts c.sub(‘#’,c.inspect)

Reply

Olivier Leclant March 20, 2010 at 9:51 pm

I found (by chance) the shortest quine in ruby.
$ touch quine.rb
$ ruby quine.rb
$

Reply

Alan Skorkin March 20, 2010 at 10:07 pm

This has been pointed out already (above), technically speaking an empty file is a valid program in ruby, however it is also thoroughly uninteresting (although good to know), it would be more fun to write a real quine :).

Reply

Andrew McElroy March 27, 2010 at 2:21 pm

I should have read the comments before posting.
owell..

it would also possible to go even shorter actually

$irb
(press return)
>>

Reply

Alan Skorkin March 27, 2010 at 2:41 pm

Haha, don’t stress about it :)

Reply

wes March 21, 2010 at 7:43 am

These are nice but they are not one line. Using the semi-colon is the equivalent of adding another line of executable functionality. Any ruby program could be written in a single line by just reformatting with semi-colons.

Reply

Alan Skorkin March 21, 2010 at 12:54 pm

That’s true, but a quine doesn’t have to be a one liner, putting it all on one line just makes things a little easier.

Reply

steenslag March 22, 2010 at 9:28 am

I’m not the inventor of this one, it’s an adaptation of an existing one.

puts <<quine*2, 'quine'
puts <<quine*2, 'quine'
quine

Reply

Chuck Vose March 22, 2010 at 11:07 am

Slightly more readible format though it does pretty much only work in Ruby since we actually have a third quote operator instead of using 34.chr. Also, somewhat unnecessarily long, but readability was most important since I’m trying to explain to a non-programmer friend.

$program_code = %s{class Quine
def to_s
puts “$program_code = %s{#{$program_code}}\n\n”
puts $program_code
end
end

Quine.new().to_s}

class Quine
def to_s
puts “$program_code = %s{#{$program_code}}\n\n”
puts $program_code
end
end

Quine.new().to_s

Reply

BonsaiDen March 26, 2010 at 12:02 pm

Javascript, without any duplication.
Note: I don’t count the script tags against the code, since HTML != Javascript.

(function(){
var q = “Question: What’s the POLAbear?”;
console.log(document.getElementsByTagName(’script’)[0].text);
})()

Reply

Alan Skorkin March 26, 2010 at 12:24 pm

Ha, nice one!

Reply

Jonas Elfström March 27, 2010 at 1:41 am

lambda { |s| puts s + s.dump }.call “lambda { |s| puts s + s.dump }.call ”

Also didn’t see a reference to http://en.wikipedia.org/wiki/Quine%27s_paradox

Reply

Alan Skorkin March 27, 2010 at 1:33 pm

Hi Jonas,

I like lambda based one a lot, thanks for sharing it.

Reply

Andrew McElroy March 27, 2010 at 2:13 pm

Guys, your over thinking it.

here is the worlds smallest program that prints its own source listing.
(from bash)
$touch lol.rb
$ruby lol.rb
$

a empty file is a valid program. Now, if there were a minimum character length, then this becomes trickier.

Reply

Andrew McElroy March 27, 2010 at 2:14 pm

By Guys I mean gender neutral, guys/gal :-)

Reply

Josh Cheek March 27, 2010 at 6:34 pm

printf a=”%1$s a=%2$s , ‘%1$s’ , a.inspect” , ‘printf’ , a.inspect

Reply

Josh Cheek March 29, 2010 at 2:08 pm

I shortened it and made it simpler:
printf a=”printf a=%s , a.dump” , a.dump

A C version based on same concept:
#include
int main() {
char a[]=”#include %2$cint main() {%2$c char a[]=%3$c%1$s%3$c;%2$c printf(a,a,10,34);%2$c return 0;%2$c}”;
printf(a,a,10,34);
return 0;
}

Reply

Josh Cheek March 29, 2010 at 2:12 pm

The blog removed the stdio because it looks like an html tag.
View it at http://codepad.org/hPzRKf0Q

Reply

Leave a Comment

Previous post:

Next post: