The Challenge

A simple "spy versus spy" challenge.

Write a program with the following specifications:

  1. The program may be written in any language but must not exceed 512 characters (as represented in a code block on this site).
  2. The program must accept 5 signed 32-bit integers as inputs. It can take the form of a function that accepts 5 arguments, a function that accepts a single 5-element array, or a complete program that reads 5 integers from any standard input.
  3. The program must output one signed 32-bit integer.
  4. The program must return 1 if and only if the five inputs, interpreted as a sequence, match a specific arithmetic sequence of the programmer's choosing, called the "key". The function must return 0 for all other inputs.

An arithmetic sequence has the property that each successive element of the sequence is equal to its predecessor plus some fixed constant a.

For example, 25 30 35 40 45 is an arithmetic sequence since each element of the sequence is equal to its predecessor plus 5. Likewise, 17 10 3 -4 -11 is an arithmetic sequence since each element is equal to its precessor plus -7.

The sequences 1 2 4 8 16 and 3 9 15 6 12 are not arithmetic sequences.

A key may be any arithmetic sequence of your choosing, with the sole restriction that sequences involving integer overflow are not permitted. That is, the sequence must be strictly increasing, strictly decreasing, or have all elements equal.

As an example, suppose you choose the key 98021 93880 89739 85598 81457. Your program must return 1 if the inputs (in sequence) match these five numbers, and 0 otherwise.

Please note that the means of protecting the key should be of your own novel design. Also, probabilistic solutions that may return false positives with any nonzero probability are not permitted. In particular, please do not use any standard cryptographic hashes, including library functions for standard cryptographic hashes.

The Scoring

The shortest non-cracked submission(s) per character 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 programs, 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.

See "Disclaimer" below for details on the updated cracking score policy.

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

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

Please do not crack your own submission.

Best of luck. :)


Penultimate standings (pending safety of Dennis' CJam 49 submission).

Secure Lockers

  1. CJam 49, Dennis
  2. CJam 62, Dennis safe
  3. CJam 91, Dennis safe
  4. Python 156, Maarten Baert safe
  5. Perl 256, chilemagic safe
  6. Java 468, Geobits safe

Unstoppable Crackers

  1. Peter Taylor [Ruby 130, Java 342, Mathematica 146*, Mathematica 72*, CJam 37]
  2. Dennis [Pyth 13, Python 86*, Lua 105*, GolfScript 116, C 239*]
  3. Martin Büttner [Javascript 125, Python 128*, Ruby 175*, Ruby 249*]
  4. Tyilo [C 459, Javascript 958*]
  5. freddieknets [Mathematica 67*]
  6. Ilmari Karonen [Python27 182*]
  7. nitrous [C 212*]

*non-compliant submission

Disclaimer (Updated 11:15 PM EST, Aug 26)

With the scoring problems finally reaching critical mass (given two thirds of the cracked submissions are thus far non-compliant), I've ranked the top crackers in terms of number of submissions cracked (primary) and total number of characters in compliant cracked submissions (secondary).

As before, the exact submissions cracked, the length of the submissions, and their compliant/non-compliant status are all marked so that readers may infer their own rankings if they believe the new official rankings are unfair.

My apologies for amending the rules this late in the game.

  • 6
    \$\begingroup\$ How are you going to verify that programs meet point 4? Do you expect people to edit their safe answers to add a proof? Are probabilistic submissions permitted on the basis of assuming that hash functions are ideal and the chance of a collision with another element of the 48-bit (according to your estimate above) space is negligible? \$\endgroup\$ – Peter Taylor Aug 25 '14 at 8:41
  • 2
    \$\begingroup\$ The scoring system seems to encourage crackers to ignore the shortest locks because they score better by cracking two long locks than two small ones. \$\endgroup\$ – Peter Taylor Aug 25 '14 at 17:37
  • 3
    \$\begingroup\$ @COTO I think the problem is that you can only get 2 cracking scores, and only the shortest. So why not wait and hope and longer one shows up? For example, Martin now has no incentive to crack my (longer) lock, since he's already cracked two shorter ones. Anyone who cracks mine will now beat him without even having to do a second one. \$\endgroup\$ – Geobits Aug 25 '14 at 17:51
  • 1
    \$\begingroup\$ I think a better scoring system might be sum of total times between question and crack. That way, cracking a bunch of easy ones can be beaten, and the real reward comes from cracking the really hard ones. \$\endgroup\$ – isaacg Aug 25 '14 at 21:52
  • 1
    \$\begingroup\$ I'm new to golfing, so maybe it's a stupid question, sorry for that. Why is the code length measured in characters and not in bytes? The latter is literally the memory space that a program occupies, so for me it seems more logical. Eg. the CJam answer is the shortest in characters, but when looking at its size (326 because of unicode) it isn't even in the top 5. So I wonder, is it common convention in golfing to count chars instead of bytes? \$\endgroup\$ – freddieknets Aug 26 '14 at 13:30

31 Answers 31


CJam, 62 characters


Stack Exchange is prone to mauling unprintable characters, but copying the code from this paste and pasting it in the CJam interpreter works fine for me.

How it works

After replacing the Unicode string with an ASCII string, the following code gets executed:

" Push 85, read the integers from STDIN and collect everything in an array.               ";


" Convert the array of base 4**17 digits into and array of base 2 digits.                 ";


" Split into chunks of length 93 and 84.                                                  ";


" Do the following 611 times:

    * Rotate array A (93 elements) and B one element to the left.
    * B[83] ^= B[14]
    * T = B[83]
    * B[83] ^= B[0] & B[1] ^ A[23]
    * A[92] ^= A[26]
    * Rotate T ^ A[92] below the arrays.
    * A[92] ^= A[0] & A[1] ^ B[5].                                                        ";


" Discard the arrays and collects the last 177 generated bits into an array.              ";


" Convert the into an integer and check if the result is 922 ... 593.                     ";


This approach uses Bivium-B (see Algebraic analysis of Trivium-like ciphers), a weakened version of the stream cipher Trivium.

The program uses the sequence of integers as initial state, updates the state 434 times (354 rounds achieve full diffusion) and generates 177 bit of output, which it compares to those of the correct sequence.

Since the state's size is precisely 177 bits, this should suffice to uniquely identify the initial state.

Example run

$ echo $LANG
$ base64 -d > block.cjam <<< IgThuKHqrLzsj4nlo6XrlqjhiKTrrabjqpDqjaHjoanmipjvpb7itozuoIDtjK3rrbLul7bkr6zqgKvvjafpg6/im4XlvajqhIfrso3uprrotbfvmL/hnqPojqjguonhhp7mtoHujLPuipzlkaLpspLssJzii5npn6rpsLTqn5PkmKbspYbnlq3itorlh4Pmj60iMkcjYjEyOWI6Y34=
$ wc -m block.cjam
62 block.cjam
$ cjam block.cjam < block.secret; echo
$ cjam block.cjam <<< "1 2 3 4 5"; echo

CJam, 91 characters


Stack Exchange is prone to mauling unprintable characters, but copying the code from this paste and pasting it in the CJam interpreter works fine for me.

How it works

After replacing the Unicode string with integers (by considering the characters digits of base 65533 numbers), the following code gets executed:

" Read the integers from STDIN and collect them in an array.                               ";


" Convert it into an integer by considering its elements digits of a base 20**20 number.   ";


" Elevate it to the 13th power modulus 252 ... 701.                                        ";


" Check if the result is 202 ... 866.                                                      ";


Since 13 is coprime to the totient of the modulus (the totient is secret, so you'll just have to trust me), different bases will generate different results, i.e., the solution is unique.

Unless someone can exploit the small exponent (13), the most efficient way of breaking this lock is to factorize the modulus (see RSA problem). I chose a 512-bit integer for the modulus, which should withstand 72 hours of factorization attempts.

Example run

$ echo $LANG
$ base64 -d > lock.cjam <<< cX5dS0sjYkQjIgHuiJHhq5bgv7zrk4velOWUse6zjuCtpuW7veK7ju2Ci+uOouWHjOG4ju+Rh+uBruWGleyYt+u/ueavs+6boOyKn+Wkq86i55yY6Je46Lqm5KqV6b2D5Zmz75Wp5Y2kIjY1NTMzOkJiJSIB6JCX57ik4aSe74aS6ZuR54eg4Y+G44ii6q2Z44i244K/5pWr5Jm/5aiy7ZuU7JOt67KT7rO26IS/57+g4p2275+K7IWt5Ymu7Kyt546T4K2C7IGs5IiG77mM4quM56ifIkJiPQ==
$ wc -m lock.cjam
91 lock.cjam
$ cjam lock.cjam < lock.secret; echo
$ cjam lock.cjam <<< "1 2 3 4 5"; echo
  • \$\begingroup\$ I have posted a new version since I forgot to remove an unnecessary character from the first one. The secret sequence is still the same, so you can try to crack either one. \$\endgroup\$ – Dennis Aug 25 '14 at 22:57
  • \$\begingroup\$ FYI, I'm aborting my factoring attempt. msieve set itself a time limit of 276 hours, but that was just for building the factor base. In that time it found 1740001 rational and 1739328 algebraic entries; it's since had almost 100 hours to process them, and reports sieving in progress b = 46583, 0 complete / 0 batched relations (need 44970493). \$\endgroup\$ – Peter Taylor Sep 13 '14 at 12:51
  • \$\begingroup\$ @PeterTaylor: Looks like 512 bits were overkill. Were you trying to factor the integer in my other answer or in this one? \$\endgroup\$ – Dennis Sep 13 '14 at 13:00
  • \$\begingroup\$ Oh, oops. Yes, other one. \$\endgroup\$ – Peter Taylor Sep 13 '14 at 18:16

Python - 128

Let's try this one:


(Expects the user to input 5 comma-separated numbers, e.g. 1,2,3,4,5.)

  • 3
    \$\begingroup\$ 32416190039,32416190047,32416190055,32416190063,32416190071 \$\endgroup\$ – Martin Ender Aug 25 '14 at 14:07
  • \$\begingroup\$ Wow, that was fast! You're right! And I'm out. \$\endgroup\$ – Falko Aug 25 '14 at 14:10
  • 3
    \$\begingroup\$ Btw, this isn't actually valid, because your five integers don't fit in a 32-bit integer. \$\endgroup\$ – Martin Ender Aug 25 '14 at 16:57

Java : 468

Input is given as k(int[5]). Bails early if not evenly spaced. Otherwise, it takes a bit figuring out if all ten hashes are correct. For large numbers, "a bit" can mean ten seconds or more, so it might dissuade crackers.

int k(int[]q){int b=q[1]-q[0],i,x,y,j,h[]=new int[]{280256579,123883276,1771253254,1977914749,449635393,998860524,888446062,1833324980,1391496617,2075731831};for(i=0;i<4;)if(q[i+1]-q[i++]!=b||b<1)return 0;for(i=1;i<6;b=m(b,b/(i++*100),(1<<31)-1));for(i=0;i<5;i++){for(j=1,x=b,y=b/2;j<6;x=m(x,q[i]%100000000,(1<<31)-1),y=m(y,q[i]/(j++*1000),(1<<31)-1));if(x!=h[i*2]||y!=h[i*2+1])return 0;}return 1;}int m(int a,int b,int c){long d=1;for(;b-->0;d=(d*a)%c);return (int)d;}

// line breaks
int k(int[]q){
    int b=q[1]-q[0],i,x,y,j,
    h[]=new int[]{280256579,123883276,1771253254,1977914749,449635393,
            return 0;
            return 0;
    return 1;
int m(int a,int b,int c){
    long d=1;for(;b-->0;d=(d*a)%c);
    return (int)d;
  • 1
    \$\begingroup\$ Your code hangs if input arithmetic sequence is descending. Or at least, takes a really long time. Which makes me think the secret code is ascending... \$\endgroup\$ – Keith Randall Aug 25 '14 at 21:04
  • 3
    \$\begingroup\$ @KeithRandall Oops. Let's add four bytes to make descending sequences take an unusually short amount of time, further reinforcing your belief. \$\endgroup\$ – Geobits Aug 25 '14 at 21:45

Java : 342

int l(int[]a){String s=""+(a[1]-a[0]);for(int b:a)s+=b;char[]c=new char[11];for(char x:s.toCharArray())c[x<48?10:x-48]++;for(int i=0;i<11;c[i]+=48,c[i]=c[i]>57?57:c[i],i++,s="");for(int b:a)s+=new Long(new String(c))/(double)b;return s.equals("-3083.7767567702776-8563.34366442527211022.4345579010483353.1736981951231977.3560837512646")?1:0;}

Here's a string-based locker that depends on both the input character count and the specific input. The sequence might be based on obscure pop culture references. Have fun!

A bit ungolfed:

int lock(int[]a){
    String s=""+(a[1]-a[0]);
    for(int b:a)
    char[]c=new char[11];
    for(char x:s.toCharArray())
    for(int i=0;i<11;c[i]+=48,
    for(int b:a)
        s+=new Long(new String(c))/(double)b;
    return s.equals("-3083.7767567702776-8563.34366442527211022.4345579010483353.1736981951231977.3560837512646")?1:0;
  • 2
    \$\begingroup\$ 8675309? 90210? \$\endgroup\$ – Malachi Aug 26 '14 at 20:46
  • 1
    \$\begingroup\$ @Malachi Two outstanding references, no doubt, but I can neither confirm nor deny their applicability to this exercise. \$\endgroup\$ – Geobits Aug 26 '14 at 21:09
  • \$\begingroup\$ lol, I haven't completely figured out how this challenge works completely yet, I may give it a shot later when I am at home. \$\endgroup\$ – Malachi Aug 26 '14 at 21:36
  • 1
    \$\begingroup\$ Initial term is -8675309, delta is 5551212. \$\endgroup\$ – Peter Taylor Aug 27 '14 at 9:36
  • \$\begingroup\$ @PeterTaylor Nicely done :) \$\endgroup\$ – Geobits Aug 27 '14 at 12:37

Python, 147

Edit: shorter version based on Dennis' comment. I updated the sequence too to avoid leaking any information.

def a(b):
    for d in b:
    return pow(7,c,0xf494eca63dcab7b47ac21158799ffcabca8f2c6b3)==0xa3742a4abcb812e0c3664551dd3d6d2207aecb9be

Based on the discrete logarithm problem which is believed to be uncrackable, however the prime I'm using is probably too small to be secure (and it may have other issues, I don't know). And you can brute-force it of course, since the only unknowns are two 32-bit integers.

  • \$\begingroup\$ Discrete logarithms are a lot harder that I thought. My cracker has been at this for 26 hours. I give up. \$\endgroup\$ – Dennis Aug 27 '14 at 4:28
  • \$\begingroup\$ You could solve the sign problem by initializing c=1, computing c=(c<<32)+d and changing the constant accordingly. \$\endgroup\$ – Dennis Aug 27 '14 at 17:44

Javascript 125

This one should be cracked pretty quickly. I'll follow up with something stronger.

function unlock(a, b, c, d, e)
    return (e << a == 15652) && (c >> a == 7826) && (e - b == d) && (d - c - a == b) ? 1 : 0;
  • 6
    \$\begingroup\$ 0, 3913, 7826, 11739, 15652 \$\endgroup\$ – Martin Ender Aug 25 '14 at 15:20
  • \$\begingroup\$ yep you got it :) \$\endgroup\$ – rdans Aug 25 '14 at 15:43

Ruby, 175

p a[2]*(a[1]^a[2]+3)**7==0x213a81f4518a907c85e9f1b39258723bc70f07388eec6f3274293fa03e4091e1?1:0

Unlike using a cryptographic hash or srand, this is provably unique (which is a slight clue). Takes five numbers via STDIN, delimited by any non-digit, non-newline character or characters. Outputs to STDOUT.

  • \$\begingroup\$ Yep, forgot they were signed. \$\endgroup\$ – histocrat Aug 25 '14 at 16:07
  • 2
    \$\begingroup\$ 622238809,1397646693,2173054577,2948462461,3723870345 (my previous guess had a mistake, but this one is tested). I don't think this is valid though, because the last number doesn't fit in a signed 32-bit integer. \$\endgroup\$ – Martin Ender Aug 25 '14 at 16:16

GolfScript (116 chars)

Takes input as space-separated integers.

~]{2.5??:^(&}%^base 2733?5121107535380437850547394675965451197140470531483%5207278525522834743713290685466222557399=
  • 2
    \$\begingroup\$ -51469355 -37912886 -24356417 -10799948 2756521 \$\endgroup\$ – Dennis Aug 25 '14 at 22:39
  • \$\begingroup\$ Nice work. Did you exploit the small exponent? \$\endgroup\$ – Peter Taylor Aug 25 '14 at 22:54
  • 2
    \$\begingroup\$ No, I factorized the modulus. Took only 13 seconds using primo's Multiple Polynomial Quadratic Sieve and PyPy. \$\endgroup\$ – Dennis Aug 25 '14 at 23:00
  • \$\begingroup\$ In that case I might as well abandon my current golfing it down by using a compactly expressed modulus. If the result has to be something like 1024 bits to be safe from factoring then even using a base-256 representation it's going to be too long. \$\endgroup\$ – Peter Taylor Aug 25 '14 at 23:03
  • \$\begingroup\$ I hope not. My answer uses the same idea as yours, but with a 512 bit modulus and an even smaller exponent (13). Given the 72 hour time limit, that might be enough... \$\endgroup\$ – Dennis Aug 25 '14 at 23:08

C 459 bytes


int c (int* a){
int d[4] = {a[1] - a[0], a[2] - a[1], a[3] - a[2], a[4] - a[3]};
if (d[0] != d[1] || d[0] != d[2] || d[0] != d[3]) return 0;
int b[5] = {a[0], a[1], a[2], a[3], a[4]};
int i, j, k;
for (i = 0; i < 5; i++) { 
for (j = 0, k = 2 * i; j < 5; j++, k++) {
k %= i + 1;
b[j] += a[k];
if (b[0] == 0xC0942 - b[1] && 
b[1] == 0x9785A - b[2] && 
b[2] == 0x6E772 - b[3] && 
b[3] == 0xC0942 - b[4] && 
b[4] == 0xB6508 - b[0]) return 1;
else return 0;

We need someone to write a C solution, don't we? I'm not impressing anybody with length, I'm no golfer. I hope it's an interesting challenge, though!

I don't think there's an obvious way to crack this one, and I eagerly await all attempts! I know this solution to be unique. Very minimal obfuscation, mostly to meet length requirements. This can be tested simply:

int main(){
    a[5] = {0, 0, 0, 0, 0} /* your guess */
    printf("%d\n", c(a));
    return 0;

P.S. There's a significance to a[0] as a number in its own right, and I'd like to see somebody point it out in the comments!


Solution: 6174, 48216, 90258, 132300, 174342

A note about cracking:

While this is not the method used (see the comments), I did happen to crack my own cipher with a very easy bruteforce. I understand now it is vitally important to make the numbers large. The following code can crack any cipher where upper_bound is a known upper bound for a[0] + a[1] + a[2] + a[3] + a[4]. The upper bound in the above cipher is 457464, which can be derived from the system of equations of b[] and some working-through of the algorithm. It can be shown that b[4] = a[0] + a[1] + a[2] + a[3] + a[4].

int a[5];
for (a[0] = 0; a[0] <= upper_bound / 5; a[0]++) {
    for (a[1] = a[0] + 1; 10 * (a[1] - a[0]) + a[0] <= upper_bound; a[1]++) {
        a[2] = a[1] + (a[1] - a[0]);
        a[3] = a[2] + (a[1] - a[0]);
        a[4] = a[3] + (a[1] - a[0]);
        if (c(a)) {
            printf("PASSED FOR {%d, %d, %d, %d, %d}\n", a[0], a[1], a[2], a[3], a[4]);
    printf("a[0] = %d Checked\n", a[0]);

With a[0] = 6174, this loop broke my work in a little under a minute.

  • 6
    \$\begingroup\$ Solution: 6174, 48216, 90258, 132300, 174342. \$\endgroup\$ – Tyilo Aug 25 '14 at 19:32
  • \$\begingroup\$ Wow that was fast. Nice one. Bruteforced, or did you find something clever I missed? \$\endgroup\$ – BrainSteel Aug 25 '14 at 19:33
  • \$\begingroup\$ I used Mathematica's symbolic evaluation like so: ghostbin.com/paste/jkjpf screenshot: i.imgur.com/2JRo7LE.png \$\endgroup\$ – Tyilo Aug 25 '14 at 19:36
  • \$\begingroup\$ Re the edit: I did basically the same thing, but fudged the upper at 500k. Got the answer and saw that Tyilo had already posted it :( \$\endgroup\$ – Geobits Aug 25 '14 at 19:50
  • \$\begingroup\$ @Geobits That's a surprisingly accurate guess. Should've put some more 0's on the ends of those numbers. \$\endgroup\$ – BrainSteel Aug 25 '14 at 19:53

Mathematica 80 67



f[{1,2,3,4,5}] (* => 0 *)

Probably pretty easy to crack, might also have multiple solutions.

Update: Improved golfing by doing what Martin Büttner suggested. Functionality of the function and the key hasn't changed.

  • \$\begingroup\$ @MartinBüttner Improving answers to get higher score when you crack them. Smart ;P \$\endgroup\$ – Tyilo Aug 25 '14 at 18:03
  • \$\begingroup\$ Huh, turns out I skipped the paragraph about scoring for the counter challenge. I thought that was just for the fun of it without any score at all. Although I don't think it would make sense for me shorten solutions I want to crack because that would reduce my score. \$\endgroup\$ – Martin Ender Aug 25 '14 at 18:09
  • 4
    \$\begingroup\$ {58871,5592,-47687,-100966,-154245} \$\endgroup\$ – freddieknets Aug 25 '14 at 21:20
  • \$\begingroup\$ @freddieknets Not the solution I used when creating it. Didn't know that NextPrime could return negative values. How did you find it? \$\endgroup\$ – Tyilo Aug 25 '14 at 21:28
  • \$\begingroup\$ Then your key is not unique :p. I just ran a few tests - there really aren't that many numbers where NextPrime[#]-# evaluates to 31, so that's an easy way to crack it. \$\endgroup\$ – freddieknets Aug 25 '14 at 21:31

Python27, 283 182

Alright, I am very confident in my locker, however it is quite long as I've added 'difficult to reverse' calculations to the input, to make it well - difficult to reverse.

import sys
for m in map(int,sys.argv[1:6]):m*=3**len(str(m));p*=m<<sum([int(str(m).zfill(9)[-i])for i in[1,3,5,7]])

edit: Thanks to colevk for the further golfing. I realized during editing that there was a bug as well as a flaw in my algorithm, maybe I'll have better luck next time.

  • 5
    \$\begingroup\$ This is invariant under reordering of the arguments, so it's not a valid locker. \$\endgroup\$ – Peter Taylor Aug 25 '14 at 18:26
  • \$\begingroup\$ Besides, I suspect the code as posted is buggy: the key 121174841 121174871 121174901 121174931 121174961 works, but only if the list [1,3,5,7] on line 7 is replaced with [1,3,5,7,11]. \$\endgroup\$ – Ilmari Karonen Aug 25 '14 at 19:18
  • \$\begingroup\$ Darn, yes I was just fixing my typo, during which I made a crucial mistake in my algorithm, leaving it very easy to crack :| \$\endgroup\$ – stokastic Aug 25 '14 at 19:33
  • \$\begingroup\$ Actually, finding and fixing the bug was the difficult part; given your algorithm, factoring the constant was kind of an obvious thing to try. \$\endgroup\$ – Ilmari Karonen Aug 25 '14 at 19:39

Mathematica 142 146

EDIT: key wasn't unique, added 4 chars, now it is.

    FromDigits /@ (
        PartitionsQ[n@(237/Plus@##) {1, ##} + 1] & @@@ 
    ) == {1913001154,729783244}

(Spaces and newlines added for readability, not counted & not needed).


f[1,2,3,4,5]   (* => 0 *)
  • 1
    \$\begingroup\$ Initial term 256208, delta -5. \$\endgroup\$ – Peter Taylor Aug 26 '14 at 13:34
  • \$\begingroup\$ Dang, then still it isn't unique, as this isn't my original key. Did you bruteforce? \$\endgroup\$ – freddieknets Aug 26 '14 at 13:37
  • \$\begingroup\$ Test it, I might have made a mistake because I don't have access to Mathematica to test. Each stage is using brute force, but it's not much computer time. The approach is to work backwards to the output of IntegerDigits and then factor to get candidates for the initial term and delta. \$\endgroup\$ – Peter Taylor Aug 26 '14 at 13:42
  • \$\begingroup\$ But there's no way this approach could be unique anyway. The second of the five inputs is only used in a sum which is passed to NextPrime; if we vary it by plus or minus one, at least one of those will give the same next prime. \$\endgroup\$ – Peter Taylor Aug 26 '14 at 14:02
  • \$\begingroup\$ yes but for a arithmetic sequence -as is the required input- it was supposed to be unique. \$\endgroup\$ – freddieknets Aug 26 '14 at 20:54

Cracked by @Dennis in 2 hours

Just a simple one to get things started - I fully expect this to be quickly cracked.

Pyth, 13


Takes comma separated input on STDIN.

Run it like this (-c means take program as command line argument):

$ echo '1,2,3,4,5' | python3 pyth.py -c h_^ZqU5m-CGdQ

Fixed the program - I had not understood the spec.

This language might be too esoteric for this competition - If OP thinks so, I will remove it.

  • 7
    \$\begingroup\$ Have you just given away that 1,2,3,4,5 is the key? \$\endgroup\$ – Peter Taylor Aug 25 '14 at 9:55
  • 1
    \$\begingroup\$ Every input I tried returned 1, did you switch 1 and 0 as output? \$\endgroup\$ – Tyilo Aug 25 '14 at 17:27
  • \$\begingroup\$ Sorry, I didn't understand the Output vs. Return distinction - the program should work now. Same underlying algorithm. \$\endgroup\$ – isaacg Aug 25 '14 at 21:20
  • 3
    \$\begingroup\$ 97,96,95,94,93 (I just killed my cracking score.) \$\endgroup\$ – Dennis Aug 25 '14 at 23:23
  • \$\begingroup\$ @Dennis Well done. The cracking score system needs to be changed - it's creating some really weird incentives. \$\endgroup\$ – isaacg Aug 25 '14 at 23:37

Lua 105

I suspect it won't be long before it's cracked, but here we go:

function f(a,b,c,d,e)
   print(t1==0 and t2==t3 and"1"or"0")

(spaces added for clarity, but are not part of count)

  • \$\begingroup\$ 3, 7, 11, 15, 19 or 6, 14, 22, 30, 38 \$\endgroup\$ – Dennis Aug 26 '14 at 4:50
  • \$\begingroup\$ @Dennis: sadly it is neither of those. I'll have to work on it a bit later to ensure the non-uniqueness. \$\endgroup\$ – Kyle Kanos Aug 26 '14 at 11:15
  • \$\begingroup\$ t1==0 whenver S is increasing. Also, both conditions are homogeneous; if S is a solution, so is kS. \$\endgroup\$ – Dennis Aug 26 '14 at 16:55

Perl - 256

sub t{($z,$j,$x,$g,$h)=@_;$t="3"x$z;@n=(7,0,split(//,$g),split(//,$h),4);@r=((2)x6,1,1,(2)x9,4,2,2,2);$u=($j+1)/2;for$n(0..$#r+1){eval{substr($t,$j,1)=$n[$n]};if($@){print 0; return}$j+=$r[$n]*$u}for(1..$x){$t=pack'H*',$t;}eval$t;if($@||$t!~/\D/){print 0}}

I had to put in a lot of error handling logic and this can definitely be golfed down a lot more. It will print a 1 when you get the right five numbers. It will hopefully print a 0 for everything else (might be errors or nothing, I don't know). If anyone wants to help improve the code or golf it more, feel free to help out!

Call with:


Ruby - 130

Based on Linear Feedback Shift Register. Inputs by command line arguments.
Should be unique based on the nature of LFSRs. Clue: ascending and all positive.

Will give more clues if no one solves it soon.

p x.to_s(36)=="qnsjzo1qn9o83oaw0a4av9xgnutn28x17dx"?1:0
  • 3
    \$\begingroup\$ Initial value 781783, increment 17982811 \$\endgroup\$ – Peter Taylor Aug 26 '14 at 10:39
  • \$\begingroup\$ @PeterTaylor Argh... =) \$\endgroup\$ – Vectorized Aug 26 '14 at 10:43

Ruby, 249

v=a[0]<a[1]&&!r[20]&&(0..3).select{|i|/^#{r}$/=~'%b'%[0xaa74f54ea7aa753a9d534ea7,'101'*32,'010'*32,'100'*32][i]}==[0]?1:0rescue 0
p v

Should be fun. Who needs math?

  • 2
    \$\begingroup\$ 309, 77347, 154385, 231423, 308461 but I don't think it's unique. \$\endgroup\$ – Martin Ender Aug 26 '14 at 14:54
  • \$\begingroup\$ Yeah, it's not. For the same regex (i.e. product of the first two numbers), I also find 103, 232041, 463979, 695917, 927855 and 3, 7966741, 15933479, 23900217, 31866955. And I'm pretty sure there are other valid regexes by using additional +s. \$\endgroup\$ – Martin Ender Aug 26 '14 at 14:58
  • \$\begingroup\$ Sorry, I guess I messed up the test string. There was supposed to be only one regexp with a unique factorization. \$\endgroup\$ – histocrat Aug 26 '14 at 15:00
  • \$\begingroup\$ If you want to try to fix it, make sure to take possessive quantifiers into account. I can also create a larger, equivalent regex by inserting () or similar. \$\endgroup\$ – Martin Ender Aug 26 '14 at 15:02

CJam, 49 characters


Try it online.

How it works

" Push a string representing a base 65536 number and convert it to an integer.            ";


" Prepend 1 to the integers read from STDIN and collect them into an array.               ";


" Convert that array into an integer by considering it a base 2**51 number.               ";


" Push the logical NOT of the modulus of both computed integers.                          ";


The result will be 1 if and only if the second integer is a factor of the first, which is a product of two primes: the one corresponding to the secret sequence and another that doesn't correspond to any valid sequence. Therefore, the solution is unique.

Factorizing a 512 bit integer isn't that difficult, but I hope nobody will be able to in 72 hours. My previous version using a 320 bit integer has been broken.

Example run

$ echo $LANG
$ base64 -d > flock512.cjam <<< IuiFleyYoeijg+SDrOqvs+uEkNaa76a/5b6L4KGG4ZOF76Gi46WE64eu4pSO5JSk5ayj6pGZ5Ji/7Zy64aWw57GD5YO+7I6n6Kuv65aG7qK04byr6aS+6IWO7rSn7YuvIjJHI2JbMXF+XThII2IlIQ==
$ wc -m flock512.cjam
49 flock512.cjam
$ cjam flock512.cjam < flock512.secret; echo
$ cjam flock512.cjam <<< "1 2 3 4 5"; echo
  • \$\begingroup\$ I've had msieve running on it for over 24 hours, but since its self-imposed time limit is 276.51 CPU-hours and I've only given it one CPU I'm not optimistic. \$\endgroup\$ – Peter Taylor Aug 29 '14 at 21:55

Javascript 958

Converts the inputs to a number of data types and performs some manipulations relevant to each data type along the way. Should be fairly easily reversed for anyone that takes the time.

function encrypt(num)
    var dateval = new Date(num ^ (1024-1) << 10);

    dateval.setDate(dateval.getDate() + 365);

    var dateString = (dateval.toUTCString() + dateval.getUTCMilliseconds()).split('').reverse().join('');

    var result = "";

    for(var i = 0; i < dateString.length; i++)
        result += dateString.charCodeAt(i);

    return result;

function unlock(int1, int2, int3, int4, int5)
    return encrypt(int1) == "5549508477713255485850495848483249555749321109774324948324410511470" && encrypt(int2) == "5756568477713252485848495848483249555749321109774324948324410511470" && encrypt(int3) == "5149538477713248485856485848483249555749321109774324948324410511470" && encrypt(int4) == "5356498477713256535853485848483249555749321109774324948324410511470" && encrypt(int5) == "5748568477713251535851485848483249555749321109774324948324410511470" ? 1 : 0;
  • 5
    \$\begingroup\$ Brute forced: 320689, 444121, 567553, 690985, 814417 \$\endgroup\$ – Tyilo Aug 25 '14 at 21:20
  • \$\begingroup\$ @Tyilo If you stop now, I think no cracker can beat your score. ;) \$\endgroup\$ – Martin Ender Aug 25 '14 at 21:48
  • 2
    \$\begingroup\$ @MartinBüttner Unless this can be golfed to under 512 per the OP, I don't think it counts. \$\endgroup\$ – Geobits Aug 25 '14 at 22:43

C, 239 (Cracked by Dennis)

Go here for my updated submission.

Could probably be golfed a little more thoroughly. Admittedly, I haven't taken the time to prove the key is unique (it probably isn't) but its definitely on the order of a hash collision. If you crack it, please share your method :)

p(long long int x){long long int i;x=abs(x);
for (i=2;i<x;i++) {if ((x/i)*i==x) return 0;}return 1;}
f(a,b,c,d,e){char k[99];long long int m;sprintf(k,"%d%d%d%d%d",e,d,c,b,a);
sscanf(k,"%lld",&m);return p(a)&&p(b)&&p(c)&&p(d)&&p(e)&&p(m);}
  • 1
    \$\begingroup\$ So, 0 0 0 0 0? \$\endgroup\$ – Dennis Aug 26 '14 at 0:01
  • \$\begingroup\$ Sigh that was a bug, but yes that works. \$\endgroup\$ – Orby Aug 26 '14 at 0:06
  • \$\begingroup\$ I've updated with a corrected version that should be a little more interesting ;) \$\endgroup\$ – Orby Aug 26 '14 at 0:14
  • \$\begingroup\$ See the corrected version here. \$\endgroup\$ – Orby Aug 26 '14 at 0:27

C, 212 by Orby -- Cracked

https://codegolf.stackexchange.com/a/36810/31064 by Orby has at least two keys:

13 103 193 283 373
113 173 233 293 353

Orby asked for the method I used to crack it. Function p checks whether x is prime by checking x%i==0 for all i between 2 and x (though using (x/i)*i==x instead of x%i==0), and returns true if x is a prime number. Function f checks that all of a, b, c, d and e are prime. It also checks whether the number m, a concatenation of the decimal representations of e, d, c, b and a (in that order), is prime. The key is such that a,b,c,d,e and m are all prime.

Green and Tao (2004) show that there exist infinitely many arithmetic sequences of primes for any length k, so we just need to look for these sequences that also satisfy m being prime. By taking long long as being bounded by -9.223372037e+18 and 9.223372037e+18, we know that for the concatenated string to fit into long long, the numbers have an upper bound of 9999. So by using a python script to generate all arithmetic sequences within all primes < 10000 and then checking whether their reverse concatenation is a prime, we can find many possible solutions.

For some reason I came up with false positives, but the two above are valid according to the program. In addition there may be solutions where e is negative and the rest are positive (p uses the modulus of x), but I didn't look for those.

The keys I gave are all arithmetic sequences but Orby's script doesn't appear to actually require the inputs to be an arithmetic sequence, so there may be invalid keys too.


MATLAB: Apparently invalid

Very simple, you just have to generate the right random number.

function ans=t(a,b,c,d,e)

It can still error out, but that shouldn't be a problem.

  • 1
    \$\begingroup\$ This approach is prohibited in the comments. If it's not mentioned in the question, propose an edit. Sorry. \$\endgroup\$ – Peter Taylor Aug 26 '14 at 10:51
  • \$\begingroup\$ @PeterTaylor I guess I am out then, I will just leave it here without score as I am curious whether someone can find a weakness. \$\endgroup\$ – Dennis Jaheruddin Aug 26 '14 at 10:54

MATLAB (with Symbolic Toolbox), 173 characters

This isn't an official entry and won't count towards anyone's cracking score, but it will net you mad bragging rights. ;)

function b=L(S),c=sprintf('%d8%d',S(1),S(2)-S(1));b=numel(unique(diff(S)))==1&&numel(c)==18&&all(c([8,9])==c([18,17]))&&isequal(c,char(sym(sort(c,'descend'))-sym(sort(c))));

The symbolic toolbox is only required to handle subtraction of big integers.

Brute forcing it should be a dog, but if you're familiar with the series it involves, the solution is trivial.


Python 2 (91)

Edit: This isn't allowed because the argument for uniqueness is probabilistic. I give up.

for n in input():s+=pow(n,s,7**58)
print s==0x8b5ca8d0cea606d2b32726a79f01adf56f12aeb6e

Takes lists of integers as input, like [1,2,3,4,5].

The loop is meant to operate on the inputs in an annoying way, leaving a tower of sums and exponents. The idea is like discrete log, but with messy complication instead of mathematical simplicity. Maybe the compositeness of the of the modulus is a vulnerability, in which case I could make it something like 7**58+8.

I don't really know how I'd prove that my key is the only one, but the range of outputs is at least 10 times bigger than the range of inputs, so probably? Though maybe only a small fraction of potential outputs are achievable. I could always increase the number of digits at the cost of characters. I'll leave it up to you to decide what's fair.

Happy cracking!


Mathematica - 72

Version 2 of my script, with the same key as the one intended for my version 1.

This basically removes negative prime numbers for NextPrime.



f[{1,2,3,4,5}] (* => 0 *)
  • \$\begingroup\$ Assuming that I've correctly understood what your code does, I get several solutions of which the smallest is initial term 9244115, delta 25. \$\endgroup\$ – Peter Taylor Aug 27 '14 at 11:39
  • \$\begingroup\$ @PeterTaylor I can confirm that that one is valid. \$\endgroup\$ – Martin Ender Aug 27 '14 at 12:12
  • \$\begingroup\$ @PeterTaylor correct, another key is 1073743739, 1073886396, 1074029053, 1074171710, 1074314367 \$\endgroup\$ – Tyilo Aug 27 '14 at 14:29

Python, 86 characters

print 1if(a*c^b*e)*d==0xd5867e26a96897a2f80 and b^d==48891746 else 0

Enter the numbers like 1,2,3,4,5.

> python 36768.py <<< "1,2,3,4,5"
> python 36768.py <<< "[REDACTED]"
  • \$\begingroup\$ This isn't a valid submission; it accepts the input 1,0,1,63021563418517255630720,0. \$\endgroup\$ – Dennis Aug 27 '14 at 3:01
  • \$\begingroup\$ @Dennis Fixed. I hope it's valid now. \$\endgroup\$ – Snack Aug 27 '14 at 5:03
  • 1
    \$\begingroup\$ 19960211, 31167202, 42374193, 53581184, 64788175 \$\endgroup\$ – Dennis Aug 27 '14 at 5:07
  • \$\begingroup\$ @Dennis Correct and awesome. I think I'm very poor at math. \$\endgroup\$ – Snack Aug 27 '14 at 5:13
  • 2
    \$\begingroup\$ @Dennis, 63021563418517255630720 isn't a 32-bit number. \$\endgroup\$ – Peter Taylor Aug 27 '14 at 8:59

Python, 78

(Cracked by Tyilo in 14 mins)


def L(a): return 1 if a==[(i-i**6) for i in bytearray(' ','utf-8')] else 0

Okay, it doesn't display properly here :(

Expects a list of five numbers, eg. [1,2,3,4,5]

  • 1
    \$\begingroup\$ Pretty easy: [-481890276, -594823292, -728999970, -887503650, -1073741792] \$\endgroup\$ – Tyilo Aug 27 '14 at 9:03
  • \$\begingroup\$ Thought so, well done :) \$\endgroup\$ – ElectricWarr Aug 27 '14 at 9:05

CJam, 37 characters (broken)


Try it online.

How it works

See my new answer.

Example run

$ echo $LANG
$ base64 -d > flock.cjam <<< IueFt+Keu+aNrOa4k+exu+K2peuVmeGLtuq+q+Oen+Wnsu6AhMy34ZCC47WI56aZ6bCz7KWb5b+p6JSDIjJHI2JbMXF+XTRHI2IlIQ==
$ wc -m flock.cjam
37 flock.cjam
$ cjam flock.cjam < flock.secret; echo
$ cjam flock.cjam <<< "1 2 3 4 5"; echo
  • 1
    \$\begingroup\$ 737262825 208413108 3974530688 3445680972 2916831257 works but isn't an arithmetic progression. Factored in 3 hours 20 minutes. 512-bit numbers were apparently doable in 72 hours for $75 on EC2 two years ago, so I think that would have been safe. \$\endgroup\$ – Peter Taylor Aug 27 '14 at 22:15
  • \$\begingroup\$ @PeterTaylor: That returns 1, but the last three integers are greater than MAX_INT, so it's not a valid key. That being said, 3 h 20 m is pretty impressive. The algorithm I was using took 16 hours for a 256-bit semiprime... \$\endgroup\$ – Dennis Aug 27 '14 at 23:59
  • \$\begingroup\$ I thought there must be some negative numbers in there somewhere because the deltas were almost right but not quite. I'll get on to it. \$\endgroup\$ – Peter Taylor Aug 28 '14 at 7:08
  • 1
    \$\begingroup\$ 737262825 208413109 -320436607 -849286323 -1378136039 \$\endgroup\$ – Peter Taylor Aug 28 '14 at 7:27
  • \$\begingroup\$ @PeterTaylor: That's the one. I hope the 512 bit version lasts longer. \$\endgroup\$ – Dennis Aug 28 '14 at 17:37

C, 212 (Cracked)

This is the same idea as my previous submission, golfed more thoroughly, with a bug corrected that passed 0,0,0,0,0 (Thanks to Dennis for pointing out the bug). Compile with -std=c99.

#define L long long
p(L x){x=abs(x);for(L i=2;i<x;i++){if((x/i)*i==x)return 0;}return(x>1);}
f(a,b,c,d,e){char k[99];L m;sprintf(k,"%d%d%d%d%d",e,d,c,b,a);sscanf(k,"%lld",&m);
return p(a)&p(b)&p(c)&p(d)&p(e)&p(m);}
  • \$\begingroup\$ Any sequence (arithmetic or not) of negative primes will work. Two examples: -7 -37 -67 -97 -127, -157 -127 -97 -67 -37 \$\endgroup\$ – Dennis Aug 26 '14 at 1:27
  • \$\begingroup\$ Yeah, my code is just riddled with bugs. The answer nitrous gave is along the lines of what I was looking for. But nice job pointing out the more obvious answers. \$\endgroup\$ – Orby Aug 26 '14 at 1:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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