## C - ~~165~~ 127

That was fun! Plain lookup table relying on a fixed offset for the lookup.

```
main(){
char*s="100011001110110v& x = |^> /~",
t[6]="0/xxx",
*u= strchr((gets(t+2),t),0)-3;
putchar(strchr(s,u[1])[*u*2+u[2]-159]);
}
```

For some reason `gets`

doesn't get implicitly declared, so when I removed the include I had to change `gets(t+2)`

to `(gets(t+2),t)`

(or similarly elsewhere, costing as much).

### Explanation

First of all, since the truth tables for the operators have plenty of overlapping characters we wish to store the lookup tables in a way so that we allow overlap. Here's how I chose to store them:

```
v & x = | ^ > ~ (operation)
1000 0001 0110 1001 0111 1110 1101 01 10 (truth table [order 00,01,10,11])
0 1 3 5 7 8 9 B D (offset in LUT below)
0123456789ABCDE (offsets)
100011001110110 (values)
```

Next, we want to map operator symbols to these offsets. We do this by storing the operator symbols in the same string at a fixed offset from the LUT data (namely, 16 characters later, i.e. directly after the LUT data). The lookup process is "find operator in `s`

, subtract `16`

, add `left*2+right`

(left/right operand). For the lookup of the empty "identity operation", due to how the input is fetched the operator in this case will resolve to whatever `t[1]`

is initialised to--in our case `/`

. Thus, we use `/`

as the lookup table key to represent the identity operation. When we process the unary `~`

operation "`left`

" (for the lookup calculation mentioned earlier) is always this same `/`

. `/`

happens to be one less than `0`

ASCII-wise, meaning when we compensate for ASCII digits `\`

will represent `-1`

. The slash in the lookup table key area (second-to-last character in `s`

, that is) is positioned to compensate for this.

Next up, input handling. The input has dynamic length, but it'd be easier if we have specific static names for the left operand, operator and right operand, regardless of input. If we pretend that we could read the input right-to-left, this would basically happen automagically--the right operand is always the rightmost character, the operator (if present) is second-to-rightmost, the left operand (if present) is third-to-rightmost. In order to be able to index the string like this, we use `strchr`

in order to locate the `\0`

terminator (`- 3`

to simplify indexing). This shows why `t[0]`

and `t[1]`

become the left operand/operator respectively when the input is 1 or 2 characters.

Putting it together, the output would be `putchar(strchr(s,u[1])[(u[0] - '0')*2 + (u[2] - '0') - 15])`

, but some refactoring and constant folding instead gets us the shorter `putchar(strchr(s,u[1])[u[0]*2+u[2]-159])`

.

3

I believe

– FireFly – 2013-10-07T15:23:42.327`^`

's symbol name should say caret.3@FireFly Haha, you're right. Too close to lunch! Thanks. – asteri – 2013-10-07T15:25:20.080