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

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

  • http://brianyamabe.com Brian Yamabe

    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.

    • http://www.skorks.com Alan Skorkin

      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.

  • Pingback: Dew Drop – March 17, 2010 | Alvin Ashcraft's Morning Dew

  • http://grumpyop.wordpress.com Mike Woodhouse

    How about

    puts File.read(__FILE__)

    or

    puts File.read($0)

    • http://www.skorks.com Alan Skorkin

      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)”

      • Mike Woodhouse

        Well, duh. I must be italic-blind.

  • http://www.truewill.net/myblog/index.php Bill Sorensen

    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.

    • http://www.skorks.com Alan Skorkin

      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.

  • Korny

    Of course, javascript would make this trivial…

    • http://www.skorks.com Alan Skorkin

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

  • lee doolan

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

    • http://www.skorks.com Alan Skorkin

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

      • lee doolan

        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.

        • http://www.skorks.com Alan Skorkin

          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.

  • http://www.peterdonis.net Peter Donis

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

    #!/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)
    

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

    • http://www.skorks.com Alan Skorkin

      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.

    • Matthew

      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!)

      • http://www.skorks.com Alan Skorkin

        I like this one :).

      • wes

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

  • Rich Collins

    In Io from the repl:

    thisMessage

    from an executed file:

    thisMessage println

  • Pant Darkin

    No offense but that is a silly interview question.

    • http://www.skorks.com Alan Skorkin

      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.

  • http://swaggadocio.com/ Stevie Graham

    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]

    • http://www.skorks.com Alan Skorkin

      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 :).

  • Michael Shapiro

    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

    • http://www.skorks.com Alan Skorkin

      Hi Michael,

      Still interesting though.

    • James Sanders

      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)

  • David Lee

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

  • Michael Shapiro

    Ah, here we are.

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

    :)

    • Michael Shapiro

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

    • http://www.skorks.com Alan Skorkin

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

  • http://loudthinking.com David

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

    • http://www.skorks.com Alan Skorkin

      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.

    • E

      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

    • 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

    • http://scorevoting.net/ Clay Shentrup

      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

  • Jon

    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.

    • http://www.skorks.com Alan Skorkin

      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.

  • Sean McLemon

    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)

  • Abhinay Mehta

    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]

  • E.Pirogov

    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

    • http://www.skorks.com Alan Skorkin

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

  • Korny

    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+’)();’;})();

    • http://www.skorks.com Alan Skorkin

      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 :).

  • http://www.boost.co.nz/blog Jeremy

    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)

    • http://www.boost.co.nz/blog Jeremy

      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)

      • http://www.skorks.com Alan Skorkin

        Similar but different, pretty cool.

  • Aaron Thomson

    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]

    • http://www.skorks.com Alan Skorkin

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

  • Jeff

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

    • http://www.skorks.com Alan Skorkin

      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.

  • Paul Damer

    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]

    • http://www.skorks.com Alan Skorkin

      Hi Paul,

      That’s a great tip, I like it.

    • Jasim

      Something in the same vein, a little more direct:

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

  • Pingback: Best of RubyFlow: 12 Ruby Links From March 2010 « Особое программирование

  • Olivier Leclant

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

    • http://www.skorks.com Alan Skorkin

      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 :).

    • http://TryRuby.org Andrew McElroy

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

      it would also possible to go even shorter actually

      $irb
      (press return)
      >>

      • http://www.skorks.com Alan Skorkin

        Haha, don’t stress about it :)

  • wes

    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.

    • http://www.skorks.com Alan Skorkin

      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.

  • steenslag

    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

  • http://www.chuckvose.com Chuck Vose

    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

  • Pingback: My Mother Would Be So Proud « Grumpy Old Programmer

  • http://github.com/BonsaiDen/ BonsaiDen

    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);
    })()

    • http://www.skorks.com Alan Skorkin

      Ha, nice one!

  • http://alicebobandmallory.com/ Jonas Elfström

    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

    • http://www.skorks.com Alan Skorkin

      Hi Jonas,

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

  • http://TryRuby.org Andrew McElroy

    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.

  • http://TryRuby.org Andrew McElroy

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

  • Josh Cheek

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

    • Josh Cheek

      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;
      }

  • Pingback: O Melhor do RubyFlow – 12 Links sobre Ruby de Março de 2010

  • Pingback: Z Carioca » Blog Archive » On the question of interviews

  • http://codefisher.org/ Michael Buckley

    Python :)

    s = “s = ; print(s[0:4] + chr(34) + s + chr(34) + s[4:])”; print(s[0:4] + chr(34) + s + chr(34) + s[4:])

    PS: yes I realise this is an oldish post, just first time I had seen the problem and had to have a go.

    • http://www.skorks.com Alan Skorkin

      You’re never too late to the party if you can still have fun, that’s what I always say :)

  • Steven Rumbalski

    In many languages you could just code up an empty file. But that’s probably cheating.

  • http://alicebobandmallory.com/ Jonas Elfström

    In case you missed two of the most mind blowing “quines” ever:

    http://mamememo.blogspot.com/2010/09/qlobe.html – rotating globe
    $ watch -n1 ‘ruby current.rb | tee next.rb && mv next.rb current.rb’
    http://www.youtube.com/watch?v=ktq-22iq-Po

    http://d.hatena.ne.jp/ku-ma-me/20090916 – Polyglot quine from Ruby to Python to Perl to Lua to OCaml to Haskell to C to Java to Brainfuck to Whitespace to Unlambda and back to Ruby.

  • Just Saying

    The First Quines in Ruby
    Originally posted to the ruby-talk list on July 19, 2000
    http://rubyhacker.com/ruby-quine.html

    Note: this also includes a heredoc example!

  • Chris

    Would you hire me if I offered an empty file?

  • Pingback: Learning about learning about programming | ThoughtDrop

  • Pingback: Why so much ugliness? | Ourbs.com