Elixir Quine Self-Replicating Program

elixirgolf bio photo By elixirgolf Comment

Instructions

Write an elixir quine. A Quine is a computer program which takes no input and produces a copy of its own source code as its only output. They are “self-replicating” or “self-reproducing” programs, and your task is to either create the shortest or the most creative elixir quine.

There will be two winners, one for the shortest and the other for the most creative. Creative is open to interpretation, however these are the sort of things we consider creative:

  • best use of language (elixir or erlang), maybe use processes
  • interpretation of a quine, e.g. prints the output in reverse
  • maybe switches between languages elixir/erlang

The rule is that you enter your code into iex and press return, the output will be your code. This can then be copied and pasted back into iex and will produce the same output. It maybe that your code requires pasting back into iex multiple times, but at some “reasonable” count it should reproduce the original code.

A Ruby example might be:

irb> lambda{|x| puts x + x.inspect}.call"lambda{|x| puts x + x.inspect}.call"
lambda{|x| puts x + x.inspect}.call"lambda{|x| puts x + x.inspect}.call"
=> nil

No cheating quines

Quines, per definition, cannot receive any form of input, including reading a file, which means a quine is considered to be “cheating” if it looks at its own source code.

This JavaScript example cheats by calling itself with the a() call. Essentially in this case the function code is a file.

function a() {
    document.write(a, "a()");
}
a()

Please submit your solutions as comments to the Github issue:
https://github.com/emson/elixirgolf/issues/1

Solutions

This weeks puzzle was less popular than last weeks, probably because Quines are quite abstract, however we had a few interesting solutions. More importantly there were things to learn from.

Winner

Winner: @rubysolo

char count: 46

q=<<"q=~p;:io.format q,[q]">>;:io.format q,[q]

Understanding

The key to this Quine is the Erlang function :io.format/2. This function takes 2 parameters Format and Data, which it uses to write the Data to the standard output device in accordance to the Format provided.

For example, using the Format "~p", it will write the Data using standard syntax and will output lists of printable characters as strings. Interestingly the Data will replace the ~pvalue, this means you can surround it with other text for example "hello ~p world".

iex> :io.format "hello ~p world", ["my"]
hello <<"my">> world:ok

NB. the :ok atom is just the standard return response so we can ignore it for our Quine purposes.

Next we build the String to be passed to :io.format. This String is the clever bit, as it will be crafted in such a way that :io.format will use it to substitue the ~p value with itself. If we substitue the Data parameter with "BOOM" you can see what :io.format does. It converts the ["BOOM"] list to a binary (String) <<"BOOM">>. Notice that the <<>> elixir bitstrings are returned.

iex> :io.format "q=~p;:io.format q,[q]", ["BOOM"]
q=<<"BOOM">>;:io.format q,[q]:ok

As <<>> bitstrings are returned we need to surround our Format String with them. Finally we bind the whole value to the variable q, and remember to separate the 2 conditions with ;.

A great solution, which demonstrates the symbiotic relationship between Erlang and elixir.

Honourable mentions

Honourable mention solutions are ordered by influence rather than on char count. This is because often a particular solution will influence others.

Submitted by @Phani_Mahesh:

char count: 90

"fn x->IO.puts~s(\#{inspect x}|>\#{x}) end.()"|>fn x->IO.puts~s(#{inspect x}|>#{x}) end.()

Understanding

Typically a Quine takes a String of code and rebuilds it with a “builder” function. This “builder” function reassembles the code when it is executed. In the solution @Phani_Mahesh has provided, he uses the following function, fn x -> IO.puts ~s(#{inspect x}|>#{x}) end.(). If we tidy it up and pass in a String value we can see what it does:

iex> f = fn x -> IO.puts ~s(#{inspect x}|>#{x}) end
#Function<6.54118792/1 in :erl_eval.expr/5>
iex> f.("BOOM")
"BOOM"|>BOOM
:ok

As we can see it uses the |> pipe operator to pipe a string into a non-String version of itself. This is interesting as @Phani_Mahesh’s function fn x -> IO.puts ~s(#{inspect x}|>#{x}) end.() has an empty anonymous function invocation applied to the end end.() which takes no parameters. Actually it does take parameters as the |> is passing the String value into the first arity position, therefore there is no need to declare it.

The function also uses the ~s sigil to return a String representation of whatever is within it’s brackets ~s(#{inspect x}|>#{x}). Note that the #{} interpolation will be applied, and that we can use inspect without prefixing the module e.g. IO.inspect. So the inspect will return the String surrounded by "" quotes.

Finally the String used to pass to the function is almost an exact representation of the function, apart from the escape characters \. These will prevent the String from interpolating the value between the #{} characters.

iex> "fn x->IO.puts~s(\#{inspect x}|>\#{x}) end.()"
"fn x->IO.puts~s(\#{inspect x}|>\#{x}) end.()"

Excellent, well done.


Submitted by @CoderDennis:

char count: 82

"(&(IO.puts~s(\#{inspect&1}|>\#{&1}))).()"|>(&(IO.puts~s(#{inspect&1}|>#{&1}))).()

Understanding

This solution is based on @Phani_Mahesh’s solution, however @CoderDennis has taken it further and realised that he can use the anonymous function capture syntax.

Thus the function:

"fn x -> IO.puts ~s(#{inspect x} |> #{x}) end.()"

Becomes:

(&(IO.puts ~s(#{inspect&1} |> #{&1}))).()

Here x becomes the capture parameter &1, and the function syntax fn x -> x end becomes &(&1). Finally the whole anonymous function is invoked with .(), for example, (&(&1)).("BOOM").

Good thinking, well done.


Resources

comments powered by Disqus