35
\$\begingroup\$

This is a puzzle the robbers' thread can be found here.

Your task will be two write two programs (or functions) such that they are anagrams of each other and one performs the left inverse of the other. These programs may accept and output as many integers or complex numbers as you wish. If you choose take numbers as character points or any other reasonable means you must indicate you are doing so in your answer. If you choose to restrict the domain of your function you must also indicate the restricted domain in your answer.

You will then present the first program in the form of an answer with left inverse hidden for robbers to find.

The shown program must implement a injective function (otherwise it would be impossible for a hidden answer to exist).

If your answer has not been cracked in one week you may reveal the hidden answer and mark it as safe. Safe answers cannot be cracked by robbers and will remain un-cracked indefinitely.

The goal will be to create the shortest un-cracked answer in bytes.

Example

You could show the following python program that adds one to the input

lambda x:~-x

A solution could be:

lambda x:-~x

This subtracts one from the input

\$\endgroup\$
10
  • \$\begingroup\$ Can we have imaginary/complex integers? \$\endgroup\$ Jan 16, 2017 at 16:18
  • \$\begingroup\$ @stewie if you indicate so you may \$\endgroup\$
    – Wheat Wizard
    Jan 16, 2017 at 16:20
  • 1
    \$\begingroup\$ Is anagramming defined as permuting the characters, or permuting the bytes (in languages which don't use a single-byte character set)? \$\endgroup\$
    – user62131
    Jan 16, 2017 at 16:57
  • \$\begingroup\$ 1. "You will then present one of the programs" seems to suggest that we can choose which to present, but the sentence continues "with left inverse hidden", implying that we have to present a specific one. Which is it? 2. The question specifically states "program" and doesn't appear to permit functions, but the example is a function rather than a program. Which is it? \$\endgroup\$ Jan 16, 2017 at 17:01
  • \$\begingroup\$ Does capitalisation matter? \$\endgroup\$
    – user41805
    Jan 16, 2017 at 17:03

17 Answers 17

12
\$\begingroup\$

Python 3, 80 bytes (Cracked)

bhmq = int(input())
print(bhmq ** 2)
(1 or [(sqrt),(specification+of*integerr)])

Domain: positive integers. Function is just squaring of a number. Input to stdin, output to stdout, as well as in the inverse function. Note that Python ignores the third line here, because it is syntactically valid and 1 is already a truthy value, so Python doesn't even look whether the right part of 'or' is well-defined.

Robbers should write a sqrt function that will work correct on all non-zero squares, printing integer value as is, without floating point (so on input '4' output should be '2' or '2\n', not '2.0' or '2.0\n').

\$\endgroup\$
14
  • 1
    \$\begingroup\$ I like this one. It is deceptively difficult to crack \$\endgroup\$
    – Wheat Wizard
    Jan 18, 2017 at 0:22
  • 3
    \$\begingroup\$ Welcome to ppcg! Nice first post! \$\endgroup\$
    – Riker
    Jan 18, 2017 at 1:03
  • 1
    \$\begingroup\$ Nevermind on that crack, I messed up. The question still stands though. \$\endgroup\$
    – orlp
    Jan 18, 2017 at 5:33
  • 1
    \$\begingroup\$ I'd say 'no', if I'm really allowed to put this restriction by the rules of the challenge. \$\endgroup\$
    – Wolfram
    Jan 19, 2017 at 17:04
  • 1
    \$\begingroup\$ Cracked? \$\endgroup\$
    – Zgarb
    Jan 20, 2017 at 9:05
11
\$\begingroup\$

Python 3, 46 bytes, cracked

lambda x:x*(1999888577766665//844333333222200)

Doubles the input.

\$\endgroup\$
4
  • 3
    \$\begingroup\$ How does 'Python' work in cops 'n robbers? May we choose an arbitrary version to attack your answer with? \$\endgroup\$
    – orlp
    Jan 16, 2017 at 15:04
  • \$\begingroup\$ Oh, this is Python 3 specifically, sorry. So / is float division. \$\endgroup\$
    – Lynn
    Jan 16, 2017 at 15:05
  • 3
    \$\begingroup\$ Well, you just proved this challenge is not worth my time. Moving on. \$\endgroup\$
    – mbomb007
    Jan 16, 2017 at 15:14
  • 5
    \$\begingroup\$ Cracked: codegolf.stackexchange.com/a/107020/18535 \$\endgroup\$
    – G B
    Jan 16, 2017 at 15:25
11
\$\begingroup\$

7, 9 bytes, Cracked

This program's full of nonprintable characters, so here's a hexdump:

00000000: 2573 dc01 7e13 dcb6 1f                   %s..~....

Note: this uses a numeric input routine that's incapable of inputting negative numbers, so this submission is restricted to nonnegative integers only.

One problem with challenges is that you don't write explanations of the code (to make it harder to crack). On the other hand, this means that I don't have to go to to the trouble here.

I picked 7 as the language because, especially in its compressed notation, it's pretty hard to read, and I don't see why it should be only me who has to go to the trouble of moving around 8-bit chunks of programs written in a 3-bit encoding. Good luck!

Explanation

Now that the program's been cracked (by brute force, unfortunately; that's always a danger in these short solutions), I may as well explain what I was getting at. This was actually fairly solvable by reading the program; I could have made it much more difficult, but that felt like a bad idea when brute-force cracks exist.

We'll start by representing the program in a more natural encoding. As usual, bolded numbers indicate commands that run immediately (not all of which are representable in a program; 6 and 7 are but 2 to 5 aren't), unbolded numbers represent their escaped equivalents (0 to 5, all of which are representable in the original program; note that 0 is an escaped 6 and 1 is an escaped 7):

11271734002770236713303

The set of commands available in a 7 program source mean that it's basically just a literal that represents the original stack (there's nothing else you can do with just escaped commands, 6 and 7). So the first thing a program will do is push a bunch of stuff onto the stack. Here's how the stack looks after the program's run (| separates stack elements, as usual in 7):

772|7|34662|023|73363

The final stack element then gets copied to become the code to run (while remaining on the stack). As it happens, this is the only part of the program that's code; everything else is just data. Here's what it translates to:

73363
7      Push an empty element onto the stack
 3     Output the top stack element, discard the element below
73     Combined effect of these: discard the top stack element
  3    Output the top stack element, discard the element below
   6   Escape the top stack element, then append it to the element below
    3  Output the top stack element, discard the element below

In other words, this is mostly just a bunch of I/O instructions. Let's analyse this in detail:

  • 73 discards the 73363 that's still on top of the stack.
  • 3 outputs the 023, and discards the 34662. It can thus be seen that the 34662 is a comment, which was used to store the bytes needed in the other version of the program. As for what 023 does when output, it selects I/O format 0 (integers), then 23 is a directive which requests the implementation to input an integer (in 7, you do input via outputting specific codes that request input). The input is done by making copies of the stack element below, e.g. if the input integer is 10, the next stack element (currently 7) will become 7777777777. Thus, we're accepting input from the user in decimal, but it's being stored as unary.
  • 6 escapes the top stack element (changing each instance of 7 to 1; this is how strings consisting entirely of 7s are escaped), then appends it to the stack element before (772). So our data is now something like 7721111111111.
  • Finally, 3 outputs the stack element in question (and pops a blank stack element that's part of the default initial stack). Its value is calculated by taking the number of 1s and 7s, and subtracting the number of 0s and 6s. (The 2 in the middle is ignored in most cases; if it's at the end of the string, it'll become a trailing newline instead of being ignored, but PPCG rules don't care about that.) Thus, the output is the original input plus 2.

At this point, there's nothing useful on the stack and nothing in the program, so the program exits.

How do we reverse this? It's a simple matter of changing the 11 to 00, so that we're prepending characters to the input that make it 2 lower, rather than 2 higher. There's a 00 conveniently hidden eight octal digits further on in the program (so that octal digits and bytes line up with each other), so we can simply swap it with the 11 at the start.

\$\endgroup\$
3
  • \$\begingroup\$ Cracked: codegolf.stackexchange.com/a/107103/18535 \$\endgroup\$
    – G B
    Jan 17, 2017 at 14:00
  • \$\begingroup\$ Side note: you don't have to explain your code, but knowing what your program does would be nice. \$\endgroup\$
    – G B
    Jan 17, 2017 at 14:01
  • \$\begingroup\$ @GB: I gave a full explanation of the program (including an explanation of how the crack works). \$\endgroup\$
    – user62131
    Jan 17, 2017 at 20:02
7
\$\begingroup\$

JavaScript (ES6), 21 bytes, Cracked

This is an easy one.

b=>Math.pow(b,torc=3)

Returns the cube of the input.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Cracked \$\endgroup\$
    – Emigna
    Jan 16, 2017 at 16:05
6
\$\begingroup\$

Python 2, 83 bytes, cracked

#((()))****+,,---/2289;==oppppppqqqqqw~~
lambda n:pow(n,65537,10998167423251438693)

This is similar to my other answer. However, this uses 64-bit RSA, and is cryptographically quite weak. If you can rob this answer, you can theoretically rob my other one as well, given enough time.

\$\endgroup\$
1
5
\$\begingroup\$

Python 2, 47 bytes, Cracked

lambda x:x**2or (iron() and saxifrage.extend())

The domain for this function is {x ∈ ℤ | x > 0}. It squares its input.


nmjcman101 found the intended solution:

lambda x:sorted(a**2for a in range(x)).index(x)

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Haha, love the made up function calls \$\endgroup\$
    – FlipTack
    Jan 18, 2017 at 22:41
  • 1
    \$\begingroup\$ Cracked That was fun, I got stuck on the sorted anagram I had left! \$\endgroup\$
    – nmjcman101
    Jan 19, 2017 at 20:32
5
\$\begingroup\$

JavaScript (ES6), 46 bytes, Cracked

x=>Math.log(x+(+String(t=985921996597669)[5]))

This function returns ln(x+1) where x is a non-negative number.

Usage

(x=>Math.log(x+(+String(t=985921996597669)[5])))(5)

Note: Due to the nature of floating point numbers f(g(x)) may not exactly equal x. Example: f(g(4))=3.9999999999999996

\$\endgroup\$
1
4
\$\begingroup\$

J, 8 bytes, cracked

Another simple one to start off with.

[:]+:[-:

Doubles the input.

\$\endgroup\$
3
4
\$\begingroup\$

Processing.js, 59 bytes, Cracked!

float igetuwebaoli(int p){return p*(((17*-4*-3)))+0+0;}//,,

This function multiplies the input by 204 (17*-4*-3=204). It takes in an int as input and outputs a float. As expected, the inverse divides the input by 204.

An online interpreter for processing-js can be found here.

\$\endgroup\$
1
4
\$\begingroup\$

J, 10 bytes, cracked

1%~<:[@*>:

Another simple one. Returns n2-1.

\$\endgroup\$
1
4
\$\begingroup\$

JavaScript (ES6), 15 bytes, cracked by Emigna

t=>(!!0+~~t+~0)

This functions returns n-1.


You can test it like:

(t=>(!!0+~~t+~0))(6)

Cracked

My intended solution is a bit different than Emigna's crack:

t=>t+(+!!~~~00)

\$\endgroup\$
1
  • 2
    \$\begingroup\$ Cracked \$\endgroup\$
    – Emigna
    Jan 17, 2017 at 12:01
4
\$\begingroup\$

J, 29 bytes (Cracked by miles)

5#.[:,(3 5&#:(-$]-)7)#.inv"0]

This is a verb that takes a positive integer as input, and does the following:

  1. Convert to bases 2 and 4.
  2. Pad the base-4 representation with 0s to have the same length as the base-2 representation.
  3. Concatenate the two representations (base-2 first).
  4. Interpret the concatenation as a base-5 representation and convert to integer.

Try it online!

My solution

The logic is pretty much the same as in the crack. The rank conjunction " can be stuck in many different places (and I use it to get rid of the unnecessary 0 and 3), since it doesn't really do anything in the solution.

(7-5)#.[:(]-:&#$,)5#.inv"0 3]
\$\endgroup\$
4
  • \$\begingroup\$ I don't understand J, but my experiments show this actually takes integer in bases 2 and 4, adds zeros to the end of base 4 to make their length equal, and only then concatenates. Are these zeros intended? \$\endgroup\$
    – Wolfram
    Jan 18, 2017 at 9:07
  • \$\begingroup\$ @Wolfram The zeros are intended, that's what I tried to say with "simultaneously". Otherwise I don't think it would be reversible. \$\endgroup\$
    – Zgarb
    Jan 18, 2017 at 9:09
  • \$\begingroup\$ @Wolfram I added a more explicit description. \$\endgroup\$
    – Zgarb
    Jan 20, 2017 at 9:11
  • \$\begingroup\$ Cracked. \$\endgroup\$
    – miles
    Jan 23, 2017 at 13:56
4
\$\begingroup\$

Processing (java), 59 bytes, SAFE

float igetuwebaoli(int p){return p*(((17*-4*-3)))+0+0;}//,,

This function multiplies the input by 204 (17*-4*-3=204). It takes in an int as input and outputs a float. As expected, the inverse divides the input by 204. Note: both programs take an int as input and output a float.

This answer is exactly the same as my other answer, except that my other answer was written in Processing.js. Meet Processing-java, the less verbose cousin of Java. You can download Processing here at processing.org.

The Crack

float ap(int i){return i*pow(blue(get(0,0)),-1);}//++7*4*-3

This program divides the argument by 204. But how? Let's go inside the function.

i *                              //multiply i by
         blue( get(0, 0) )       //this (evaluates to 204)
    pow(                  , -1)  //raises to the -1 power (ie its reciprocal)

Simple enough, but how does blue( get(0, 0) ) become 204? This is the centrepiece of this submission. First of all, get(0,0) gets the colour of the pixel located at (0,0) (the top left corner of the window, which always opens in a Processing sketch). Next, blue() gets the blue value of that pixel, which is 204!

To come up with this submission, I experimented by printing the different attributes of the colour obtained by get(0,0). I have found out that the red, green, blue, alpha values are 204, 204, 204 and 255 respectively. From this, I decided to do a simple operation with this number and ended up with this post.

\$\endgroup\$
2
  • \$\begingroup\$ I thought Kotlin was the less verbose cousin of Java! I do concede that the C family of languages is pretty big... but what would the family tree actually look like... \$\endgroup\$
    – CAD97
    Jan 17, 2017 at 7:52
  • \$\begingroup\$ I believe you made it, no one has cracked your post and it's been a week. \$\endgroup\$
    – miles
    Jan 24, 2017 at 14:59
3
\$\begingroup\$

JavaScript (ES6), 63 bytes Cracked by Ilmari Karonen

x=>eval(atob`eCp4KzEvLyAgfXBModLS4TvEn4wp1iys9YRRKC85KLIhNMC=`)

Time for some atob nonesense. This function returns x*x+1 where x is a non-negative number.

Usage

(x=>eval(atob`eCp4KzEvLyAgfXBModLS4TvEn4wp1iys9YRRKC85KLIhNMC=`))(5)

Intended

x=>eval(atob`Lyp5fMRwICAgKi9NYXRoLnBvdyh4LTEsMC41KS8veCp4KzE=`)

There's a large number of potential solutions, but I was hoping that the leading characters would throw off the byte order enough to make this harder. C'est la atob

\$\endgroup\$
3
  • \$\begingroup\$ Cracked. \$\endgroup\$ Jan 17, 2017 at 22:54
  • \$\begingroup\$ Did you just accidentally repost your challenge code as the intended solution? :) \$\endgroup\$ Jan 18, 2017 at 16:45
  • \$\begingroup\$ @IlmariKaronen Thanks, that'll teach me to copy/paste... lol yeah right :P \$\endgroup\$
    – SLuck49
    Jan 18, 2017 at 17:02
3
\$\begingroup\$

Brain-Flak, 26 bytes, Cracked

Original

((((()()())){}[()]){}{}{})

My Crack

([(((()())){}()){}{}()]{})

1000000000's Crack

([(((()())()){}){}{}](){})

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Cracked \$\endgroup\$
    – 0 '
    Jan 16, 2017 at 18:32
2
\$\begingroup\$

Python 2, 225 bytes, cracked by Sp3000

#((()))****+,,---/000555666888;==oppppppqqqqqw~~
lambda n:pow(n,65537,9273089718324971160906816222280219512637222672577602579509954532420895497077475973192045191331307498433055746131266769952623190481881511473086869829441397)

Domain of this function is [0, n), where n is the huge number above. Yes, this function is invertible on this domain. And unless I messed up, breaking this answer is as hard as breaking 512 bit RSA.

\$\endgroup\$
7
  • 1
    \$\begingroup\$ Brute-forcing this is considerably easier than brute-forcing RSA because you already have an approximate anagram of the constant you need. On the other hand, it's likely still too difficult to manage in practice. \$\endgroup\$
    – user62131
    Jan 16, 2017 at 17:29
  • 4
    \$\begingroup\$ Keep in mind that there is a meta post regarding randomisation in CnR challenges: meta.codegolf.stackexchange.com/questions/10793/… \$\endgroup\$
    – user41805
    Jan 16, 2017 at 18:21
  • 5
    \$\begingroup\$ @KritixiLithos My answer does not contain randomization, hashes or builtin crypto code. It's literally one modular exponentiation. \$\endgroup\$
    – orlp
    Jan 16, 2017 at 18:25
  • 2
    \$\begingroup\$ Your answer intendedly aims at a problem known to be hard to solve and therefore matches the meta post (especially since it mentions RSA directly). I think that even if you meta loophole your script still deserves my downvote. \$\endgroup\$
    – Christoph
    Jan 20, 2017 at 13:54
  • 4
    \$\begingroup\$ Cracked \$\endgroup\$
    – Sp3000
    Jan 22, 2017 at 9:33
0
\$\begingroup\$

J, 15 bytes

(".&,'10.')#.#:

Takes a non-negative integer n, converts it to a list of binary digits, and combines those digits as a base 10 number.

Try it online!

\$\endgroup\$

Your Answer

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

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