mbomb007 asked us to make a self mutilating program. Its an interesting challenge, but I personally don't like to encourage my programs to be self-mutilating. I like to think that, at the heart of every program is a beautiful butterfly waiting to break out.
As such, for my first ever Code Golf challenge, I challenge Stack Exchange to metamorph a butterfly. Your program should accept its own code as input and output I am a caterpillar!
followed by the code for another program in the same language (you may put a divider between the outputs or not... but we're talking butterflies, so prettiness counts!). This second program should output I am a beautiful butterfly!
Metamorphosis: This program should modify itself, which is why it is being passed itself as input. I don't want a boring nested program that is nothing but a print statement I am a caterpillar!
followed by printing source code. You have to metamorph the code itself, so the most boring acceptable answer is one which prints I am a caterpillar
, then rips a string out of the input (which happens to be code) and prints that. Of course, this is a very tricky little requirement to write, so it should be thought of as a "spirit of the challenge." The formal requirement is going to be set at "If your program is given a random string of the same length as your program, there should be less than a 5% chance of printing I am a butterfly
when the second program is run."
Summary:
- Write a program which, when provided its own code as input, prints
I am a caterpillar!
followed by a block of source code (with a delimiter between them or not). - This second block of source code, when compiled/interpreted as the same language, prints
I am a beautiful butterfly!
- If your program is not fed its own source code as input, and is instead given a random string of characters that does not match its own code, the result must either fail to compile/interpret, or not print
I am a butterfly!
for at least 95% of random strings (spirit: you are expected to read your own source code from the input, and stitch it together into a butterfly).- I'm comfortable with you not proving this, so long as you're holding to the spirit of the metamorphosis idea, modifying your own code, but if you're trying to play loophole games to work around using your inputs, expect to have to prove it.
- Standard loopholes apply
I'd like these to be judged by their beauty, but that's a decidedly non-quantitative approach, so the usual "number of bytes" route can be used to judge
Bonus: -20% - pick any 3 letter string that doesn't match the first 3 letters of your program. If I run the caterpillar program, but modify the input so that the first 3 character are changed to the specified ones, print I am Batman!
instead. Always be Batman. (Same random string rules apply for this... metamorphosis!)
Trivial example (python):
"""
print "I am a beautiful butterfly!"
#print "I am Batman!"
"""
import sys
code = sys.stdin.read()
if code.startswith("YYZ"):
# swap the comments between the print statements
code = code.replace("#print", "_a").replace("print", "#print").replace("_a", "print")
code = [3:] # remove """ or XYZ
code = code.split('"""')[0]
print "I am a caterpillar!"
print code
-
\$\begingroup\$ As a note: I'd love to see ascii art programs where it looks like a caterpillar the first time, and turns into an ascii butterfly the next phase, but that's quite a bit more advanced than the challenge needs to be. \$\endgroup\$Cort Ammon– Cort Ammon2015年10月07日 19:58:49 +00:00Commented Oct 7, 2015 at 19:58
-
\$\begingroup\$ What should we do if a program has multiple files? \$\endgroup\$TheNumberOne– TheNumberOne2015年10月07日 23:25:23 +00:00Commented Oct 7, 2015 at 23:25
-
\$\begingroup\$ @TheNumberOne I'm curious what you have planned there! I don't know if I want to beat down the rules for that right away, without seeing the consequences, but it seems to me that, if you were to accept a multi-part set of files as input (rather than a single file's contents), and you were to output a multi-part set of outputs (rather than a single output), with a half-reasonable deliniator between the files, I think that should be a reasonable solution. If that doesn't work for you, I may need more insight into your proposed solution to better craft a rule. \$\endgroup\$Cort Ammon– Cort Ammon2015年10月07日 23:47:14 +00:00Commented Oct 7, 2015 at 23:47
-
\$\begingroup\$ @TheNumberOne And thank you for the typo catch. That typo was very clearly not a beautiful butterfly! \$\endgroup\$Cort Ammon– Cort Ammon2015年10月07日 23:48:09 +00:00Commented Oct 7, 2015 at 23:48
9 Answers 9
Befunge-98, 602 bytes
"^@<"v@@
"'I'"00v>00g::
"@v"0v@@@>g::a">#"
"a">v@@> 0g::'"1> /
":\"'"v@> 'm'"00g:a >"@v$"
"lufituaeb"'"'v00ga"@v\"'":'b00円v@> :'a\":*84>"00ga"\>@@@@_,#:>"00g:a'<'"
"et"'"'va'v'":'l00円g5k:'""y!">>v@> g::'''""ut"'"'>a'<'""fr"'"00g3k:'">
"ma"00g>'I~48*-~48*-+#@_>:#,_@> '"aa"---"aa"!rallipretac"00g:'a\
Tested in PyFunge.
When run with a string not starting with 2 spaces (probability well over 95% when random) outputs nothing. This isn't exactly what the OP is looking for, but fits the specification.
When passed a string starting with 2 spaces (like itself) outputs this:
I am a caterpillar!
---
"!y" "l"v
v"te" "rf"<
>"tu"' "b"\v@
v"beautiful"<
>:#,_@@@@>\
>48*:"a"\:$v@
"ma" v@#>
'I' <@^
The lower part of that, in turn, outputs:
I am a beautiful butterfly!
-
2\$\begingroup\$ Wow. This is amazing. \$\endgroup\$a spaghetto– a spaghetto2015年10月08日 00:12:12 +00:00Commented Oct 8, 2015 at 0:12
-
3\$\begingroup\$ I knew someone would want to push the rules just like you did; I'm glad something beautiful came out of it =) \$\endgroup\$Cort Ammon– Cort Ammon2015年10月08日 03:21:57 +00:00Commented Oct 8, 2015 at 3:21
-
\$\begingroup\$ Both caterpillar and butterfly look like they are stuck in the Matrix. Beautiful! \$\endgroup\$Emond– Emond2015年10月08日 13:07:10 +00:00Commented Oct 8, 2015 at 13:07
-
\$\begingroup\$ where can I run this? \$\endgroup\$user1514631– user15146312015年10月08日 13:19:17 +00:00Commented Oct 8, 2015 at 13:19
-
3\$\begingroup\$ I will never understand how you good folks at Code Golf manage to create such beautiful monstrosities. \$\endgroup\$Chris Cirefice– Chris Cirefice2015年10月09日 00:08:56 +00:00Commented Oct 9, 2015 at 0:08
PHP, 74 Bytes
<?=~¶ßž’ßžß,$s="caterpillar!",strtr($argv[1],[$s=>~šžŠ‹–TMŠ"ߊ‹‹šTM"†Þ]);
<?=
is equivalent to<?php echo
and can take several comma separated values to output¶ßž’ßžß
andšžŠ‹–TMŠ"ߊ‹‹šTM"†Þ
are valid constant names in PHP, but because the constants do not exist are treated as string literal.~
inverts them to"I am a "
and"beautiful butterfly!"
(saving a byte for one quotation mark each)strtr
replaces "caterpillar!" with "a beautiful butterfly!" in the argument
-
2\$\begingroup\$ Care to provide an explanation? \$\endgroup\$Timwi– Timwi2015年10月07日 21:58:35 +00:00Commented Oct 7, 2015 at 21:58
-
\$\begingroup\$ @Timwi no problem, explanation added \$\endgroup\$Fabian Schmengler– Fabian Schmengler2015年10月07日 22:04:26 +00:00Commented Oct 7, 2015 at 22:04
-
\$\begingroup\$ I fully expected someone to encode "beautiful butterfly" with something like ROT13, but the idea of matching it with PHP's string literal technique is, in the words of Kaylee, shiny! \$\endgroup\$Cort Ammon– Cort Ammon2015年10月07日 23:52:12 +00:00Commented Oct 7, 2015 at 23:52
Pyth, (削除) 50 (削除ここまで) 46 bytes
"I am a caterpillar!"+<z8"beautiful butterfly!
Explanation
"I am a caterpillar!" print "I am a caterpillar!"
z<8 first 8 chars of input
+ "beautiful butterfly! add "beautiful butterfly!" to that and print
The resulting source code is
"I am a beautiful butterfly!
Which basically prints the text.
Perl 6, (削除) 60 (削除ここまで) 56 bytes
say "I am a caterpillar!"; s/\S+\!/beautiful butterfly!/
Requires -p to run properly; I have accounted for this in the byte count. Sadly one of the downsides to Perl 6 is that the syntax is much more strict now...
-
\$\begingroup\$ Caterpillars are vulnerable during metamorphosis. That's why they like to wrap themselves in c̶o̶c̶o̶o̶n̶s̶ variables:
$a=caterpillar;say"I am a $a!";s/$a/beautiful butterfly/
(I'm assuming that Perl 6 allows barewords like Perl 5 withno strict 'subs'
ands///
interpolates variables on the LHS.) \$\endgroup\$ThisSuitIsBlackNot– ThisSuitIsBlackNot2015年10月07日 22:35:28 +00:00Commented Oct 7, 2015 at 22:35 -
\$\begingroup\$ Huh, that's funny. I tried that and for some reason when I did wc it gave me the same amount of bytes. But upon typing it out again it gave me less bytes. Strange. \$\endgroup\$a spaghetto– a spaghetto2015年10月07日 23:13:34 +00:00Commented Oct 7, 2015 at 23:13
-
\$\begingroup\$ Oh wait nevermind I remember why I didn't do it. When run the new code it throws an error because of the space between beautiful and butterfly. \$\endgroup\$a spaghetto– a spaghetto2015年10月07日 23:18:03 +00:00Commented Oct 7, 2015 at 23:18
-
\$\begingroup\$ Ah, I've never used Perl 6 so can't help you there. I really just wanted an excuse to make a witty remark. ;)
say"I am a caterpillar!";s/\S+!/beautiful butterfly!/
is shorter and will certainly work in Perl 6. \$\endgroup\$ThisSuitIsBlackNot– ThisSuitIsBlackNot2015年10月08日 00:48:55 +00:00Commented Oct 8, 2015 at 0:48 -
1\$\begingroup\$ @ThisSuitIsBlackNot It does fit the challenge. The rules were just there to make sure you actually read and modify your code. In the end, the real spirit is trying to let the beautiful butterfly in the heart of the code break free. Beauty, of course, is in the eye of the beholder. We will each find different solutions more or less beautiful than others. As for solutions in PERL, well... let's just say PERL has its own peculiar definition of beautiful, and it suits its purposes just fine ;-) \$\endgroup\$Cort Ammon– Cort Ammon2015年10月08日 20:08:22 +00:00Commented Oct 8, 2015 at 20:08
Retina, 53 bytes
caterpillar
beautiful butterfly
^
I am a caterpillar!
Prints out:
I am a caterpillar!beautiful butterfly
beautiful butterfly
^
I am a beautiful butterfly!
Notice that there is no separator between I am a caterpillar!
and the new program. The new program expects no input.
bash
/ awk
/ cksum
- (削除) 179.2 (削除ここまで) (削除) 169.6 (削除ここまで) 168 bytes
awk '/^xyz/{print"I am Batman!";exit}NF{("cksum<<<'"'"'"substr(0,100ドル))|getline r;if(r!~/^6689751/)exit}{printf"I am a %s%."!NF"s!\n",NF?"caterpillar":"beautiful"," butterfly"}NF&&sub(/!NF/,10){print"echo|"0ドル}'
Demo:
$ awk '/^xyz/{print"I am Batman!";exit}NF{("cksum<<<'"'"'"substr(0,100ドル))|getline r;if(r!~/^6689751/)exit}{printf"I am a %s%."!NF"s!\n",NF?"caterpillar":"beautiful"," butterfly"}NF&&sub(/!NF/,10){print"echo|"0ドル}'<<'E'
> awk '/^xyz/{print"I am Batman!";exit}NF{("cksum<<<'"'"'"substr(0,100ドル))|getline r;if(r!~/^6689751/)exit}{printf"I am a %s%."!NF"s!\n",NF?"caterpillar":"beautiful"," butterfly"}NF&&sub(/!NF/,10){print"echo|"0ドル}'
> E
I am a caterpillar!
echo|awk '/^xyz/{print"I am Batman!";exit}NF{("cksum<<<'"'"'"substr(0,100ドル))|getline r;if(r!~/^6689751/)exit}{printf"I am a %s%."10"s!\n",NF?"caterpillar":"beautiful"," butterfly"}NF&&sub(/!NF/,10){print"echo|"0ドル}'
$ echo|awk '/^xyz/{print"I am Batman!";exit}NF{("cksum<<<'"'"'"substr(0,100ドル))|getline r;if(r!~/^6689751/)exit}{printf"I am a %s%."10"s!\n",NF?"caterpillar":"beautiful"," butterfly"}NF&&sub(/!NF/,10){print"echo|"0ドル}'
I am a beautiful butterfly!
# Batman!
$ awk '/^xyz/{print"I am Batman!";exit}NF{("cksum<<<'"'"'"substr(0,100ドル))|getline r;if(r!~/^6689751/)exit}{printf"I am a %s%."!NF"s!\n",NF?"caterpillar":"beautiful"," butterfly"}NF&&sub(/!NF/,10){print"echo|"0ドル}'<<'E'
> xyzawk '/^xyz/{print"I am Batman!";exit}NF{("cksum<<<'"'"'"substr(0,100ドル))|getline r;if(r!~/^6689751/)exit}{printf"I am a %s%."!NF"s!\n",NF?"caterpillar":"beautiful"," butterfly"}NF&&sub(/!NF/,10){print"echo|"0ドル}'
> E
I am Batman!
# Invalid input
$ awk '/^xyz/{print"I am Batman!";exit}NF{("cksum<<<'"'"'"substr(0,100ドル))|getline r;if(r!~/^6689751/)exit}{printf"I am a %s%."!NF"s!\n",NF?"caterpillar":"beautiful"," butterfly"}NF&&sub(/!NF/,10){print"echo|"0ドル}'<<'E'
> awk '/^xyz/{print"I am Batman!";exit}NF{("cksum<<<'"'"'"substr(0,100ドル))|getline r;if(r!~/^6689751/)exit}{printf"I am a %s%."!NF"s!\n",NF?"caterpillar":"beautiful"," butterfly"}NF&&sub(/!NF/,10){print"echo|"0ドル{'
> E
I hope the 20% applies for any string starting with xyz
, otherwise the original count is (削除) 224 (削除ここまで) (削除) 212 (削除ここまで) 210 bytes (fixed the "I am Batman!"
part).
Transformation done: replaces the only occurrence of the literal !NF
with 10
, so that " butterfly"
is also printed using the printf
.
Performs a simple cksum
on a portion (i.e. the remainder) of the source code, hence its requirement as well.
(削除) Caveat: first input must end with Not so much a caveat as to suppress wrong input...'
. (削除ここまで)
No second input is expected.
-
1\$\begingroup\$ WHOA. I was waiting for the awk person, and that's it. That's pretty cool. \$\endgroup\$jrg– jrg2015年10月08日 21:19:04 +00:00Commented Oct 8, 2015 at 21:19
Python - 184 bytes -20% for bonus = 147.2
""""""
import sys;c=sys.stdin.read();print"I am a caterpillar!";x=c[3:] if"\'''"!=c[:3] else c
print x+c[:3]
""";print"I am a beautiful butterfly!" """
''';print"I am Batman";'''
To print I am batman
, replace the first three double quotes with single quotes in the input.(First line is '''"""
)
FMSLogo, 169.6 bytes
from 212 * 0.8
to f[:b]1
type[I am]type char 32 ifelse name? "b[make "b last :b
print[a caterpillar!;beautiful butterfly
](foreach[23 8 19 2][10 32 13 97][repeat ?2[ignore pop "b]repeat ?1[type pop "b]])][print[Batman!]]print "
The online logo interpreters I know of do not support every logo feature this program is using. calormen.com, for example, does not support anonymous functions. The program works on FMSLogo 8.3.2.
Luckily for readability, the newlines are either necessary or have no cost. The program, in caterpillar form, is a variadic function which defaults to 1 argument. Pass the program code to it by pasting it between the bars in f "||
.
It will print "I am a caterpillar!", then splice together the output program from its own parts character by character by popping from the string. It will output this:
type[I am]type char 32 print[a beautiful butterfly!]
I should change the type char 32
part, but then the splicing code will look less epic.
In Batman form, achieved by replacing to
with ;
, thereby commenting out the function header, the Program will run when you load the file, and obviously not take input. For me, non-declarative code pasted into the edit window runs twice, but loading it as a file will still make it run once. To decide whether it is Batman, the program checks whether the input variable exists.
morsecco: (削除) 190 (削除ここまで) 193 bytes
Morsecco itself ignores those boring strings without any dots or dashes, but if you provide it as input, why not use it and modify it?
I am a caterpillar!beautiful butterfly!. .-. - - . - .-. -... -.. --.. --.- --.- -.-. -..-- - - --- -.-. --- - .. -.-. -.-.. - .-. -.-. . . . - . -.- .- -.-. .... . -.- - --- -.-. ... ---
. .-. - - . - .-.
toR
ead the own source code and stdin-... -.. --.. --.- --.-
for aB
inaryD
iff and toZ
eroskip theQ
uit if it's identical-.-. -..-- - - ---
C
uts the caterpillar string, keeps a copy andO
utputs it-.-. --- - .. -.-. -.-.. - .-. -.-. .
gets rid of the caterpillar and sets in the butterfly. . - . -.- .- -.-. ....
K
onverts from·T
ext to hide the butterfly in the caterpillar. -.- - --- -.-. ... ---
finallyC
oncatenates the code for butterflyO
utput and put this codeO
ut.
Other languages may need to do some ASCII art now, but the output of the code (if given the correct source, otherwise silently quit) will be:
I am a caterpillar!
. -..-..- -..... --....- --.--.- -..... --....- -..... --...-. --..-.- --....- ---.-.- ---.-.. --.-..- --..--. ---.-.- --.--.. -..... --...-. ---.-.- ---.-.. ---.-.. --..-.- ---..-. --..--. --.--.. ----..- -....- -.- - ---
and honestly: It looks a little like crawling caterpillars anyhow! Maybe like a millipede, but you wouldn't expect this to turn into a butterfly, wouldn't you? But execute it with morsecco and be surprised about the metamorphosis!