The Challenge

I present to you another spy vs. spy challenge pitting obfuscators versus crackers. In this case, however, the datum to be protected is not an input but an output.

The rules of the challenge are simple. Write a routine with the following specifications:

  1. The routine may be written in any language but may not exceed 320 bytes.
  2. The routine must accept three 32-bit signed integers as inputs. It can take the form of a function that accepts 3 arguments, a function that accepts a single 3-element array, or a complete program that reads 3 integers from any standard input.
  3. The routine must output one signed 32-bit integer.
  4. Over all possible inputs, the routine must output between 2 and 1000 (inclusive) unique values. The number of unique values a routine can output is called its key.

As an example, the C program

int foo( int i1, int i2, int i3 ) {
    return 20 + (i1^i2^i3) %5;

has a key of 9, since it (hopefully) can only output the nine values 16,17,18,19,20,21,22,23, and 24.

Some additional limitations are as follows:

  1. The routine must be fully deterministic and time-invariant, returning identical outputs for identical inputs. The routine should make no call to pseudorandom number generators.
  2. The routine may not rely on "hidden variables" such as data in files, system variables, or esoteric language features. For example, routines should generally not refer to constants unless the constants are clearly defined in the code itself. Routines that rely on compiler quirks, outputs from mathematically undefined operations, arithmetic errors, etc. are also strongly discouraged. When in doubt, please ask.
  3. You (the coder) must know precisely how many unique outputs the routine can produce, and should be able to provide at least one input sequence that produces each output. (Since there can potentially be hundreds of unique outputs, this set would only ever be requested in the event your key is contested.)

Since this problem bares far less resemblance to classical encryption than the previous one, I expect it will be accessible to a broader audience.

The more creative, the better.

The Scoring

The shortest non-cracked submission(s) per byte count will be declared the winner(s).

If there's any confusion, please feel free to ask or comment.

The Counter-Challenge

All readers, including those who have submitted their own routines, are encouraged to "crack" submissions. A submission is cracked when its key is posted in the associated comments section. If a submission persists for 72 hours without being modified or cracked, it is considered "safe" and any subsequent success in cracking it will be ignored for sake of the contest.

Only one cracking attempt per submission per reader is permitted. For example, if I submit to user X: "your key is 20" and I'm wrong, user X will disclaim my guess as incorrect and I will no longer be able to submit additional guesses for that submission.

Cracked submissions are eliminated from contention (provided they are not "safe"). They should not be edited. If a reader wishes to submit a new routine, (s)he should do so in a separate answer.

A cracker's score is the number of submissions (either compliant or not) (s)he cracks. For crackers with identical counts, the ranking is determined by total byte count across all cracked submissions (the higher, the better).

The cracker(s) with the highest score(s) will be declared the winners along with the developers of the winning routines.

Please do not crack your own submission.

Best of luck. :)


Last Updated Sept 2, 10:45 AM EST

Immovable Barriers (non-cracked submissions):

  1. CJam, 105 [Dennis]

Unstoppable Forces (crackers):

  1. Dennis [Java, 269; C, 58; Mathematica, 29]
  2. Martin Büttner [Java, 245]
  • 11
    \$\begingroup\$ May I suggest [cops-and-robbers] as the tag for these challenges? I think it's a fairly established name for such games in security and it will probably provoke more interest then [adversarial]. \$\endgroup\$ Commented Aug 31, 2014 at 9:01
  • \$\begingroup\$ Sure. I'll change it now. \$\endgroup\$
    – COTO
    Commented Aug 31, 2014 at 9:02
  • \$\begingroup\$ What kind of output is acceptable? STDOUT, return, etc... \$\endgroup\$
    – Ypnypn
    Commented Aug 31, 2014 at 21:01
  • 2
    \$\begingroup\$ Your example is incorrect; its signature is 9. %5 can return anything from -4 to 4, inclusive. \$\endgroup\$ Commented Sep 1, 2014 at 5:07
  • 1
    \$\begingroup\$ @Dennis I would be fine with you trying again. It was my fault that it was messed up. \$\endgroup\$ Commented Sep 1, 2014 at 22:25

7 Answers 7


CJam, 105 bytes

M-8M-^^M-n$4M-^M^SM-x M-OM-^@^?"256b@D#Y256#%2+md!A3#*)%)%

The above uses caret and M notation, since it contains unprintable character. After converting the byte stream into an integer (256b), the following code gets executed:


You can try this version online in the CJam interpreter.

How it works

This submission uses number theory instead of obfuscation. The program will return 0 for almost all inputs. From the few inputs that result in a non-zero output, a secret modulus is derived that is applied to the 10 least significant bits of the third integer.

The most efficient way of solving this challenge (that I can think of) would be factorizing the 512 bit integer, which I hope won't be achievable in 72 hours.

" Prepend 1 to the numbers read from STDIN and convert the resulting array into an integer
  (“N”) by considering them digits of a base 2**32 number.                                 ";


" Compute “N / 1024” and “N % 1024”.                                                       ";


" Push a carefully selected 512 bit semi-prime (“S”).                                      ";


" Compute P = (N / 1024) ** 13 % 2 ** 256 + 2.                                             ";


" Compute “S / P” and “S % P”.                                                             ";


" Compute “M = (S / P) % (1000 * !(S % P) + 1) + 1”.

  “M” is the key if P is a divisor of S; otherwise, “M == 1”.                              ";


" Compute the final output: “N % 1024 % M”.                                                ";


Example run

$ base64 -d > outputs.cjam <<< MXF+XTRHI2IyQSNtZCLrGNdI7gewJfV355hl65ZPEGgsjZDxobjBz/50huPoAbCw7MCbTUY9mhOxy9QyudVtU84KuJ7uJDSNE/ggz4B/IjI1NmJARCNZMjU2IyUyK21kIUEzIyopJSkl
$ wc -c outputs.cjam
105 outputs.cjam
$ LANG=en_US cjam outputs.cjam < outputs.secret; echo
$ LANG=en_US cjam outputs.cjam <<< '1 2 3'; echo
  • \$\begingroup\$ You're just too darn good with the encryption stuff. ;) \$\endgroup\$
    – COTO
    Commented Sep 1, 2014 at 6:54
  • 11
    \$\begingroup\$ "This submission uses number theory instead of obfuscation." Looks at code "Hmm, right." \$\endgroup\$ Commented Sep 1, 2014 at 16:34

Java - 269

Thanks for everyone's patience, this should now be fixed.


int a(int a,int b,int c){double d=180-360.0/(int)(Math.abs(Math.sin(a*60))*50+2),e=180-360.0/(int)(Math.abs(Math.cos(b*60))*50+2),f=180-360.0/(int)(Math.atan2(c*60, a*60)*51+2);if(Math.abs(d+e+f-360)<.1)return Integer.valueOf((int)d+""+(int)e+""+(int)f);else return 1;}

Not shortened:

int a(int a, int b, int c) {
    double d = 180 - 360.0 / (int) (Math.abs(Math.sin(a * 60)) * 50 + 2);
    double e = 180 - 360.0 / (int) (Math.abs(Math.cos(b * 60)) * 50 + 2);
    double f = 180 - 360.0 / (int) (Math.atan2(c * 60, a * 60) * 51 + 2);
    if (Math.abs(d + e + f - 360) < .1)
        return Integer.valueOf((int) d + "" + (int) e + "" + (int) f);
        return 1;
  • \$\begingroup\$ You can save four characters by changing double e,f,d=...;e=...;f=...; to double d=...,e=...,f=...; \$\endgroup\$
    – Ypnypn
    Commented Sep 1, 2014 at 0:17
  • \$\begingroup\$ @Ypnypn Thanks! added to golfed version. \$\endgroup\$ Commented Sep 1, 2014 at 0:28
  • 1
    \$\begingroup\$ Second attempt (with explicit permission): 122 \$\endgroup\$
    – Dennis
    Commented Sep 1, 2014 at 23:18
  • 1
    \$\begingroup\$ @Dennis nice job! (That's it) \$\endgroup\$ Commented Sep 1, 2014 at 23:46
  • 1
    \$\begingroup\$ @Dennis In that case, you're forgetting 1 and your answer is incorrect as well ;) (123 being correct... someone come along and grab the cracking score...). And I guess Stretch Maniac didn't account for sin == 1.0 when he said that 122 is correct. \$\endgroup\$ Commented Sep 2, 2014 at 15:00

A Sampler

Not an official entry of course, and the character count is too high, but I figure if anyone wants a mind-numbing challenge, they can try to determine how many unique outputs the following function produces (given three inputs as described in the OP):

function z(y,_,$){M=[];N=[];O=[];C=1792814437;P=72;r=t=0;(f=function(a,k,L){if(k<a.length){for(L=a[k],a[k]=0;a[k]<L;a[k]++)f(a,k+1)}else
!(a[0]-a[1]))||1))||(s|=N[(a[0]+1)*a[1]+a[3]]);})([],0,0);return r;}

In fact, I'm so confident that it's uncrackable, I'll award anyone who cracks it the "Supreme Unstoppable Force of Nature Award".

Because really, they deserve it.

  • 1
    \$\begingroup\$ You should put up a bounty for it! \$\endgroup\$
    – Orby
    Commented Sep 1, 2014 at 3:37
  • 1
    \$\begingroup\$ @Orby That would be nice, but it's hard to award a bounty to a comment. \$\endgroup\$
    – Geobits
    Commented Sep 1, 2014 at 4:29
  • \$\begingroup\$ I added some indentation to this. \$\endgroup\$ Commented Sep 1, 2014 at 18:05
  • \$\begingroup\$ @COTO is this challenge still on? \$\endgroup\$ Commented Sep 15, 2014 at 18:55
  • \$\begingroup\$ @SohamChowdhury: Absolutely. If you figure it out, I'll expound your victory in the OP. If not, let me know and I'll post the solution. \$\endgroup\$
    – COTO
    Commented Sep 15, 2014 at 22:08

C, 58 bytes (Cracked)

A simple one:

f(a,b,c){return(long long)a*b*c-0x1d21344f8479d61dLL?0:a;}
  • 2
    \$\begingroup\$ 7 (-15485867, -1299721, -104287, 0, 104287, 1299721, 15485867). \$\endgroup\$
    – Dennis
    Commented Sep 1, 2014 at 5:55
  • \$\begingroup\$ That was fast :) \$\endgroup\$
    – Orby
    Commented Sep 1, 2014 at 5:56

Java - 245

Cracked by Martin Büttner

int a(int[]_$){return $($($_(_$[0],0)))+$_(_$[1],1)*11+$($($_(_$[1+1],0)))*(1+1);}int $_(int $,int $_){int OO=0,o=1,O=1;for($=$<0?-$:$;++O*O<=$;OO+=$%O<1?O:0,o+=$%O<1?1:0,$/=$%O<1?O--:1);return $_>0?o:OO+$;}int $(int $){return(int)Math.sqrt($);}

Feed the input as an int array: a(new int[]{1,2,3}). I'm not expecting it to go 72 hours, but have fun with it.

Here it is with line breaks, to make it a bit more readable:

int a(int[]_$){return $($($_(_$[0],0)))+$_(_$[1],
1)*11+$($($_(_$[1+1],0)))*(1+1);}int $_(int $,int
$_){int OO=0,o=1,O=1;for($=$<0?-$:$;++O*O<=$;OO+=
$%O<1?O:0,o+=$%O<1?1:0,$/=$%O<1?O--:1);return $_>
0?o:OO+$;}int $(int $){return(int)Math.sqrt($);}
  • \$\begingroup\$ Just from bruteforcing... 90? \$\endgroup\$
    – Vectorized
    Commented Sep 1, 2014 at 6:23
  • \$\begingroup\$ @bitpwner Nope, sorry. \$\endgroup\$
    – Geobits
    Commented Sep 1, 2014 at 6:27
  • 1
    \$\begingroup\$ I deobfuscated it a bit: pastebin.com/8pvvfFYB (I hope I didn't make any mistakes while replacing variable names.) \$\endgroup\$ Commented Sep 1, 2014 at 10:44
  • 4
    \$\begingroup\$ Okay, here is my attempt: 965? \$\endgroup\$ Commented Sep 1, 2014 at 11:35
  • 1
    \$\begingroup\$ @MartinBüttner Correct. Thanks for the obfuscated version :D \$\endgroup\$
    – Geobits
    Commented Sep 1, 2014 at 15:18

Mathematica, 29 bytes, Key: 715, Cracked by Dennis

This is just a fixed version of my initial answer, which didn't work for non-positive inputs.


Takes a list of integers like

  • \$\begingroup\$ I found 349 unique outputs. The range was from 3 to 717. \$\endgroup\$
    – PhiNotPi
    Commented Sep 1, 2014 at 11:57
  • \$\begingroup\$ @PhiNotPi Wrong. (I double-checked) \$\endgroup\$ Commented Sep 1, 2014 at 12:00
  • \$\begingroup\$ Well, I found my mistake and the right answer. Too late though. \$\endgroup\$
    – PhiNotPi
    Commented Sep 1, 2014 at 12:25
  • 1
    \$\begingroup\$ If the stuff I pieced together from the Mathematica documentation and WolframAlpha is correct, the key is 715 (3 ... 717). \$\endgroup\$
    – Dennis
    Commented Sep 1, 2014 at 16:18
  • 2
    \$\begingroup\$ Mathematica looks like a nice language, but it's either too darn expensive or I'm too darn cheap... \$\endgroup\$
    – Dennis
    Commented Sep 1, 2014 at 16:23

207 characters, in C/C++, not yet obfuscated:

int x(int a, int b, int c) {
    int d, e, f;
    for (int i=0; i!=1<<31; ++i) {
        a += d;
        b += e;
        c += f;
    return ((a%5+5)*10+(b%5+5))*10+c%5+5;
  • \$\begingroup\$ Just trying my luck... 729. \$\endgroup\$
    – Vectorized
    Commented Sep 1, 2014 at 8:14
  • \$\begingroup\$ @bitpwner Damn, I was just gonna say that. :D ... If that's wrong, that's the upper bound though. \$\endgroup\$ Commented Sep 1, 2014 at 8:15
  • 2
    \$\begingroup\$ This is not a valid submission. All assignments inside the loop may result in signed integer overflow, which has undefined behavior. \$\endgroup\$
    – Dennis
    Commented Sep 1, 2014 at 23:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.