This is the companion thread to the main Unscramble the Source Code challenge. If you think you have managed to unscramble one of the cop answers, you should post your solution as the answer to this thread.

As a reminder, you have one attempt at cracking each submission. Your cracking attempt will be an unscrambled version of the source code. If your guess matches the description (same characters, output, and of course language), and you are the first correct guess, then you win a point. It is important to note that your program does not have to exactly match the original, simply use the same characters and have the same functionality. This means there could be more than one correct answer.

\$\begingroup\$Very nice! I should have taken out two more characters from the string I guess. In my original I actually had the spaces still inside the string, but an mr before taking the length. Not that you wouldn't have figured that out as well at some point. ;)\$\endgroup\$
– Martin EnderNov 6 '14 at 10:30

\$\begingroup\$@Imray Because of short-circuiting - Python loads the tuple and checks if the tuple's value is true, since it's empty, it is false. The code to load the variable bciprt is never executed, so it never produces a NameError.\$\endgroup\$
– Mateon1Nov 10 '14 at 14:13

\$\begingroup\$Have a point :) For reference, original was print 2**2**2**2/2**2**2/2**2**2/2-2**2**2*2**2-22, but it's not surprising at all that more than one option is correct.\$\endgroup\$
– GeobitsNov 4 '14 at 20:33

That's 23 numbers, which was a strong indicator for repeating the block 22 times, as well as ending the block with . (duplicate top stack element), such that the previous result got left behind on the stack and such that the final iteration would appear on the stack twice. That's 22,{____.}/.

Now looking at the gaps, those turn out to be 4th powers (which is nice, because we have 4 and ?). More precisely, they are the fourth power of the index of the current number. So next we looked at which indices created a gap:

4,5,6,7, 12,13,14,15, 20,21,..?

In binary those are

00100
00101
00110
00111
01100
01101
01110
01111
10100
10101

They all have the third bit set, which means that the index is probably just bitwise-and'ed with 4 (which is nice again, because we can make another 4 with . and have a &). This works particularly well, because this operation results in either 0 or 4, and if we use that as the exponent we get either 1 or a fourth power, which is exactly what we need. So let's put that together:

22,{.4&?+.}/

Here is what the block does:

. # Duplicate current index
4 # Push a 4
& # Bitwise and
? # Raise index to resulting power
+ # Add to previous result
. # Duplicate for use in next iteration

Now there were two problems left: we had a stray , we didn't use yet, and the first iteration is a special case, in that there is no value from a previous iteration which we could add things to when encountering +. We found that thanks to an unrelated comment by user23013 who casually mentioned that GolfScript starts out with an empty string on the stack (if there's nothing on STDIN). So we could use that other , right at the beginning to turn that string into a 0, which was just what we needed as the start of the iteration.

\$\begingroup\$Props to Doorknob for being insanely misleading with print, only to split it up into p for printing, %r for regexes and i for case-insensitive regex matching.\$\endgroup\$
– Sp3000Nov 5 '14 at 19:15

fairly quickly, at which point I needed something that gives -6 after the comma, having $++$++$++$+=$~main$2 left.

The main catch is that $a, $m and $i are all NULL, so using them indirectly in variable variables, means they all point to the same variable. However, PHP seems to be doing some weird things about resolving variable variables. With normal variables you can do things like

echo $a+$a=2;

which prints 4 (the 2 is assigned to $a and then added to itself). But if I do the same with variable variables:

echo $$a+$$a=2;

I get 2, because now the first $$a is evaluate before the assignment.

In the end I managed to force some order by putting some increments on the RHS of the += which had to be evaluated before that addition-assignment. That way I got to 5 which I could then just bit-complement. Still... there are some mysterious things going on, and I have no idea why half the things I tried worked and didn't work.

\$\begingroup\$Btw. I hope all the dollar signs and the fact that all the letters for main were in the string mislead you a lot. Also, a rather unusual method for extracting {main}, I think ;-)\$\endgroup\$
– bwoebiNov 6 '14 at 1:58

\$\begingroup\$@bwoebi The main didn't really mislead me, after spotting exception, new and substr. I thought they would just be variable names. It took me a bit to come up with using variable variables and than I spent most of the time on figuring out some order of operations that would actually yield a 5 which I could complement without using another set of parentheses.\$\endgroup\$
– Martin EnderNov 6 '14 at 2:01

\$\begingroup\$Well, for next time, if there are more dollars than characters, it usually are variable variables. (In this case I also abused varvars to force left-to-right evaluation.) How long did it take you then to spot the substr new exception? Also by the way, I have deeper knowledge of the Zend engine, so I can perfectly explain to myself why things are evaluated in which order and that's nice for these challenges ;-) If there's a specific thing you don't get, I'll happily explain it to you.\$\endgroup\$
– bwoebiNov 6 '14 at 2:08

\$\begingroup\$@bwoebi Come in chat tomorrow, and we can talk about it, but I've spent long enough on this today. ;) As for your first question, exception was obvious, which left stray characters for substr and new lying around. It was literally the first thing I saw when starting to work on it.\$\endgroup\$
– Martin EnderNov 6 '14 at 2:12

I'm pretty sure this is nowhere near the original source. It's deterministic despite using rand.

Here is how this one works. $><< is just output. $pece60 and $win are undefined global variables, which therefore are just nil (and they allowed me to get rid of some extraneous characters). !$pece60 makes a true and to_s gives the string "true".

For ages, I tried getting a 2 or -2 to access that u in there, but then I realised I could just take the t, and call .succ(essor) on it to make a u.

rand with a nil parameter returns a random float in the interval [0,1). When using floats to index into strings, they get truncated to integers, so this will always return the first character.

Finally, I had a spare pair of [] so I just wrapped everything in it, because thankfully everything is an expression in Ruby.

Woohoo! This is my first crack at a code golf problem, and I don't have enough rep to comment on the original post. I immediately recognized the trick used, since I've actually found use for it in production code often. It took about 5 minutes to figure out most of the structure and a few hours to come up with the complete answer.

Explanation:

%q[] is an alternative method for creating strings. Parenthesis and curly braces may also be used.

String#to_i in Ruby accepts numbers in any base from 2 to 36. It will ignore the first character in the string which is not part of the number, so any extra characters can be "thrown away" after the space.

\$\begingroup\$I added a comment to the original answer for you.\$\endgroup\$
– FireFlyNov 14 '14 at 20:44

\$\begingroup\$This is awesome (and close to the intended answer), but technically not valid because it doesn't have output.\$\endgroup\$
– histocratNov 14 '14 at 20:59

\$\begingroup\$*facepalm Well I still had fun.\$\endgroup\$
– charredUtensilNov 14 '14 at 21:29

2

\$\begingroup\$@charredUtensil if you don't mind running your script for some more, I think the printing is just moving the p to before the expression. Presumably the remaining characters can be used to form the constants as you've done.\$\endgroup\$
– FireFlyNov 14 '14 at 21:34

\$\begingroup\$I don't actually need to run it again. The last few characters of the string can be rearranged without changing the result - p %q[zyfnhvjkwudebgmaclrsx].to_i(36)/51074892 I know I broke my actual cracking attempt though :)\$\endgroup\$
– charredUtensilNov 15 '14 at 6:32

CEGIK are all variables, which are pre-initialised to 12, 14, 16, 18, 20, respectively.

s converts the top stack element to a string.

Strings are technically just arrays of characters.

f is pretty magic. For the purpose of this answer, the simplified version is that, for an array a, some other value b and an operator g, the sequence abfg maps g(_,b) onto a (where each element of a goes into the _ slot).

/ is division and splitting arrays (amongst other things).

* is multiplication and array repetition (amongst other things).

% is modulo and some weird operation, which in the form ad% for array a and integer d takes every dth element of a (like Python's slicing with step width d).

# is exponentiation (amongst other things).

, turns numbers into ranges (from 0 to n-1) and returns the length of an array.

Okay, that out of the way...

It was fairly obvious that we needed , to turn a number into a range, because the only other way to get an array would have been to build a larger number and turn it into a character array with s - but then we couldn't have done any further arithmetic on it. And we need an array to do something with the fs.

I first assumed that the fs were used with # and %, but that would mean we would have needed a number around 90 to get the right amount of digits in the end. And also, this didn't explain what to do with s, and since the answer looked really golfy, I doubted user23013 just appended an s as an effective no-op somewhere to throw people off.

So I figured, maybe he isn't even keeping the numbers small with %, but instead he builds an array of huge numbers, concatenates their string representation with s, but then only picks some odd slice out of it with %. So I played around a bit with the following framework:

__*,_f#_f/s_%

(You can't do _f/ first, because that would yield zero for at least the first 12 elements.)

Where the _ are some permutation of the variables. I didn't try all of them before I got bored, and the main problem with this was that the resulting sequence of digits as always way too long.

At some point it occurred to me, that we wouldn't need such a large range (i.e. the product of two numbers), if instead we used the * to repeat the resulting string. Due to the mismatch of the parameters of * and % this would yield no repetition in the result:

_,_f#_f/s_*_%

This yielded results of a length very close to what I was looking for. I would have actually tried all 240 of them, but fairly quickly (third or fourth attempt), I stumbled upon

And I figured a match of the first six digits wouldn't be a coincidence. So the question was how to rearrange it without upsetting the actual computation:

I couldn't change K because that would pick out different digits altogether.

I couldn't change C or I because that would change the numbers resulting from the two map operations.

If I changed G that would only change the number of repetitions, which would do nothing but change the length of the result. (Which is good.)

If I changed E that would change the range of the array, but the range would still start with [0 1 2 3 ...], so it wouldn't affect the calculation. It would affect the length of the base string returned by s, which would also mean that K% would pick out different digits upon additional repetitions.

\$\begingroup\$Nice! For reference, the original was print(sum(map(ord,str((dict(list(((str(),str(dict())),))),list()))))), but obviously a lot of different permutations of keywords would work.\$\endgroup\$
– Sp3000Nov 5 '14 at 13:01

From the given characters, I guessed it had to be one of the three following forms:

__,{_%}%{_+}%:+
_,{_%}%{__+}%:+
__,{_+}%{_%}%:+

which creates a two-digit range, then maps an addition and modulo operation (in either order) onto the range, before summing it. So I just started with the first one, and systematically tried permutations of 6789 in the gaps.

\$\begingroup\$In hindsight, I shouldn't have included the quotes... ;)\$\endgroup\$
– FryAmTheEggmanNov 5 '14 at 4:59

\$\begingroup\$@FryAmTheEggman Oh wow - nice program! I was convinced you had at least used dir() to find the 'get'. And yes, it would have been very difficult without the quotes.\$\endgroup\$
– grcNov 5 '14 at 5:04

\$\begingroup\$And I don't know how did you figure it out:) Original: _:print_r(chr(3*pow(2,5)+@++$i));if(@$i<4<<1)goto _;.\$\endgroup\$
– kenorbNov 5 '14 at 18:38

3

\$\begingroup\$@kenorb a) you need to print something, so echo not possible; print remained; b) you need some loop, but for a for loop, there weren't enough semicolons, and well, there's a colon... so probably a label there in combination with goto; c) then it needs an if to abort the goto-loop. Having now X:print($Y);if($Y)goto X; (X and Y being placeholders); d) there's a ++, but no =, so probably some ++$Z from 1 to 8; e) to get letters from an integer, we need chr() (usually) - it was there; f) now I just needed to find numbers 96 and 8 for chr and if. Then fill in placeholders and volià.\$\endgroup\$
– bwoebiNov 5 '14 at 18:47

The hard part ended up being to keep track of all the unneeded characters...seriously...I had to redo them about 10 times. The only one that worried me was the . but somehow I stuck it in the middle of the printf format string and it became invisible!

Note that this program must be run on a 32-bit machine. If you want to check that this is the correct program and you have a 64-bit machine, you can use this instead:

import Data.Int
main=print(0xb2f3d5^0x7f1f27::Int32)

It was pretty easy to guess the "frame" of the program main=print(0x<hex digits>^0x<hex digits>::Int). All the magic was in searching for the right way to partition and order the digits. I didn't do very much smart here, just a brute-force search... though I did take care to abuse the fact that some digits were duplicated, there were probably about an equal number of digits in the base and exponent, and the last digit of the base almost certainly wasn't even. The complete search code is included below; it uses the multiset-comb package. The full search takes about 10:33 on my machine (and produces only one right answer, of course).

Your Answer

If this is an answer to a challenge…

…Be sure to follow the challenge specification. However, please refrain from exploiting obvious loopholes. Answers abusing any of the standard loopholes are considered invalid. If you think a specification is unclear or underspecified, comment on the question instead.

…Try to optimize your score. For instance, answers to code-golf challenges should attempt to be as short as possible. You can always include a readable version of the code in addition to the competitive one.
Explanations of your answer make it more interesting to read and are very much encouraged.

…Include a short header which indicates the language(s) of your code and its score, as defined by the challenge.

More generally…

…Please make sure to answer the question and provide sufficient detail.

…Avoid asking for help, clarification or responding to other answers (use comments instead).

Code Golf Stack Exchange is a site for recreational programming competitions, not general programming questions. Challenges must have an objective scoring criterion, and it is highly recommended to first post proposed challenges in the Sandbox.