Rebmu: 79 chars OR (37 + length(p1) + 2 * max(length(p2), length(p3)))
First I'll give a 79 character solution that asks Which languages must you learn? (entropy 4.0, 30 letters not including ?
) and offers you the suggestions of Rebol and [Red]:
DD 11 DD :do dd {dd {p{Which languages must you learn?}qt}} pp{{[RReebdo]l}}
A unique tactic available here that isn't in other languages comes from taking advantage of the fact that curly braces are an asymmetric string delimiter, that can nest legally:
my-string: {"It's cool," said {Dr. Rebmu}, "for MANY reasons--like less escaping."}
That let me produce a generalized solution, that can work effortlessly on any program that doesn't use escape sequences. The 79 character version was simple enough to shortcut, but to properly contain arbitrary program source for programs p2 and p3 you'd need the full template. Had we used that, it would have been 87 characters:
DD 11 DD :do dd {dd {p{Which languages must you learn?}qt}} ddoo{{pp{{[RReebdo]l}}}}
The pattern for using this general form is that if you have three source texts of sequential characters of variable lengths (let's use an example like AAA
, BBBBB
, CCCCCCC
) you can encode them as something along the lines of:
DD 11 DD :do dd {dd {AAAqt}} ddoo{{BCBCBCBCBC C C}}
(Note: Although this pattern won't work without tweaking on programs that use escape characters, this is not a fatal flaw. Getting an unmatched left brace in a string delimited by braces requires something like {Foo ^{ Bar}
...but you could easily rewrite that using the alternative string notation "Foo { Bar"
, and combined cases can be managed with gluing together a mixture of unescaped strings.)
So...how about an example? Once the general form was available, this 573 character program was assembled in only a couple of minutes from 3 prior code golf solutions:
DD 11 DD :do dd {dd {rJ N 0% rN Wa1m2j S{ \x/ }D00 Hc&[u[Ze?Wa Qs~rpKw[isEL00c[skQd2k][eEV?kQ[tlQ]]pcSeg--b00[eZ 1 5]3]prRJ[si~dSPscSqFHs]eZ 1[s+dCa+wM2cNO]]]Va|[mpAp2j]prSI~w{}Ls2w Wl h01tiVsb01n -1 chRVs{}hLceVn01qt}} ddoo{{BrdSz [fcebC[sn[{N sbeo[tIt0l1eV}0e5gXN1 01L{5s0}C{1}0{0 Do5f0 0bMe1e0r0}0]]]tMw9C9 Numz Jl[paN+[KperlCJBn[[ba sWS{B noJn Nt0h0e] jw]aJlnl]}aCd{K,j } b P { . } l f E Z - - n [ N m { G o t o t h e s t o r e a n d b u y s o m e m o r e } ] { T a k e o n e d o w n a n d p a s s i t a r o u n d } c B w P l f ] ] }}
If anyone wants to try writing that program in their language of choice, and thinks they can beat 573, let me know. I will bounty you a heavy amount of reputation if you do--assuming your language of choice is not Rebmu, because I know those programs aren't minimal. :-)
That "wasteful" spacing you get at the end is what happens when p2 and p3 are of imbalanced lengths. But all 3 programs are different sizes in this case so there isn't a particular good pairing to pick for p2/p3. (I picked these because there was no external data as input, such as a maze or whatever, not that they were of similar lengths. While I could have written new programs that were more optimal, I've spent enough time and the point was you don't have to write new programs...)
How it works
(Note: I started with a more "creative" approach that was not as streamlined but more interesting-looking. I moved it to an entry on my blog as describing this approach is already long.)
A key here is the "eval code as a string" trickery like some other entries, it just has the trump card of the asymmetric string delimiter. I'll start by explaining the workings of the 80 character case.
Here's the "whole" program, adjusting the whitespace for this case's readability:
DD 11 ; assign 11 to dd (about to overwrite again)
DD :do ; make dd a synonym for DO (a.k.a. "eval")
; eval a string as source code that ends with QUIT (QT)
dd {dd {p{Which languages must you learn?}qt}}
; we'll never get here, but whatever's here must be legally parseable
pp{{[RReebdo]l}}
Here we wind up setting DD to a synonym for DO (a.k.a. "eval"). But the trick is that when the halved programs run, they wind up running code whose only effect is to define D to the harmless literal 1.
Here's what the odd-chars code makes, whitespace again adjusted:
D 1 ; assign 1 to d
D d ; assign d to itself, so it's still 1
d ; evaluates to integer, no side effect
{d pWihlnugsms o er?q} ; string literal, no side effect
p {Rebol} ; print "Rebol"
And here's the even-chars code:
D 1 ; assign 1 to d
D:od ; URL-literal (foo:...), no side effect
d ; evaluates to integer, no side effect
{{hc agae utyulan}t} ; string literal (well-formed!), no side effect
p {[Red]} ; print "[Red]"
It's actually the case that for the non-halved program, the dd {dd {(arbitrary code)qt}}
will execute whatever code you want. However, there are two calls to evaluate instead of just one. That's because while the nested braces work great in the interleaved code, they mess up the eval behavior of DO. Because:
do {{print "Hello"}}
Will load the string as a program, but that program winds up being just the string constant {print "Hello"}
. Thus the trick I use here is to take my DD (holding the same function value as DO) and run it twice. The halvers chew at the different parts of the string but they don't chew both if the even/oddness is correct for the content, and because what's left outside the string after halving is just the integral constant d
they're harmless.
With this pattern there's no challenge in writing the program behavior when it's not cut in half--you can put in anything as long as the character length of the code is even (odd if you're counting the QT, which is QUIT). If you need to get the even number from an odd one, throw in a space (so there's actually a +1 in my formula above on p1 for odd program lengths of p1). The trick would seem to write that interleaved code afterwards, which must pass the parser if it isn't halved. (It won't be run because of the QT, but it has to be LOADable before it will be executed.)
This case is trivial; pp
loads fine as a symbol even though it's undefined, and is split into p
for print in each half program. But we can do another trick just by using a string literal again. The halved programs still have DO defined normally, so we could also have just said:
ddoo{{pp{{[RReebdo]l}}}}
By having the only part picked up by the parser in the whole case be the symbolic word ddoo
and a string literal, we can then interleave any two programs we wish inside that string literal and not anger the parser. The halved versions will just say:
do{p{Rebol}}
..and...
do{p{[Red]}}
As I say, this part looks familiar to other solutions that treat programs as strings and eval them. But in the competition's case, when the programs you're packing contain nested strings, that throws in wrenches for them. Here the only things that will get you in trouble are use of escaping via carets (^
)...which can be easily worked around.
(Small 'cheating' note: I added QT for "QUIT" in response to this problem. Actually, I had purposefully removed the abbreviation for quit before...because somehow I thought it was only good for console use and just taking up the two-letter space if it wasn't in a REPL. I'm adding it because I see I was wrong, not adding it for this case in particular. Nevertheless, prior to that change it would have been 2 characters longer. Also, when I first posted the solution there was a bug in Rebmu that kept it from actually working even though it should have...now it works.)
Are there any practical uses for something like this? No disrespect intended; just curious. – voices – 2016-05-25T09:53:50.730
6Gah, this is so hard to do in a "normal" language like JavaScript. The farthest I can get is something like
x0=00;;
. Great challenge! – Doorknob – 2014-08-11T01:34:13.700@Doorknob sorry to deflate your boat, but
00;
is traditionally ignored by the compiler... – John Dvorak – 2014-08-11T06:05:37.8172Seriously... "apple" has a Shannon entropy of 1.92??? – John Dvorak – 2014-08-11T06:10:53.200
@JanDvorak
00;
is fine. I mainly just meant to restrict comments. – Calvin's Hobbies – 2014-08-11T06:19:19.9104
It may have an odd or even number of characters
Is there a number of characters that is not odd or even? – Snack – 2014-08-11T06:27:22.6771@Snack That lets people know that the two answer code parts don't need to have the same length. – Calvin's Hobbies – 2014-08-11T06:30:49.607
Can I write to a file as output? – Οurous – 2014-08-11T07:35:22.320
@Ourous Sure. I might as well remove the "output to stdout" restriction since it might loosen up the problem. – Calvin's Hobbies – 2014-08-11T07:42:18.553
Interesting problem...though I was enjoying it a bit more before I wound up going in the "eval" direction. Perhaps there could be a similar problem of three different outputs, that's a bit more challenging in terms of what's different about the programs, and disallowed eval of code as strings? – HostileFork says dont trust SE – 2014-08-12T15:17:56.300
I was just reading the question, and I think that your third example answer may be reversed. – Magus – 2014-08-12T22:08:05.523
@Magus How so exactly? – Calvin's Hobbies – 2014-08-13T02:17:58.687
Nevermind, got the joke. Must've been blind yesterday. – Magus – 2014-08-13T14:30:25.767
This is insane! It's hard to believe it's even possible, yet look at all the answers! – GreenAsJade – 2014-08-14T12:59:53.430
Hate to nitpick, but it's a tall order to put specific requirements on the entropy contents. Firstly, one can't talk about entropy of a message without a context involving an a priori probability distribution over the messages (and not just the observed probability of individual chars in one msg). The closest objective measurement of complexity (which is of course related to entropy) is Kolmogorov complexity, but it can not be calculated by any program, including the calculator you link to. – Morty – 2014-08-17T21:01:10.473
@Morty I know the entropy restraint isn't perfect but it seems the easiest way to ensure people don't give potentially trivial repetitive answers. – Calvin's Hobbies – 2014-08-17T21:38:49.953
@Calvin: My sympathies for that. But the wording of the question gives the impression that the requirement is for the actual entropy in the string, not the entropy using some specific calculator. Besides, the whole way this calculator works is based on a huge misunderstanding of what entropy is, IMHO. – Morty – 2014-08-18T05:16:02.190