[Question]
  [
From the [Wikipedia article](https://en.wikipedia.org/wiki/Location_arithmetic):
> 
> Location arithmetic (Latin arithmeticæ localis) is the additive (non-positional) binary numeral systems, which John Napier explored as a computation technique in his treatise Rabdology (1617), both symbolically and on a chessboard-like grid.
> 
> 
> 
## What?
Location numerals is a way of writing numbers using letters of the alphabet.
> 
> Binary notation had not yet been standardized, so Napier used what he called location numerals to represent binary numbers. Napier's system uses sign-value notation to represent numbers; it uses successive letters from the English alphabet to represent successive powers of two: **a = 2^0 = 1, b = 2^1 = 2, c = 2^2 = 4, d = 2^3 = 8, e = 2^4 = 16** and so on.
> 
> 
> 
## An example
**`ab`** = 1+2 = 3 in base 10
**`aabb`** = 1+1+2+2 = 6 in base 10
Note that `aabb` can be shortened to `bc` by replacing any 2 instances of a letter by a higher one.
## Addition
You just concatenate the two numbers and simplify.
`acd` + `bde` = `acdbde` = `abcdde` = `acebe` = `abcf` = `39` in base 10
## Subtraction
Just remove all digits appearing equally in both parts of the subtraction. Expanding (converting `b` to `aa`) may be necessary
`abde`- `ad` = `be` = 18 in base 10
## Multiplication
This is a bit harder.
Lets say we want to multiply `acd` (13) by `def` (56). First you arrange `acd` vertically:
```
a
c
d
```
Then you add `def` after the first `a`:
```
a def
c
d
```
Now, c is 2 positions later in the alphabet than a, so we add 2 positions in the alphabet to `def` to make `fgh`. That is added to the second row.
```
a def
c fgh
d
```
Lastly, d is 1 position later in the alphabet than c, so we add 1 position in the alphabet to `fgh` to make `ghi`. That is added to the third row.
```
a def
c fgh
d ghi
```
Then you take the sum of the right: `def` + `fgh` + `ghi` = `deffgghhi` = `deggghhi` = `deghhhi` = `deghii` = `deghj` (728)
## Another example of multiplication
Input:
```
bc * de
```
First:
```
b
c
```
Then
```
b ef
c 
```
Then
```
b ef
c fg
```
**Note that we wrote down `ef` on the first line. That's because `bc` starts with `b`, and `b` is the second letter in the alphabet, so we need to shift `de` by 1 letter, so it becomes `ef`.** 
Then
```
ef+fg
```
Output: 
```
eh
```
## Division
This is not part of this challenge, because it can get very complex.
# Your actual challenge
Your program or function must take input as a string that looks like this:
```
a + b
```
And you must output:
```
ab
```
Of course, your program or function must support numbers of arbitrary length (up to the string or input limit of your language) with any of the operators `+`, `-`, or `*`. Some more examples:
Input:
```
ab + bd
```
Output:
```
acd
```
Input:
```
d - ab
```
Output:
```
ac
```
Input:
```
ab * cd
```
Output:
```
cf
```
# Notes:
* The order of letters in the output doesn't matter, but you can always assume that the order of letters in numbers in the input will be ascending (a before z).
* You may take input with a trailing newline and output with a trailing newline.
* You may *not* take input as a list of `ab`, `*` and `bd` for `ab * bd`.
* The english alphabet is used (`abcdefghijklmnopqrstuvwxyz`)
* Your output must be simplified (`aa` is not allowed, `b` is required)
* The input will be simplified (`b` + `c`, not `aa` + `bb` or `aa` + `aaaa`)
* You may require a space before and the operator (`+`, `-`, or `*`), or you may require there to be none.
* There will only be one operator per input.
* You may assume that the output and the input will never go over 2^27-1 (`abcdefghijklmnopqrstuvwxyz`)
* **This is [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'"), so the shortest answer in bytes wins!**
  
[Answer]
## Mathematica, 168 bytes
```
FixedPoint[StringReplace[x_~~x_:>FromCharacterCode[c@x+1]],Table["a",ToExpression@StringReplace[#,x:LetterCharacter..:>ToString@Tr[2^((c=ToCharacterCode)@x-97)]]]<>""]&
```
My initial solution (before the post was edited to clarify that the output must be simplified) was `64` bytes shorter:
```
Table["a",ToExpression@StringReplace[#,x:LetterCharacter..:>ToString@Tr[2^(ToCharacterCode@x-97)]]]<>""
```
This just modified that solution to work. It's probably shorter to actually use the methods described in the challenge, but I wanted to put this up anyway.
## Explanation:
Replaces each sequence of letters with its corresponding integer by character code arithmetic, then converts the resulting string to an expression (which will automatically simplify to an integer), then produces a string of `a` characters of length equal to that integer, and finally replaces adjacent identical characters with the next character code up until a fixed point is reached. 
[Answer]
## JavaScript (ES6), ~~136~~ ~~134~~ 133 bytes
*Saved 1 byte thanks to Luke*
```
s=>[...a='abcdefghijklmnopqrstuvwxyz'].filter((c,i)=>eval(s.replace(/\w+/g,s=>[...s].reduce((p,c)=>p|1<<a.search(c),0)))&1<<i).join``
```
### Test cases
```
let f =
s=>[...a='abcdefghijklmnopqrstuvwxyz'].filter((c,i)=>eval(s.replace(/\w+/g,s=>[...s].reduce((p,c)=>p|1<<a.search(c),0)))&1<<i).join``
console.log(f('ab + bd'));  // acd
console.log(f('d - ab'));   // ac
console.log(f('ab * cd'));  // cf
```
[Answer]
# [Perl 5](https://www.perl.org/), 95 bytes
94 bytes of code + `-p` flag.
```
s/\w/a x 2**(-97+ord$&)/ge;s/(.*)-\1|\+//;/\*/&&($_=$`x length$');1while s/(.)\1/chr 1+ord$1/e
```
[Try it online!](https://tio.run/nexus/perl5#JY7NbsMgEITvfoqtYvm3BNFLFVl9E6SWwGKQCDiA61Tqu7s4vcxqNd/s7OllweiALK46AXGgnZjBJoh4X21EBTpEuK0u28UhZEwZpEiYzgW3GrLBiAcfvPsp8o@8whLDt1XFybDZbMKaQVsvHHjcnPVY0t1hQIvSBCC@fRZZn7LwEvs9Ub5RAQ94G4aOXN7HEFXd9HTGKdHuPPSEs18@UjpRPtCm6erPj/rrAQ79nE3d9hPbjC0vH3TPGZUmAnteYRT3XUg1XhVWoggRqir7oFBXV1nGHw "Perl 5 – TIO Nexus")
Three steps here:  
- `s/\w/a x 2**(-97+ord$&)/ge;` converts the input into a string of `a` only.  
- `s/(.*)-\1|+//;/*/&&($_=$`x length$')` will execute the operator (that are very simple on strings of `a`): `+` is the concatenation, `-` means removing from the first part as many `a` as there are in the second part, and `*` means duplicating the first part as many times as there are `a` in the second part.  
- `1while s/(.)\1/chr 1+ord$1/e` folds the consecutive same letters into the next letter in the alphabet.
[Answer]
# [05AB1E](https://github.com/Adriandmen/05AB1E), 29 bytes
```
ð¡À¬U¦v0yvAyko+}}X.VbRvyiANèJ
```
[Try it online!](https://tio.run/nexus/05ab1e#@394w6GFhxsOrQk9tKzMoLLMsTI7X7u2NkIvLCmorDLT0e/wCq///xOTUxS0FFJS0wA "05AB1E – TIO Nexus") or as a [Test suite](https://tio.run/nexus/05ab1e#qymrDKv8f3jDoYWHGw6tCT20rMygssyxMjtfu7Y2Qi8sKaisMtPR7/AKr/@1tZFKh/dbKRzer6TzPzE5RUFbISkllQvE0lJISU3jSgSJcCUmgSW4UhR0FRLBXC2F5BQA)
**Explanation**
```
ð¡                             # split input on string
  À                            # rotate left
   ¬U¦                         # get the operator, store it in X and remove it from list
      v                        # for each side of the equation
       0                       # push 0 as an accumulator
        yv                     # for each letter in each side of the equation
          Ayk                  # get its index in the alphabet
             o                 # raise 2 to this power
              +                # add to the accumulator
               }}              # end loops
                 X.V           # apply the operator to the 2 numbers now on the stack
                    bR         # convert to binary and reverse
                      v        # for each binary digit
                       yi      # if it is true
                         ANè   # get the letter at that index in the alphabet
                            J  # join stack to a single string
```
[Answer]
# C & x86 asm, 340 Bytes
Compile with -O0
```
#define G getchar()
g(){int c,a=0;for(;islower(c=G);)a+=1<<(c-97);return a;}
main(){short o[]={[43]=0x4403,[45]=0x442b,[42]=0x6cf7};
mprotect((long)&&l&~4095,4096,7);
for(;;){int c,b=0,a=g();*(short*)&&l=o[G];G;g();asm("xchg %%eax,%0":"+m"(a));
l:asm("addl %1,%%eax":"=a"(c):"m"(a));
for(;a=c>>b;b++)if(a&=1)putchar(97+b);putchar(10);}}
```
**Explanation**
Since C doesn't have `eval()`, I used a table of x86 instructions in its place. I had to choose instructions which were all the same length (or padded with nops), and which expected src and destination of the same types. Of particular annoyance was that MUL can only write to registers, and the 1-byte MUL opcodes can only write to EAX. Additionally, there seemed to be no register-writing SUB instruction which subtracted from memory, instead of the other way around, hence the XCHG.
**edit**
Since it was asked in the comments, a more traditional appraoch would look
like this:
```
#define G getchar()
#define return r
#define int i
g(){i c,a=0;for(;islower(c=G);)a+=1<<(c-97);r a;}
a(i x,i y){r x+y;}s(i x,i y){r x-y;}m(i x,i y){r x*y;}
main(){i(*o[])(i,i)={[43]=a,[45]=s,[42]=m};
for(;;){i c,b,a=g();b=G;G;g();c=o[b](a,g());
for(b=0;a=c>>b;b++)if(a&=1)putchar(97+b);putchar(10);}}
```
It's actually a bit shorter, at 301 chars, for a few reasons: 1. Because there need to be a lot of functions, the overhead of each can be chopped with some preprocessor rules. 2. Modern linux protects from execution on the stack, so the mprotect() call to disable this sacrificed 34 bytes. 3. The XCHG call is very sub-optimal, costing another 30 bytes. If not for those things, the x86 combo would win by about 10-20 bytes.
Also chopped 2 bytes from both by improving the islower() call in g.
[Answer]
# GNU sed + coreutils, 329 bytes
Yeah, I have no idea what got into me, but at least I know sed scripting a bit better now. Note that this solution requires GNU sed's `e` extension, which runs a shell command.
```
/\+/{s/\+//
b S}
/-/{:E
/a+-a+/{s/(a*)(a*)-\2/\1/
b S}
s/.*/echo &|tr b-z- A-Y-/
e
s/([A-Z])/\L\1\1/g
b E}
/\*/{h
:M
/^\*/{x
s/[^\n]*//
s/\n//g
b S}
s/(.).*\*(.*)/echo \2|tr a-z \1-za-z/
e
H
g
s/.(.*)/\1/
h
s/\n.*//
b M}
:S
s/^.*$/echo &|grep -o .|sort|tr -d '\n'/
e
:L
s/(.)\1/\u\1/g
/^[a-z]*$/ q
s/.*/echo &|tr A-Z b-za/;e
b L
```
I assume that there will not be spaces around the operators. From my terminal:
```
$ sed -rf golf.sed <<< a+b
ab
$ sed -rf golf.sed <<< ab+bd
acd
$ sed -rf golf.sed <<< abc+b
ad
$ sed -rf golf.sed <<< d-ab
ca
$ sed -rf golf.sed <<< ab*cd
cf
$ sed -rf golf.sed <<< bc*de
eh
$ sed -rf golf.sed <<< acd*def
deghj
```
And, for those saner than I: the commented version!
```
#!/bin/sed -rf
/\+/ {
    s/\+//
    b simplify
}
/-/ {
    # expand pattern space; everything will now be 'a's
    :E
    /a+-a+/{
        # Remove doubled 'a's on either side of the dash. For example,
        # for input d-ab, space is now 'aaaa-aaa'; substitute this to 'a'
        s/(a*)(a*)-\2/\1/
        b simplify
    }
    # shift letters that aren't 'a' down and double them
    s/.*/echo &|tr b-z- A-Y-/;e
    s/([A-Z])/\L\1\1/g
    b E
}
/\*/ {
    # Hold space: line 1 is pattern, other lines are output
    h
    :M
    # if space starts with *, we've eaten entire arg0; sum and simplify
    /^\*/ {
        x
        s/[^\n]*//      # remove first line, which is our pattern
        s/\n//g         # remove newlines to add results together
        b simplify
    }
    # convert pattern into shifting command
    s/(.).*\*(.*)/echo \2|tr a-z \1-za-z/
    # execute it, append result to hold space
    e
    H
    # restore pattern, with leading char and all output lines removed
    g
    s/.(.*)/\1/
    h
    s/\n.*//
    b M
}
:simplify
# reorder all letters so all 'a's are before all 'b's are before all 'c's
# are before ... etc    
# See https://stackoverflow.com/questions/2373874
s/^.*$/echo &|grep -o .|sort|tr -d '\n'/
e
:L
# Replace repeated characters with themselves upper-cased, then translate
# upper-cased characters to what they should be.
s/(.)\1/\u\1/g
/^[a-z]*$/ q
s/.*/echo &|tr A-Z b-za/;e
b L
```
[Answer]
# PHP, 168
Output Ascending with use of eval
```
[$a,$o,$b]=explode(" ",$argn);function d($s){for(;$i<strlen($s);)$n+=2**(ord($s[$i++])-97);return$n;}for(eval("\$k=d($a)$o d($b);");$i<26;)echo$k&2**$i++?chr(96+$i):"";
```
# PHP, 185 Bytes
Output Ascending
```
[$a,$o,$b]=explode(" ",$argn);function d($s){for(;$i<strlen($s);)$n+=2**(ord($s[$i++])-97);return$n;}for(;$i<26;)echo(bc.[mul,add,0,sub][ord($o)-42])(d($a),d($b))&2**$i++?chr(96+$i):"";
```
[Online Version](http://sandbox.onlinephpfunctions.com/code/ba38afb7a46b7e54297f3a6d929c464e4af90c4f)
Expanded
```
[$a,$o,$b]=explode(" ",$argn); # part the input into variables
function d($s){ # make decimal value
    for(;$i<strlen($s);)$n+=2**(ord($s[$i++])-97);
    return$n;
}
for(;$i<26;)
echo(bc.[mul,add,0,sub][ord($o)-42])(d($a),d($b))&2**$i++?chr(96+$i):""; # Bitwise Compare and Output
```
## PHP, 201 Bytes
Output Decending
```
[$a,$o,$b]=explode(" ",$argn);function d($s){for(;$i<strlen($s);)$n+=2**(ord($s[$i++])-97);return$n;}for($r=(bc.[mul,add,0,sub][ord($o)-42])(d($a),d($b));$r;$r-=2**$l)$t.=chr(97+$l=log($r,2)^0);echo$t;
```
[Online Version](http://sandbox.onlinephpfunctions.com/code/b11688e83798dedb2eb15acee83a80f5881eee6f)
Expanded
```
[$a,$o,$b]=explode(" ",$argn); # part the input into variables
function d($s){ # make decimal value
    for(;$i<strlen($s);)$n+=2**(ord($s[$i++])-97);
    return$n;
}
for(
$r=(bc.[mul,add,0,sub][ord($o)-42])(d($a),d($b)) # result of the operation
;$r;
$r-=2**$l) # subtract the letter value 
$t.=chr(97+$l=log($r,2)^0); # find greatest letter
echo$t; # Output
```
[Answer]
# [Python 3](https://docs.python.org/3/), 176 167 bytes
```
i=lambda a:str(sum(1<<ord(i)-97for i in a))
def f(a):
 a,b,c=a.split();m=eval(i(a)+b+i(c));r=''
 while m:
  t=0
  while m>=2**t*2:t+=1
  r+=chr(97+t);m-=2**t
 return r
```
[Try it online!](https://tio.run/nexus/python3#LYxJDoMwDEX3OYV32ASqwgYxpHdxGIQlJpnQHp9GVTd/8Z7ev8UtvPqBgZszKJ7XikXX7TqgUF5X064gIBswkRnGCSZkagxw5rPe8eM8FglI7erGNy8o0VpvBXuiVl2SGPjMsoywxgaCe8b9g5cr0zSkZROsKyJW6/pZsa5siHf5zxrQMVy6gd6HyhZwwoQ9WPBDQnR/AQ "Python 3 – TIO Nexus")
* saved 9 bytes: Thanks to [tutleman](https://codegolf.stackexchange.com/users/64834/tutleman)
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), ~~26~~ 25 [bytes](https://github.com/DennisMitchell/jelly/wiki/Code-page)
```
i@€Øað’2*S;ḟ.Ḣ
ḲÇ€VBṚTịØa
```
Uses Jelly's operators (`×` rather than `*` and `_` rather than `-`) in the input string as [allowed by the OP](https://codegolf.stackexchange.com/questions/116017/lets-do-some-location-arithmetic#comment283341_116017).
(Requires spaces around the operators)
**[Try it online!](https://tio.run/nexus/jelly#@5/p8KhpzeEZiYc3PGqYaaQVbP1wx3y9hzsWcT3cselwO1AuzOnhzlkhD3d3AxX9//8/MUnh8HSF5BQA)** or see the [test suite](https://tio.run/nexus/jelly#@5/p8KhpzeEZiYc3PGqYaaQVbP1wx3y9hzsWcT3cselwO1AuzOnhzlkhD3d3AxX9f7h7y6GtR/eAJbKA@FHDHAVbhUcNcyP//09MTlE4PF0hJTWNKykZwuJKVNBWSOJKTAJRKVwpCvEKiWAuUDY5BQA)
### How?
```
i@€Øað’2*S;ḟ.Ḣ - Link 1, transform from input sub-string to value or operator: sub-string
i@€            - 1st index of, for €ach (or 0 if not found) [reversed @rguments] in:
   Øa          -      lowercase alphabet (i.e. a->1, b->2, ..., non-alpha->0)
     ð         - dyadic chain separation i.e. f(result above, substring):
      ’        - decrement (i.e a->0, b->1, ..., non-alpha->-1)
       2*      - 2 raised to that power
         S     - sum
          ;    - concatenate with the substring
           ḟ   - filter out:
            .  -     0.5 (for an operator substring the evaluated 0.5 is removed)
             Ḣ - head (i.e. the evaluation for a location, and the operator otherwise)
ḲÇ€VBṚTịØa - Main link: string                        e.g. 'ab × cd'
Ḳ          - split on spaces                               [['a','b'],['×'],['c','d']]
 Ç€        - last link (1) as a monadic function for €ach  [3,'×',12]
   V       - evaluate as Jelly code                        36
    B      - convert to binary                             [1,0,0,1,0,0]
     Ṛ     - reverse                                       [0,0,1,0,0,1]
      T    - truthy indexes                                [3,6]
       ị   - index into:
        Øa -     lowercase alphabet                        ['c','f'] (i.e. "cf", which is implicitly printed when run as a full program)
```
[Answer]
# PHP, 130
```
for($d=a;$e=$argn[$i++];)$e!=' '?$d!=b?$$d+=1<<ord($e)-97:$b=$e:++$d;eval("for(;\$j++<27;)echo($a$b$c>>\$j-1)&1?chr(96+\$j):'';");
```
expanded version:
```
for($d=a;$e=$argn[$i++];)       // for each char in the input
  $e!=' '?                      //   if space
    $d!=b?                      //     if not the operation
      $$d+=1<<ord($e)-97:       //       add 2^(char - 'a')
      $b=$e:                    //     else save operation
    ++$d;                       //   else increase "pointer"
eval("for(;\$j++<27;)           // for each bit in the output
        echo($a$b$c>>\$j-1)&1?  //   calulate the result and check the bit
          chr(96+\$j):          //     output corrosponding char
          '';                   //     output nothing
     ");
```
run with `php -R <code>`.
[Answer]
# AWK, 201 bytes
```
BEGIN{RS="(.)"}n=index(V="abcdefghijklmnopqrstuvwxyz",RT){s+=2^--n}index("+-*",RT){a=s RT
s=0}END{RS="\n"
"(awk '$0="a s"'<<<1)"|getline v
for(j=26;j--;)if((s=v-2^j)>=0){v=s;c=substr(V,j+1,1)c}print c}
```
`"(awk '$0="a s"'<<<1)"|getline v` is the best way I could come up with to do an `evaluate` in `AWK`. I may be "cheating" a little to call this just `AWK`, since I am executing a command, but at least the command is also `AWK` :)
I'm sure I'm missing some way to reduce the byte-count, but I sure can't see it.
Usage is fairly standard, e.g. put the code in `FILE` and do:
```
awk -f FILE <<< "bc + ab"
```
Note that spaces are not required and any non-op/non[a-z] character will be silently ignored. Could be extended to work with numbers greater than "abcdefghijklmnopqrstuvwxyz" by changing the loop. To do division, simply add the `/` character to the operation string :). Also, will print a blank line if the `result <= 0`.
]