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
Related posts:
- Timing Ruby Code – It Is Easy With Benchmark
- How A Ruby Case Statement Works And What You Can Do With It
- True, False And Nil Objects In Ruby
- How To Answer A Programming Interview Question And Look Good Doing It
- Ruby Equality And Object Comparison
- Serializing (And Deserializing) Objects With Ruby
- Ruby Procs And Lambdas (And The Difference Between Them)
{ 4 trackbacks }
{ 70 comments… read them below or add one }
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.
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.
How about
puts File.read(__FILE__)
or
puts File.read($0)
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)”
Well, duh. I must be italic-blind.
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.
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.
Of course, javascript would make this trivial…
That sounds intriguing. If you would like to whip one up quickly and post it, I’d love to see it.
lee@stjohn:~$ ruby q.rb
_=”_=%p;puts _%%_”;puts _%_
Oh very nice, using string format, I didn’t even think of that, works a treat :)
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.
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.
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.)
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.
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!)
I like this one :).
I disagree that this is one line! Using the semi-colon is the equivalent of writing another line of code.
In Io from the repl:
thisMessage
from an executed file:
thisMessage println
No offense but that is a silly interview question.
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.
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]
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 :).
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
Hi Michael,
Still interesting though.
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)
golf?
echo > quine.rb && ruby quine.rb
Ah, here we are.
a = <<-doc
puts 'a = <<-doc'
puts a
puts 'doc'
puts 'eval a'
doc
eval a
:)
And by it’s nature, will handle any kind of formatting that you decide to throw into the ‘a’ variable, indent away! :)
That’s awesome, very cool indeed, and once again, I can’t believe I didn’t think of it :).
> “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.
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.
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
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
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
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.
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.
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)
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]
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
Oh, that’s brilliant, if someone came up with that in an interview I am not quite sure how I would look at it :).
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+’)();’;})();
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 :).
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)
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)
Similar but different, pretty cool.
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]
Hehe, nice, it’s pretty awesome how you can get them so short in Ruby.
#!/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.
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.
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]
Hi Paul,
That’s a great tip, I like it.
Something in the same vein, a little more direct:
c=”c=#; puts c.sub(‘#’,c.inspect)”; puts c.sub(‘#’,c.inspect)
I found (by chance) the shortest quine in ruby.
$ touch quine.rb
$ ruby quine.rb
$
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 :).
I should have read the comments before posting.
owell..
it would also possible to go even shorter actually
$irb
(press return)
>>
Haha, don’t stress about it :)
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.
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.
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
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
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);
})()
Ha, nice one!
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
Hi Jonas,
I like lambda based one a lot, thanks for sharing it.
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.
By Guys I mean gender neutral, guys/gal :-)
printf a=”%1$s a=%2$s , ‘%1$s’ , a.inspect” , ‘printf’ , a.inspect
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;
}
The blog removed the stdio because it looks like an html tag.
View it at http://codepad.org/hPzRKf0Q