# Cheapo Enigma machine (Cops)

For robbers' post, Cheapo Enigma machine (Robbers)

A cop's submission will consist of a program/function that accepts a single byte of data and return a single byte of data. Every possible input must produce a unique output. (In the other words, your function must be bijective)

Robbers will attempt to create the inverse function of yours using as short a code as possible. So your objective is to make your function difficult to invert.

You cannot use built-ins that have the sole purpose of hashing or encryption.

Your byte count cannot exceed 64 bytes. 0-byte solutions are not eligible for winning.

# Input/Output format

8 bits (0 or 1), or a base-10 integer in range 1-256, 0-255 or -128 to 127. Can use standard I/O or file I/O. Function can also return a value as output. Input and output should belong to the same range (binary, 1-256, 0-255 or -128 to 127). The robber will also be required to use this range for input and output.

# Scoring

Ratio of your byte count to that of the best robber's attempt against you. Lowest score wins.

You are eligible to win (as a cop) only if a robber has attempted to defeat you. (This robber may be you)

# Example

C++, uses 0-255 range, 31 bytes

int x;
cin>>x;
cout<<(x+1)%256;


Possible robber submission in C++, 32 bytes

int f(int x)
{return x?x-1:255;}


Using the same language or a similar algorithm isn't a requirement

This gives a score of 31/32 = 0.97 to both the cop and the robber.

• What does a cop submission consist of? Language, size and full program/function code? – Arnauld Apr 22 '17 at 10:27
• isn't it a bit broken if the cop can just make an arbitrarily large thing? – Destructible Lemon Apr 22 '17 at 10:32
• This robber may be you What if I post a 64-byte cop answer that maps N to N and a robber answer that does the same thing in one byte? – Arnauld Apr 22 '17 at 11:04
• You may want to specify if / how the cop submission should be updated when robbers answer it. (The usual "cracked" update doesn't apply here, I guess. At least not as a unique and definitive crack.) – Arnauld Apr 23 '17 at 13:28
• On second thought, you might want to remove that rule altogether. I can destroy most answers by posting a robber in Jelly. – Dennis Apr 24 '17 at 18:25

# Javascript, 11 8 bytes, Score: 8 / 5

x=>x^x/2


Simple implementation of gray code. Decoding usally needs a whole loop. Let's see who comes up with the smallest or even without a loop !

• I guess x^x/4 will be harder because there shouldn't be builtins for it ... – Christoph Apr 24 '17 at 8:31
• Score: 8/25 – Arnauld Apr 24 '17 at 8:36
• How is this bijective? – Leaky Nun Apr 25 '17 at 11:54
• @LeakyNun Uhm not sure what kind of an answer you expect but I'll try: Gray code is an alternative form of representing a number where each consecutive number only changes in 1 bit (hammig distance is always 1). For each number there is exactly one gray encoding and one binary encoding therefore they form a bijection. E.g. 7 is 0111 in binary and 0100 in gray, the next number 8 is 1000 in binary and 1100 in gray. Gray coding is basically the edge coding of binary. – Christoph Apr 25 '17 at 13:56
• @LeakyNun ^ is bitwise xor, not exponentiation. Anyway it looks magic – Евгений Новиков Jul 25 '17 at 11:45

# C, 64 bytes, Score 64/71 = 0.901

T[256];f(x){srand(x&&f(x-1));for(;T[x=rand()%256]++;);return x;}


Takes input in the range [0 255].

Try it online! — on TIO (using GCC), this produces:

103,198,105,115,081,255,074,236,041,205,186,171,242,251,227,070,
124,194,084,248,027,232,231,141,118,090,046,099,051,159,201,154,
102,050,013,183,049,088,163,037,093,005,023,233,094,212,178,155,
180,017,014,130,116,065,033,061,220,135,112,062,161,225,252,001,
126,151,234,107,150,143,056,092,042,176,059,175,060,024,219,002,
026,254,067,250,170,058,209,230,148,117,216,190,097,137,249,187,
168,153,015,149,177,235,241,179,239,247,000,229,202,011,203,208,
072,071,100,189,031,035,030,028,123,197,020,075,121,036,158,009,
172,016,080,021,111,034,025,125,245,127,164,019,181,078,152,224,
077,052,188,095,119,108,134,043,085,162,004,211,054,226,240,228,
079,073,253,169,008,138,010,213,068,091,243,142,076,215,045,066,
006,196,132,173,222,048,246,032,133,007,244,185,195,217,160,120,
218,106,083,144,087,238,207,096,210,053,101,063,098,128,165,089,
140,012,192,131,047,039,022,147,184,109,182,193,199,237,018,069,
057,157,174,104,122,166,055,110,003,040,139,086,145,114,129,113,
206,167,191,214,146,221,136,038,156,082,200,029,044,204,223,064


Note that on other systems, it may produce different (but still valid) output, since C does not mandate a specific rand implementation. My submission is specifically the version running on TIO (as linked).

I'm quite disappointed that I wasn't able to get a version like my original (f(x){return rand(srand(x*229))/229%256;}) to work on TIO, since I think that's much more elegant. Since that only works on Clang running on OS X, it isn't fair for the competition. This one's still pretty awkward to reverse, so that's enough I guess.

• Well..This is amusing! – Matthew Roh Apr 27 '17 at 13:38
• Solution here, but I had a bit of a hard time with your srand(), so you'll have to decide if it's acceptable in this form. – Appleshell Apr 28 '17 at 4:41
• I fail to see how this program fulfills the Bijection requirement, since output is random not every input has a unique output. – Sriotchilism O'Zaic Apr 28 '17 at 5:08
• The problem is not the implementation. The problem is that it lacks what I think are all key ideas of this challenge: Finding a trival algorithm (therefore limited to 64 bytes and language independent) that is nontrival to reverse. Your submission "feels" to loophole on: Language independence, the 64 byte limit by outsourcing to an unknown implementation of a builtin (rand does not depend on the language but the local stdlib) and the hash/encryption rule. It's within PPCG's rules but certainly not what ghosts_in_the_code intended with his rules. – Christoph Apr 28 '17 at 8:24
• @ghosts_in_the_code good RNGs and hash functions are both designed to hardly be reversible. Therefore I think they should be included in that rule (even if the actual implementation might not be designed this way). Anyway I don't recommand changing the rules at this stage. – Christoph Apr 28 '17 at 10:54

# Jelly, 2/5

^H


Try it online to see the whole table.

• Hm, looks like @Christoph had the same idea 9 hours before me... – Dennis Apr 24 '17 at 17:50

# JavaScript, 44 bytes 22/3

x=>a.sort()[x]
for(a=[],i=0;i<256;)a[i]=i++;


Uses lexicographic sort (Javascript Default) to rearrange all the numbers from 0-255

Try it online!

• 22/3 - different language seems acceptable, even if a little odd. I thought I had 5, but 256 got in my way :). – Jonathan Allan Apr 26 '17 at 4:16

# C (gcc), 32 27/30 bytes

Thanks to christoph for golfing 5 bytes.

f(x){x=x?f(x*5+1&255)+1:0;}


Try it online!

• Score 32/30. You might want to switch to f(x){x=x?f(x*5+1&255)+1:0;} for a score of 27/30. – Christoph Apr 28 '17 at 14:39

# Javascript, 11/8 bytes

x=>x**5%257


Domain/range is 1 through 256.

• Hm, is Javascript bad with large number exponents? This works in Ruby: repl.it/HXvZ/0 – histocrat Apr 24 '17 at 19:00
• JavaScript only has double-precision floats, so anything with more than ~53 bits cannot be represented exactly. x**3 and x**5 should work. – Dennis Apr 24 '17 at 19:02
• Well, serves me right for assuming. I'll change languages. – histocrat Apr 24 '17 at 19:03
• Or do Dennis's suggestion, given the rules favoring terser languages. :) Thank you! – histocrat Apr 24 '17 at 19:05
• Unfortunately, the rules are a bit broken at the moment, and I would be allowed to invert this with another language. Precisely because of the precision limit, this will be rather verbose to invert using JS. – Dennis Apr 24 '17 at 19:08

# JavaScript, 13 bytes 13/12

x=>(x<<9)%257


Input and output are both in the range 1->256

Try it online!

# Javascript, 27/29 bytes

x=>x-6?x*95%127+x*98%131:65


Edit: Range/Domain is 1..256. Generated via brute force, more or less.

• Sadly it's bijective but not in range [0,256): the value of 130 is never outputted but a value of 256 is (which doesn't fit a 8 bit int). – Christoph Apr 25 '17 at 6:27
• Score 27 / 29. I like it ! – Christoph Apr 25 '17 at 6:28
• Thanks! The rules allow me to specify a range of [1,256], and it's bijective on that range. – histocrat Apr 25 '17 at 13:01

# Octave, 16/6

@(x)mod(x*3,256)


Try it online!

• Score: 16/6 (Note: I don't think it should be allowed to use another language for the robber submission, but at this point, it is.) – Dennis Apr 24 '17 at 18:42
• It would also be interesting to know whether I can try to beat your robber submission by making another cop (again using Jelly or MATL too) – flawr Apr 24 '17 at 19:49

# Java, 35 bytes

int a(int v){return (v*v+v)%512/2;}


Domain/Range are 0-255

# Ruby, 23 bytes

->x{('228'*x).to_i%257}


Range and domain is 0..255. Concatenate 228 to itself x times, then take the result modulo 257 (0 maps to 0). 228 is the first magic number after 9 that works for this range (gives distinct values that don't include 256).

## Python 3, 55 bytes

y=lambda x,i=3:x if i==0 else pow(3,y(5*x,i-1),257)-1


Domain/Range is 0-255.

## Python 3, 32 bytes 32/23

V=lambda x:((3+x)%16)*16+x//16


Domain/Range is 0-255.

Flips the first four bytes with the last four, and adds a three to the first bytes.

# Mathematica, 13 bytes

Mod[#^7,257]&


Uses the range [1..256], although it's equally valid on the range [0..255]. To see the entire table, copy/paste one of the following lines of code into the Wolfram sandbox:

Array[ Mod[#^7,257]&, 256]   (for a list of values in order)
Array[ Rule[#,Mod[#^7,257]]&, 256]   (for a list of input-output rules)


# brainfuck, 37/11

,+++++[>+++++++<-]>++[<+++++++++>-]<.


Try it online!

Not very good but range of 0-255

• Score: 37/11 – Dennis Apr 27 '17 at 16:40
• @Dennis Nice job! I should not use such a bytey language. – Christopher Apr 27 '17 at 21:43
• By the way, censoring language names isn't a good idea. Yes, this particular languages has an ordinary and childish name, but everyone knows what the asterisk stands for, and it cannot be found by the search engine in its current form. – Dennis Apr 27 '17 at 21:46
• @Dennis finally fixed that – Christopher May 28 '17 at 20:05