Generalized Quine Generator
Source = Target = CJam, 19 17 16 bytes
{`"_~"+}`)q\"_~"
This assumes that the input program Q
(given on STDIN) is some CJam snippet which expects a string on the top of the stack and leaves another string on top of the stack.
Test it here.
Examples
The identity would just be an empty snippet, so leaving STDIN empty prints
{`"_~"+}_~
Which is the standard quine, with an additional
+
.To reverse a string in CJam, you can use
W%
, so putting that on STDIN, this yields:{`"_~"+W%}_~
which we can run to obtain
~_}%W+"~_"`{
As a third example, say we use a snippet which intersperses a string with spaces:
' *
. RunningP
with that as input, we get{`"_~"+' *}_~
which in turn prints
{ ` " _ ~ " + ' * } _ ~
It now also works if
Q
contains line breaks (although that's never necessary in CJam). Here is a program with a line break, which removes all line breaks from a string (in an unnecessarily convoluted way - split into lines, then join):N/ "" *
This results in the following
R
:{`"_~"+N/ "" *}_~
which in turn prints
{`"_~"+N/""*}_~
Explanation
Let's look at the produced output first:
The standard CJam quine is
{`"_~"}_~
It works as follows:
- Push the block
{`"_~"}
. - Duplicate it with
_
. - Execute the copy with
~
. - Now inside the block,
`
turns the first block into its string representation. "_~"
pushes the two characters of the source that are not part of the block (and hence missing from the string representation).- The two strings are printed back to back at the end of the program.
In the basic quine the `
is unnecessary, because if you just leave the block as it is, it's printed all the same at the end of the program.
The output of my program P
is a modified version of this snippet. First, I've added a +
to the block, which concatenates the two strings into one string containing the entire source. Note that this will be true no matter what I do inside the block, because that will all get added to the string representation obtained with `
. Now I can simply put the program/snippet Q
inside the block after the +
, so that it can modify the source string before it is printed. Again, since Q
goes inside the block, it will be part of said source string.
In summary, P
prints
{`"_~"+Q}_~
Now, for how I go about constructing this output in P
:
{`"_~"+} "Push the block without Q.";
` "Turn it into a string. This is shorter than writing a string right away,
because I'd have to escape the quotes, and I'd need two quotes instead of
one backtick.";
) "Pop off the last character (the brace) and push it on the stack.";
q "Read input Q.";
\ "Swap Q with the brace.";
"_~" "Push the final two characters.";
The four strings are printed automatically (back-to-back) at the end of the program.
Haskell expressions → Haskell expressions, 41 bytes
((++)<*>show).('(':).(++")$(++)<*>show$")
Try it online!
How it works
P $ "Q"
= ((++)<*>show).('(':).(++")$(++)<*>show$") $ "Q"
constructs "R"
by
(++")$(++)<*>show$")
: appending the string")$(++)<*>show$"
,('(':)
: prepending the character'('
, and(++)<*>show
(=\x->x++show x
): appending a quoted version of that,
resulting in "R"
= "(Q)$(++)<*>show$\"(Q)$(++)<*>show$\""
.
R
= (Q)$(++)<*>show$"(Q)$(++)<*>show$"
works by
- taking the string
"(Q)$(++)<*>show$"
, (++)<*>show
: appending a quoted version of that,- applying
Q
to that,
resulting in Q "(Q)$(++)<*>show$\"(Q)$(++)<*>show$\""
= Q "R"
.
(The parens around Q
are necessary because Q
might contain $
just as easily as R
does, and $
is unfortunately right-associative.)
Demo
λ> putStrLn $ ((++)<*>show).('(':).(++")$(++)<*>show$") $ "id"
(id)$(++)<*>show$"(id)$(++)<*>show$"
λ> putStrLn $ (id)$(++)<*>show$"(id)$(++)<*>show$"
(id)$(++)<*>show$"(id)$(++)<*>show$"
λ> putStrLn $ ((++)<*>show).('(':).(++")$(++)<*>show$") $ "reverse"
(reverse)$(++)<*>show$"(reverse)$(++)<*>show$"
λ> putStrLn $ (reverse)$(++)<*>show$"(reverse)$(++)<*>show$"
"$wohs>*<)++($)esrever("$wohs>*<)++($)esrever(
λ> putStrLn $ ((++)<*>show).('(':).(++")$(++)<*>show$") $ "length"
(length)$(++)<*>show$"(length)$(++)<*>show$"
λ> print $ (length)$(++)<*>show$"(length)$(++)<*>show$"
44
Source = Target = JavaScript, 66
console.log("function a(){console.log("+prompt()+"(a+'a()'))}a()")
Assumptions for Q:
Q
should be a string-to-string JavaScript anonymous function.
Examples:
- Reverse. Q =
function(s) { return s.split('').reverse().join(''); }
In this case, P(Q)
(or R
) will be: function a(){console.log(function(s) { return s.split('').reverse().join(''); }(a+'a()'))}a()
, and by executing it, we will get: )(a}))')(a'+a(} ;)''(nioj.)(esrever.)''(tilps.s nruter { )s(noitcnuf(gol.elosnoc{)(a noitcnuf
which is exactly the same as Q(R)
.
- Identity. Q =
function(s) { return s; }
in this case, P(Q)
(or R
) will be: function a(){console.log(function(s) { return s; }(a+'a()'))}a()
which is a JavaScript Quine. Needless to say, Q(R)
will be the same, since Q is the Identity function.
Some notes:
STDIN in JavaScript is traditionally prompt()
, however, I allowed myself to refrain from the tradition of alert()
as STDOUT, in order to make the process of run output as a progrem using copy-paste easier. (I do realize I can save up to 12 characters when changing to alert()
).
I can also make things much shorter in ES6, but I want to stay with Native JavaScript for now. I'm considering submitting a S=Scala,T=ECMA6 answer in future, just for the experience.
I also realize JavaScript can almost never beat CJam in code-golf, but I had to take this challenge! It was surly a fun one.