# Cheapo Enigma machine (Robbers)

For cops' post, Cheapo Enigma machine (Cops)

A robber's submission consists of a program/function that accepts the output of a cop's code and returns the input for all the outputs provided by that cop's code. (In other words, you must write the inverse function)

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

# 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 must belong to the same range (as in, binary, 1-256, 0-255 or -128 to 127), which must also be the same range as that used by the cop.

# Scoring

Ratio of the cop's byte count to your byte count. Highest score wins.

You can submit a robber attempt against your own cop code for reference. (Of course this code isn't eligible for winning)

• At first I was wondering how you were going to make Emigna into a machine. Then I realized you weren't talking about the user. Apr 24 '17 at 18:39
• OK, sorry for bothering you again, but I want to make sure I got it right this time. If the brainfuck answer reads and prints bytes (code points 0 to 255) and my Jelly answer takes an integer between 0 and 255 and returns an integer in the same range, is that acceptable? Apr 28 '17 at 15:32
• @Dennis No, it isn't. Maybe you (or someone else) could suggest an alternate wording that makes this clearer. Apr 28 '17 at 16:12
• @carusocomputing Emigna is a machine, right? He has every single 05AB1E program loaded up in his memory system, yeah? Jun 18 '17 at 23:17

## JavaScript by Christoph, 8/25

f=(y,x=0)=>y?f(y/2,x^y):x


(range 0-255)

Sadly, f=(y,x)=>y?f(y/2,x^y):x works for all values except 0.

### Technical note

We use y/2 rather than y>>1 to save a byte. This is abusing the fact that any value of y will eventually be rounded to 0 because of arithmetic underflow.

## JavaScript by fəˈnɛtɪk, 13/19

x=>((514>>x%2)-x)/2


(range 1-256)

# C, by Dave, 64/9592 85

b,i,e,t[256];r(x){for(;!b;++i,b=e==x)for(srand(i&&e);t[e=rand()%256]++;);return i-1;}


# C, shorter version, 64/89 71

i,e,t[256];r(x){for(srand(1);t[e=rand()%256]++||++i,e!=x;);return i-1;}


This one is more implementation specific, but works on TIO. Same length as the PHP solution, I wasn't able to get it any shorter than this.

• Ok I will take it up with the cops submission then. Thanks for informing me. Apr 28 '17 at 5:05

# JavaScript by fəˈnɛtɪk, 13 / 12

x=>x*128%257


Another multiplicative inverse.

# JavaScript, 11/13

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


Try it online!

# Jelly, 22/3 = 7 1/3

⁹ḶDÞḊi


Try it online!

The cop submission by fəˈnɛtɪk was to return the nth (0-indexed) lexicographically sorted decimal number using the domain [0,255].

I first literally reversed the operation described, ⁹ḶDÞi⁸‘ - takes the lowered range of 256, ⁹Ḷ, and Þ instructs to sort it by a key function of conversion to a decimal list, D; then finds the index of, i, the input, ⁸, and subtracts 1, ‘ (Jelly lists are 1-indexed).

Then I golfed it by dequeuing the sorted list with Ḋ. When an item is not found i returns 0 as required for the removed first element (0), while everything else is found one index earlier, allowing the removal of the decrement, ‘, which in turn gives i implicit input on its right from the left (only) input to the monadic link.

# Javascript by Magenta, 32 / 23

x=>x%16*16+(x/16+13)%16


Code basically switches the lower and the upper 4 bits and does a modulo addition on one part.

# Javascript by histocrat, 27 / 29

x=>x-65?x-126?x*127%258:131:6


Sadly two hard codings are needed in order to break it. Note that the orginal function doesn't map any value to 130 but maps a value to 256.

• Having 256 in the range is legal according to the rules ("8 bits (0 or 1), or a base-10 integer in range 1-256"). This is still a valid Robber on that range, though! Apr 25 '17 at 13:05

# PHP, Score 64/71

for(srand(0);$a<256;)$b[$c=rand()%256]++||$d[$c]=$a++;echo$d[$argn]|0;


Luckily PHP's rand just forwards to the stdlib like C. So this works as long as we're using the same stdlib. This means it works on TIO but not on e.g. sandbox.onlinephpfunctions.com. The current version of Dave's code just iterates over a pseudorandom sequence and returns the nth unique value so I guess there might be much shorter answers if a golfing languages also uses the stdlib.

Here's an implementation of Dave's code that does not dependent on the stdlib. That might also help.

• +1 for finding a way to switch language on this one! Any idea why this doesn't need to srand(1)? Also here's a Try it online!
– Dave
Apr 28 '17 at 12:10
• @Dave srand(x&&f(x-1)) this stops only if x==0 therefore it gets seeded with 0 on the first round. Not sure why the next calls don't change it. Apr 28 '17 at 12:47
• @Dave it seems srand(0) breaks rand (see here). I guess srand(0) automatically gets promoted to srand(1). I guess if you could use a different seed each time it would get a lot harder to break it. Apr 28 '17 at 12:55
• Interesting that this works. Seems to be specific to the stdlib version used on TIO, the behaviour in C on there is apparently the same, while on my local machine with clang it requires to re-invoke srand with 0 resp. 1 on each iteration, instead of just invoking it once with 0. Apr 28 '17 at 18:02
• @Appleshell seems Christoph's suspicions are correct: glibc has a special check. See here: stackoverflow.com/a/8049852/1180785 (since you mention clang, I'm guessing your local is OSX, so no glibc)
– Dave
Apr 28 '17 at 18:09

# Octave, 16/18

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


Try it online!

^H$7¡  Try it online to see the whole table. # Jelly, 8/5 ^H$7¡


Try it online to see the whole table.

# Jelly, 16/6

×171%⁹


Try it online to see the whole table.

# Jelly, 11/8

*205%257


Try it online to see the whole table.

In case robber submissions in a different languages are disallowed in the future, I call dibs on the following solution.

g=(x,y=0)=>x-++y**5%257?g(x,y):y


# Jelly, 35/7

⁹Ṗ+\%⁹i


Try it online to see the whole table.

# C (gcc) by Bijan, 32 / 30

g(x){x=x?g(--x)*205+51&255:0;}


Had a fun time golfing it, thanks ! x= allows to skip return with gcc and tcc (you might want to change your answer to include it). g(--x)*205+51&255 is the inverse.

# Jelly, 37/11

O_77×191%⁹Ọ


Uses the same I/O format as the cop. Not sure if that is required.

Try it online to see the whole table.

### How it works

For input n, the cop answer computes f(n) := ((((n + 5) % 256 × 2) % 256 + 2) % 256 × 9) % 256. Since % is a linear operator, this is equivalent to f(n) = (((n + 5) × 7 + 2) × 9) % 256. Expanding the right term, we get f(n) = (63n + 333) % 256 = (63n + 77) % 256.

Reversing this is rather straightforward. To undo the addition, we simply have to subtract 77. Also, since 191 × 63 % 256 = 12033 % 256 = 1, it follows that 191 is 63's inverse modulo 256, so multiplying by 191 undoes multiplying by 63. This way, g(n) = (n - 77) × 191 % 256 defines the inverse of f.