[Question]
  [
# Preamble
[Integers](https://en.wikipedia.org/wiki/Integer) are always either [even or odd](https://en.wikipedia.org/wiki/Parity_(mathematics)). Even integers are divisible by two, odd integers are not.
When you add two integers you can infer whether the result will be even or odd based on whether the summands were even or odd:
* Even + Even = Even
* Even + Odd = Odd
* Odd + Even = Odd
* Odd + Odd = Even
Likewise, when you multiply two integers you can infer whether the result will be even or odd based on whether the factors were even or odd:
* Even \* Even = Even
* Even \* Odd = Even
* Odd \* Even = Even
* Odd \* Odd = Odd
Thus, if you know the evenness or oddness of all the variables in a math expression that only involves addition and multiplication, you can infer whether the result will be even or odd.
For example, we can confidently say that `(68 + 99) * 37` results in an odd because an even plus an odd (`68 + 99`) is an odd, and that odd times another odd (`odd * 37`) gives an odd.
# Challenge
Write a program or function that takes in a string only containing the four characters `eo+*`. This string represents a mathematical expression given in [prefix notation](https://en.wikipedia.org/wiki/Polish_notation) involving only addition (`+`) and multiplication (`*`). Each `e` represents some arbitrary even number, and each `o` represents some arbitrary odd number.
Your task is to simplify the expression, printing or returning a single `e` or `o` based on whether the result of the expression is even or odd.
You can assume that the input will always be in valid prefix notation. Specifically, each `+` and `*` will always have two corresponding operands occurring after it. These operands may be a single `e` or `o`, or another `+` or `*` expression that in turn has operands.
For example, the input `*+eoo` could be read as `mul(add(e, o), o)`, or `(e + o) * o` in normal [infix notation](https://en.wikipedia.org/wiki/Infix_notation). The `e` and the first `o` are the operands corresponding to the `+`, and `+eo` and the last `o` are the operands corresponding to the `*`.
Just to make it clear, here are some invalid inputs that have incorrect prefix notation:
```
eo
ooe
o+e
ee*
+*oe
+e*o
```
A single trailing newline in the output is fine, but otherwise a plain `e` for even or `o` for odd is all that should be output.
**The shortest code in bytes wins.**
# Test Cases
(Empty lines are only to help visually separate similar cases.)
```
e -> e
o -> o
+ee -> e
+eo -> o
+oe -> o
+oo -> e
*ee -> e
*eo -> e
*oe -> e
*oo -> o
+e+ee -> e
+e+eo -> o
+e+oe -> o
+e+oo -> e
+e*ee -> e
+e*eo -> e
+e*oe -> e
+e*oo -> o
+o+ee -> o
+o+eo -> e
+o+oe -> e
+o+oo -> o
+o*ee -> o
+o*eo -> o
+o*oe -> o
+o*oo -> e
*e+ee -> e
*e+eo -> e
*e+oe -> e
*e+oo -> e
*e*ee -> e
*e*eo -> e
*e*oe -> e
*e*oo -> e
*o+ee -> e
*o+eo -> o
*o+oe -> o
*o+oo -> e
*o*ee -> e
*o*eo -> e
*o*oe -> e
*o*oo -> o
++eee -> e
++eeo -> o
++eoe -> o
++eoo -> e
++oee -> o
++oeo -> e
++ooe -> e
++ooo -> o
+*eee -> e
+*eeo -> o
+*eoe -> e
+*eoo -> o
+*oee -> e
+*oeo -> o
+*ooe -> o
+*ooo -> e
*+eee -> e
*+eeo -> e
*+eoe -> e
*+eoo -> o
*+oee -> e
*+oeo -> o
*+ooe -> e
*+ooo -> e
**eee -> e
**eeo -> e
**eoe -> e
**eoo -> e
**oee -> e
**oeo -> e
**ooe -> e
**ooo -> o
+e+e+e+ee -> e
+o+o+o+oo -> o
*e*e*e*ee -> e
*o*o*o*oo -> o
+e+o+e+oe -> e
+o+e+o+eo -> o
*e*o*e*oe -> e
*o*e*o*eo -> e
+e*e+e*ee -> e
+o*o+o*oo -> o
*e+e*e+ee -> e
*o+o*o+oo -> o
+**++*+*eeoeeooee -> e
+**++*+***eooeoeooeoe -> e
+**+***+**++**+eooeoeeoeeoeooeo -> o
+e*o*e**eoe -> e
+*e+e+o+e**eeoe -> e
**o++*ee*++eoe*eo+eoo -> o
```
  
[Answer]
## CJam, ~~18~~ ~~17~~ 13 bytes
*Thanks to aditsu for saving 4 bytes.*
```
qW:O%eu~"eo"=
```
[Try the test suite here.](http://cjam.aditsu.net/#code=qN%2F%7B%22%20-%3E%20%22%2F_1%3D%3AR%3B0%3D%3AQ%7B%0A%0AQW%3AO%25eu~%22eo%22%3D%0A%0A%5D%3AQoSoQsR%3Dp%7D%26%7D%2F) (The test suite is too long for the permalink. Just copy them from the challenge spec.)
### Explanation
```
q     e# Read the input.
W:O   e# Push a -1 and store it in variable O.
%     e# Use the -1 to reverse the string, because CJam's stack-based nature and the
      e# commutativity of the operators means we can evaluate the code in postfix notation.
eu    e# Convert the string to upper case, turning 'e' into 'E' (a variable with even value
      e# 14) and 'o' into 'O' (which we've stored the odd value -1 in).
~     e# Evaluate the string as CJam code, leaving the result on the stack.
"eo"= e# Use the result as an index into the string "eo". CJam's indexing is cyclic so it
      e# automatically takes inputs modulo 2. Negative indices also work as expected.
```
[Answer]
# Pyth, ~~16~~ 14 bytes
```
@"eo".vjdXzGU9
```
Pyth can itself evaluate a string, that is in Pyth syntax. Therefore I replace `e` and `o` with `4` and `5`. Then the evaluation will give me an even or odd number, and I can easily print the result. 
Try it online: [Demonstration](http://pyth.herokuapp.com/?code=%40%22eo%22.vjdXzGU9&test_suite=0&input=%2B%2A%2A%2B%2A%2A%2A%2B%2A%2A%2B%2B%2A%2A%2Beooeoeeoeeoeooeo&test_suite_input=%2B%2A%2A%2B%2B%2A%2B%2Aeeoeeooee%0A%2B%2A%2A%2B%2B%2A%2B%2A%2A%2Aeooeoeooeoe%0A%2B%2A%2A%2B%2A%2A%2A%2B%2A%2A%2B%2B%2A%2A%2Beooeoeeoeeoeooeo%0A%2Be%2Ao%2Ae%2A%2Aeoe%0A%2B%2Ae%2Be%2Bo%2Be%2A%2Aeeoe%0A%2A%2Ao%2B%2B%2Aee%2A%2B%2Beoe%2Aeo%2Beoo) or [Test Suite](http://pyth.herokuapp.com/?code=%40%22eo%22.vjdXzGU9&test_suite=1&input=%2B%2A%2A%2B%2A%2A%2A%2B%2A%2A%2B%2B%2A%2A%2Beooeoeeoeeoeooeo&test_suite_input=%2B%2A%2A%2B%2B%2A%2B%2Aeeoeeooee%0A%2B%2A%2A%2B%2B%2A%2B%2A%2A%2Aeooeoeooeoe%0A%2B%2A%2A%2B%2A%2A%2A%2B%2A%2A%2B%2B%2A%2A%2Beooeoeeoeeoeooeo%0A%2Be%2Ao%2Ae%2A%2Aeoe%0A%2B%2Ae%2Be%2Bo%2Be%2A%2Aeeoe%0A%2A%2Ao%2B%2B%2Aee%2A%2B%2Beoe%2Aeo%2Beoo)
### Explanation:
```
@"eo".vjdXzGU9   implicit: z = input string
         XzGU9   replace "e" in z with 4 and "o" with 5
       jd        put a space between each char
     .v          evaluate it (Pyth style)
@"eo"            and print "e" or "o"
```
Additional explanation to the replace. `G` is a variable initialized with the alphabet `abc...xyz`. `U9` is the list `[0, 1, ..., 8]`. `XzGU9` replaces the letters of the alphabet with the values of the list. So `a` gets replaced with `0`, `b` with `1`, ..., `e` with `4`, ..., `i` with `8`, `j` with `0`, ..., and `o` with `5`. Therefore I `e` gets replaced with an even number and `o` with an odd number. All the other replacements have no effect at all. 
[Answer]
# Perl, ~~50~~ ~~45~~ 40 characters
(39 characters code + 1 character command line option.)
```
1while s/\+oe|\+eo|\*oo/o/||s/\W\w\w/e/
```
Sample run:
```
bash-4.3$ echo -n '**o++*ee*++eoe*eo+eoo' | perl -pe '1while s/\+oe|\+eo|\*oo/o/||s/\W\w\w/e/'
o
```
[Answer]
# Python 2, 90
```
def f(s):i=iter(s);a=next(i);return(a>'a')*a or'oe'[f(i)==f(i)if'*'<a else'e'in f(i)+f(i)]
```
The `iter` function is a good way to make the input string into a FIFO queue which remembers how much of the string has been parsed across calls of `f`. It is idempotent, so it is harmless to call it again when the input is already an iterator rather than a string. The trailing half of the answer beginning with `or'oe'`... seems like it should be golfable, but I couldn't find anything.
-1 thanks to Sp3000.
[Answer]
# [Retina](https://github.com/mbuettner/retina), 29 bytes
```
(+`\*oo|\+(eo|oe)
o
\W\w\w
e
```
For the convenient one file version the `-s` flag is used.
We swap odd expressions (`*oo`, `+oe`, `+eo`) to `o` until we can, then swap the remaining symbol-letter-letter expressions to `e`. We repeat this until we can and the final one letter is our output.
(This solution is similar to [manatwork's Perl answer](https://codegolf.stackexchange.com/a/65529/7311).)
[Try it online!](http://retina.tryitonline.net/#code=KCtgXCpvb3xcKyhlb3xvZSkKbwpcV1x3XHcKZQ&input=K2Uqb28) (by Dennis)
[Answer]
## Python 2, 80 bytes
```
def f(s,e=0,o=1):i=iter(s);a=next(i);return(a>'a')*a or'eo'[eval(f(i)+a+f(i))%2]
```
This is built on feersum's [very clever answer](https://codegolf.stackexchange.com/a/65532/20260) that uses an `iter` to implement Polish-notation operations. The new idea is to use `eval` to evaluate the expressions `+` and `*` with `eval(f(i)+a+f(i))`, where the operator `a` is placed infix between the recursive results. The eval uses the bindings `e=0,o=1` in the optional function arguments. The output is then taken mod 2.
[Answer]
## Mathematica, ~~91~~ 84 bytes
```
#//.s_:>s~StringReplace~{"+ee"|"+oo"|"*ee"|"*eo"|"*oe"->"e","+eo"|"+oe"|"*oo"->"o"}&
```
Looking for a way to compress this...
[Answer]
## C, 79 bytes
Straightforward recursion. Relies on some (coincidental?) bitwise properties of the four allowed input characters.
```
f(){int c=getchar();return c&4?c:c&1?f()^f()^'e':f()&f();}main(){putchar(f());}
```
[Answer]
# Shell + GNU utilities, 33
```
dc -eFo`rev|tr oe OK`2%p|tr 10 oe
```
Input is taken from STDIN.
This does the same trick of reversing the input and evaluating with a stack-based calculator - in this case `dc`. We could replace `e` and `o` with `0` and `1`, but then spaces would need to be inserted to prevent greedy parsing of the digits into the incorrect numbers.
Instead `e` is replaced with `K` which is the `dc` command to push the current precision to the stack, which by default is 0. And `o` is replaced with `O` which is the `dc` command to push the current output base to the stack. This needs to be odd, so we set it to 15 with `Fo` before doing anything else in dc.
Then it is simply a matter of taking mod 2 and printing `2%p`. The only possible values are now `0` and `1`, so it doesn't matter that the output base is 15. Then `tr` translates back to `o` or `e`.
---
I like that if you squint your eyes, this source almost looks like `dc Forever OK`.
[Answer]
## [Seriously](https://github.com/Mego/Seriously), 24 bytes
```
,R'2'e(Æ'1'o(Æ£ƒ'e'o2(%I
```
More efficient stack manipulation could probably make this shorter, but meh, I'm happy with it.
Takes input as a string, like `"+*oee"`
[Try it online](http://seriouslylang.herokuapp.com/link/code=2c522732276528922731276f28929c9f2765276f32282549&input=) (input must be manually entered)
Explanation:
```
,R        get input and reverse it
'2'e(Æ    replace all "e"s with "2"s
'1'o(Æ    replace all "o"s with "1"s
£ƒ        cast as function and call
'e'o2(%I  push "e" if result is even, else "o"
```
[Answer]
# Ruby, 61 bytes
Using recursive descent parsing and boolean algebra.
```
def f
gets(1)==?+?f^f : ~/\*/?f&f : $_==?o
end
puts f ? ?o:?e
```
The function reads one character from stdin at a time. If it reads a `+` or a `*`, it calls itself twice to determine odd or even. The function returns `true` for odd and `false` for `even`. The `^` *XOR* and `&` *AND* operators are used to determine "oddness" of addition and multiplication expressions respectively.
Here's an ungolfed version:
```
def f
  x = gets(1)
  case x
  when '+'
    f ^ f
  when '*'
    f & f
  else
    x == 'o'
  end
end
puts f ? 'o' : 'e'
```
Thanks @Shel for pointing out a bug in the initial version.
[Answer]
# [Vyxal](https://github.com/Vyxal/Vyxal), 13 bytes
```
‛oe₀Ŀ∑ṘṄĖ₂∆ċt
```
[Try it Online!](https://vyxal.pythonanywhere.com/#WyIiLCIiLCLigJtvZeKCgMS/4oiR4bmY4bmExJbigoLiiIbEi3QiLCIiLCIqbytlbyJd)
```
    Ŀ∑        # Replace each of 
‛oe           # o and e
   ₀          # With 1 and 0
      Ṙ       # Reverse 
       Ṅ      # Join by spaces
        Ė     # Eval
         ₂    # Even? (1-n%2)
          ∆ċt # Last character of num -> cardinal (one -> e, zero -> o)
```
[Answer]
## [Minkolang 0.14](https://github.com/elendiastarman/Minkolang), 40 bytes
I tried to do a clever eval method, but it turns out that any values added to the codebox outside of the original space will never be reached by the program counter. So I did a less clever eval method. :P
```
$o"eo+*"r0I4-[4g1Z2*1F]l*"e"+O.
0f1f+f*f
```
[Try it here.](http://play.starmaninnovations.com/minkolang/?code=%24o%22eo%2B*%22r0I4-%5B4g1Z2*1F%5Dl*%22e%22%2BO%2E%0A0f1f%2Bf*f&input=**o%2B%2B*ee*%2B%2Beoe*eo%2Beoo)
### Explanation
```
$o                                Read in whole input as characters
  "eo+*"                          Push these characters onto the stack (in reverse order)
        r                         Reverse the stack
         I4-                      Push the length of the stack - 4
            [                     For loop; pop n and repeat that many times
             4g                   Get the item at the fourth index and put it on top
               1Z                 Pops n and pushes first index of n in stack
                 2*               Multiply by 2
                   1F             Gosub; goes to codebox(2n,1) to be returned to
                     ]            Close for loop
                      l*          Multiply by 10
                        "e"+      Add 101 ("o" is 111)
                            O.    Output as character and stop.
0f1f+f*f                          Does the appropriate operation then returns to F
```
[Answer]
# JavaScript, 110 106 94 bytes
```
while(i.length>2)i=i.replace(/([+*][eo]{2})/,(o,e)=>{return"+oe+eo*oo".indexOf(o)<0?"e":"o"});
```
Certainly not the smallest solution, but likely the smallest solution possible in a verbose language like JavaScript!
[Answer]
# [O](https://github.com/phase/o), ~~24~~ ~~20~~ ~~19~~ 18 bytes
```
i`2:e;1:o;~2%'o'e?
```
Takes input, reverses it, assigns `e` to *2* and `o` to *1* and ~~posts it to Tumblr~~ evaluates it as O code.
Explanation:
```
i`     Get input and reverse it, because O uses postfix notation
2:e;   Assign `e` to 2
1:o;   Assign `o` to 1
~2%    Eval and check if result is even
'o'e?  Output 'e' if even, 'o' if odd
```
[Answer]
# GNU Sed, 36
```
:
s/*oo\|+eo\|+oe/o/
t
s/\W\w\w/e/
t
```
After posting I saw this exactly the same approach as [@manatwork's Perl answer](https://codegolf.stackexchange.com/a/65529/11259) and [@randomra's Retina answer](https://codegolf.stackexchange.com/a/65535/11259). So I guess I may as well go all the way and borrow their `\W\w\w` as well.
Thanks to @Ruud for shaving off 4 bytes.
[Answer]
# Haskell, 160 bytes
Call `f`.
```
f=until((==1).l)r
r s|l s<3=s|3#s?o=r('o':3%s)|3#s?sequence["+*","oe","oe"]=r('e':3%s)|0<1=1#s++r(1%s)
l=length
(#)=take
(%)=drop
(?)=elem
o=["+eo","+oe","*oo"]
```
[Answer]
# Jolf, 11 bytes
(Noncompetitive, as the language postdates the question.) [Try it here!](http://conorobrien-foxx.github.io/Jolf/index.html#code=RlZ5QWkib2UiQAw)
```
FVyAi"oe"@\x12
```
(Replace `\x12` with the actual character `\x12`. This should be done automatically in the interpreter.)
Explanation:
```
FVyAi"oe"@\x12
    i          input
          \x12 character 12
         @     char code at
   A "oe"      replace all os with 1s and all es with 2s
  y            eval as jolf, returning the answer
 V             return parity "even" or "odd"
F              get first character
               implicit output
```
[Answer]
## JavaScript, ~~92~~ 71 bytes
```
f=i=>i>"0"?i:f(i.replace(/.[eo]{2}/,e=>"eo"[eval((e[1]>"e")+"^&"[+(e[0]<"+")]+(e[2]>"e"))]))
```
It's a bit obfuscated, but I wanted to do something using `eval` and bitwise operators. Annotated:
```
f = (i) => // function(i) { return
    i>"0"  // i[0] == "o" || i[0] == "e" :-) - the characters `*` and `+` are both <"0"
      ? i  // finish
      : f(i.replace( // recursively repeat with
          /.[eo]{2}/, // first occurrence of "something" followed by two values
          (e) =>    // replaced by
              "eo"[ // string indexing
                eval(
                    (e[1]>"e")        // e[1] == "o" ? "true" : "false"
                  + "^&"[+(e[0]<"+")] // e[0] == "+" ? "^" : "&"
                  + (e[2]>"e")        // e[2] == "o" ? "true" : "false"
                )
              ]     // like eval(…) ? "o" : "e"
        ))
```
The repetition of `(e[…]>"e")` annoys me a bit, but the following is not better either (103 bytes):
```
f=i=>i>"0"?i:f(i.replace(/e|o/g,x=>+(x>"e")).replace(/.\d\d/,e=>"eo"[eval(e[1]+"^&"[+(e[0]<"+")]+e[2])]))
```
So in the end, @Arkain's approach with simple substring matching is superiour. Made into a function, with some optimisations:
```
f=i=>i>"0"?i:f(i.replace(/.[eo]{2}/,v=>"eo"[+"+oe+eo*oo".includes(v)]))
```
[Answer]
## Haskell, 98 94 bytes
Sorry to bother you with yet another Haskell attempt; just wanted to prove it is very well possible in less than 100 bytes.
```
p(c:s)|any(<'a')s=p(c:p s)
p('+':x:y:s)|x/=y='o':s
p('*':'o':s)=s
p(c:_:_:s)|c<'a'='e':s
p s=s
```
Defines a function `p` that accepts any valid expression as parameter, and returns the result as a string of length 1.
Example:
```
*Main> p "**o++*ee*++eoe*eo+eoo"
"o"
```
The function works by repeatedly reducing the rightmost operator in the string until no operators are left.
[Answer]
# Dart, 173 bytes
```
f(i){var l=i.split(''),e='e',o='o';g(p){if(l[p]!=e&&l[p]!=o){var x=p+1,y=p+2;g(x);g(y);l[p]=l[p]=='+'?l[x]!=l[y]?o:e:l[x]==o?l[y]:e;l.removeRange(x,p+3);}}g(0);print(l[0]);}
```
This isn't competitive, but whatever. The gist of the solution is, starting at 0, recursively replace every operator with the evaluation the pair of characters following that operator and then remove those characters from the list. 
[Answer]
# Haskell, 231 bytes
Here is an approach using a serious language ;)
Golfed version:
```
p(s:_)[]=s
p s(x:y)=p(r$x:s)y
r[]=[]
r('e':'e':'+':x)=r$'e':x
r('e':'o':'+':x)=r$'o':x
r('o':'e':'+':x)=r$'o':x
r('o':'o':'+':x)=r$'e':x
r('e':'e':'*':x)=r$'e':x
r('e':'o':'*':x)=r$'e':x
r('o':'e':'*':x)=r$'e':x
r('o':'o':'*':x)=r$'o':x
r x=x
```
Example:
```
*Main> p [] "+**+***+**++**+eooeoeeoeeoeooeo"
'o'
```
Ungolfed and pretty comprehensive version:
```
type Stack = String
parse :: String -> Char
parse = parse' []
parse' :: Stack -> String -> Char
parse' (s:_) []     = s
parse' s     (x:xs) = parse' (reduce $ x:s) xs
reduce :: Stack -> Stack
reduce [] = []
reduce ('e':'e':'+':xs) = reduce $ 'e':xs
reduce ('e':'o':'+':xs) = reduce $ 'o':xs
reduce ('o':'e':'+':xs) = reduce $ 'o':xs
reduce ('o':'o':'+':xs) = reduce $ 'e':xs
reduce ('e':'e':'*':xs) = reduce $ 'e':xs
reduce ('e':'o':'*':xs) = reduce $ 'e':xs
reduce ('o':'e':'*':xs) = reduce $ 'e':xs
reduce ('o':'o':'*':xs) = reduce $ 'o':xs
reduce xs               = xs
```
Example:
```
*Main> parse "+**+***+**++**+eooeoeeoeeoeooeo"
'o'
```
Features: Pattern matching and recursion.
[Answer]
# Python 3, ~~171~~ ~~145~~ 135 bytes
Not competitive, but I had fun doing it, so I just couldn't keep it to myself. Unlike the (very clever) [recursive-iterator Python entry by feersum](https://codegolf.stackexchange.com/a/65532/13959), this one reverses the input and then does a good old stack-based parsing of reverse Polish notation.
```
def p(i):
 s=[]
 for c in i[::-1]:
  s+=[c>'e'if c>'a'else getattr(s.pop(),'__'+('axnodr'[c>'*'::2])+'__')(s.pop())]
 return'eo'[s[0]]
```
[Answer]
# [Add++](https://github.com/cairdcoinheringaahing/AddPlusPlus), 46 bytes
```
D,g,@,d"oe"$eA"e"=+o
D,f,@,bR€gbU32CjbV2%"eo":
```
[Try it online!](https://tio.run/##ZZNLjtNAEIbX9CmilpGg2iMlw87SeIJmYIuEBBs0giSuREHBZWFHsOYwrDgFR@Eiobrb3X@PRvGjUvX7c7286bphuFzu60O9rjsrbCt@bdneODH39V6d2/f/fv05bD@8ur77uv14/dyy2EYf2Mm5n3r@cTr2PKputbxT4c3f304fHIfTcarX67paqL@aFnZx1S6sCqZFpddGNQeejhN/86rV56oxJsGapZl4nKJ9G@yx@fRgvvN4PkVz5KGxV6013HeNffHm58C7idU0@2Pf2JfWmC8JZ6pHqbaZrZrANlVIF4F2qaH5bU@DK2Pe5rrNs8DQezXXE5Rje/QhnvMqwzM3Cja76bw5qdXNlE4r8@p9mxyQaK16kwL6TqutLxf2zWUj/ibG8fzfcfIIJ0NiiJKGOHkkeSRzChJYDBpnnmOCNjPVFHgzV2ZuNJNWXNaKg5agJdRDqIhQk0NVmUucucRF/UUH0APkSwyugCu5DyS5DyTgCrhS9LboLvqg2FSxmvDm2tRM3dGXZa8wvLlnaiYCgUvgEgu80Aq0Aq3kHEhybciXUr7BFHgTl5xAm7mEfMmBi3yJwEW@RAwtuCTQgktS7m@5wxJ/KReOv2Iu5WzYr2a5keyK2bMfbjlTLqbtP4DyexC/H4T3xjg2SqjYdyLnKIxNj2I20R06oaFwQYjC6fwZQ/EQDDQm/GgFYkWh4@id86@msIMqzvP8Dw "Add++ – Try It Online")
The footer simply enumerates all the example inputs and their corresponding outputs.
## How it works
Like a lost of the answers here, this uses replacement and evaluation. Our main function is `f`, and `g` is a helper function. We'll use `"*e*o*e*oe"` (which is `e`) as an example.
`f` begins by taking the input string and reversing it, yielding `"eo*e*o*e*"`. We then map `g` over each element:
`g` starts by duplicating the argument, to keep a copy until the final command. We then check if the argument is in the string `"oe"`, yielding **1** for letters and **0** for `*` or `+`. We then push the argument again and check whether it is equal to `"e"`. This result is then added to the previous check. This yields **0** for either `*` or `+`, **1** for `o` and **2** for `e`. We then take the logical OR between this value and the argument. If the value is **0**, it is replaced by the argument (i.e. `*` or `+`), otherwise it is left as-is (i.e. **1** and **2**).
This converts all letters in the reverse of the input into a numerical value. We then join each element by spaces, to ensure digits aren't concatenated. For our example, this yields the string `"2 1 * 2 * 1 * 2 *"`. We can then evaluate this, using Add++'s postfix notation, yielding **8**. We then take the parity of this value, yielding either **0** for even numbers and **1** for odd numbers, before indexing into the string `"eo"` and returning the corresponding letter.
[Answer]
# [Lexurgy](https://www.lexurgy.com/sc), 65 bytes
```
a propagate:
\+ {ee,oo}=>e
\+ {eo,oe}=>o
\* {eo,ee,oe}=>e
\*oo=>o
```
Explanation:
```
a propagate:     # while last output was not the same...
\+ {ee,oo}=>e    # handle even addition
\+ {eo,oe}=>o    # handle odd addition
\* {eo,ee,oe}=>e # handle even multiplication
\*oo=>o          # handle odd multiplication
```
As a bonus, if you copy-paste the test cases verbatim into Lexurgy, it will not touch the expected output side of the arrow.
[Answer]
# [05AB1E](https://github.com/Adriandmen/05AB1E/wiki/Commands), 14 [bytes](https://github.com/Adriandmen/05AB1E/wiki/Codepage)
```
„eoDIRs„¾X‡.Vè
```
[Try it online](https://tio.run/##yy9OTMpM/f//UcO81HwXz6BiIOPQvohHDQv1wg6v@P9fW0sLiEBYG4RT8/NT81MhCMQEAA) or [verify all test cases](https://tio.run/##RZK9TQRBDIVbOW345kQLl1ABAUJCBCBNQPSCk5Auu4gCKACJjCoIoJNrZJm1P89p/2b89unz2Pbx@eW1r2@nw7K7vH/slsN6OX92357ujmPx@/NwOX/d3P99r/v1cenLfvF4Wu/xjrVj7W2tiCviiric/5cDT8fVG7rQhS50/MbvYhYVv/Ebv/Fb5NXILP2Cr155V@bkDl/wBV/wBV/wBV@us9fpyX/YO1/2Zo9udKMb3akLv/ALv/ALv/ALv9Iv@IIv@IIv@IIv@IIv@IIv@IIv@IIv@IK/9X3OgPOqus/aO6@ajzkjzl31ZfbGuav5mTPkrSvXvs/eO5Wsj1pTVHPcVbuMxZlGPF7EFU/bnoznbc9pHblce5IJR7GoQttYiraP36LqT/8).
**Explanation:**
```
„eo            # Push string "eo"
   D           # Duplicate it
    IR         # Push the input, and reverse it
               # (since 05AB1E evaluates in Reverse Polish Notation)
      s        # Swap so one of the "eo" is at the top
       „¾X     # Push string "¾X"
               # (`¾` is 0 by default and `X` is 1 by default. We use these instead of
               # literals, because it could otherwise push 10, 100, "001", etc. instead
               # of loose digits)
          ‡    # Transliterate "e"→"¾" and "o"→"X"
           .V  # Pop, evaluate, and execute the string as 05AB1E code
             è # Index the resulting 0/1 into the "eo" string
               # (after which the result is output implicitly)
```
[Answer]
# [Thue](https://esolangs.org/wiki/Thue), 95 bytes
```
*ee::=e
*eo::=e
*oe::=e
*oo::=o
+ee::=e
+eo::=o
+oe::=o
+oo::=e
>e::=~e
>o::=~o
i::=:::
::=
>i
```
[Try it online!](https://tio.run/##LY2xDcAwCAT7HwU2QIq3QYqrb5LWqztPTHU6PeKe@829LTPiSljykO0sJ7x3z/Z/L577UbrE0kVMISIgYEwoYHRXxVwvUhmB@AA "Thue – Try It Online")
[Answer]
# [Python 3](https://docs.python.org/3/), 99 bytes
```
import re
a=b=input()
for i in a:a,b=re.subn(b and"\+(eo|oe)|\*oo"or"\W\w\w","oe"[b==0],a)
print(a)
```
[Try it online!](https://tio.run/##VVPLbtwwEDvHX2HoZFObIEVuAZzf6KHuwU6miIHEXLi72BbIv29kKRIV@IEBRVAUZ3T8f3rl@nC9vC5v1v54bG7snz13m3PuurwfuZ3azZppmIdlPZ5PXd/84dYu7bK20@N0mIfN7v6e57Wb22l9caPvjB@0/mME6bi58ed4GS/u4Gju1zwM978PU98ct2U9dVN/Dfv0V0@2t0@tNTDLRUaYkcRh03jzmbaXX3AoEzWVzASIW0RDSaES5pcwY5nJ9IVMn8meEBcmlEKziXAar4MVYVgRhlURVCEoBjmGVcKUMEsUYIkClDAlzCrfKuEqiqCbDx3KfLywhanMAYXdCkoTWmILZRGGhCFhGIWWjEFxKS6LCVBRyDGy41hSaBaGp7hFGHIMXwnLMSBhOQZKFJBjgOJKGPw2x/UsMz3ZjaWnak7VoH3EvdWDab4aANs7XDfWqpbvF6G@F9yHBNo3rWusCLkKkcN7xNaFt@pPgmMWYSn@tIT4@f1LS@llyT7ew@Dy2xykM8XQFZ/f90acxEAuPf0E "Python 3 – Try It Online")
Nice solution using regex. (python has already better solutions, go upote those)
[Answer]
# [MathGolf](https://github.com/maxbergmark/mathgolf/blob/master/math_golf.txt), 23 [bytes](https://github.com/maxbergmark/mathgolf/blob/master/code_page.py)
```
x$╟⌠%_Z)m=9*m+$y~♂*♀)+$
```
Input as a list of characters to save a byte.
[Try it online.](https://tio.run/##y00syUjPz0n7/79C5dHU@Y96FqjGR2nm2lpq5WqrVNY9mtmk9Whmg6a2yv//0UraSjpKWlCsDcVaSHQqFOejsRH8WC7CpmghmYasOx@nGDZTtXDwtbHwcdmEi42qFmZ7KtTEfCT3o/sF1a2pSPZrQ1VoY9GJqlsLyR5tLKGP7EtkVyO7A9XXsQA)
**Explanation:**
```
x                 # Reverse the (implicit) input-list
 $                # Convert each character to its codepoint-integer
  ╟⌠              # Push 62 (60+2)
    %             # Modulo
     _            # Duplicate the list
      Z)          # Push 39 (38+1)
        m=        # Check for each value if it's equal to 39 (1 if 39; 0 otherwise)
          9*      # Multiply each by 9
            m+    # Add the values in the lists together
              $   # Convert it from codepoint-integers back to characters
               y  # Join it together to a string
                ~ # Evaluate and execute it as MathGolf code
♂*                # Multiply each by 10
  ♀)              # Push 101 (100+1)
    +             # Add it to the integer
     $            # Convert it as code-point integer to character ('e' or 'o')
                  # (after which the entire stack is output implicitly)
```
Unfortunately MathGolf lacks a replace/transliterate builtin, otherwise this could be as easy as `xûoe2à`<transliterate>`~♂*♀)+$` (14 [bytes](https://github.com/maxbergmark/mathgolf/blob/master/code_page.py)).
]