Cóż, to dziwne… nie czekaj, to nawet!

70

Preambuła

Liczby całkowite są zawsze parzyste lub nieparzyste . Nawet liczby całkowite są podzielne przez dwa, nieparzyste liczby całkowite nie są.

Po dodaniu dwóch liczb całkowitych możesz wywnioskować, czy wynik będzie parzysty czy nieparzysty na podstawie tego, czy sumy były parzyste czy nieparzyste:

  • Parzysty + Parzysty = Parzysty
  • Parzysty + Nieparzysty = Nieparzysty
  • Nieparzysty + Parzysty = Nieparzysty
  • Nieparzysty + Nieparzysty = Parzysty

Podobnie, mnożąc dwie liczby całkowite, możesz wywnioskować, czy wynik będzie parzysty czy nieparzysty na podstawie tego, czy czynniki były parzyste czy nieparzyste:

  • Parzysty * Parzysty = Parzysty
  • Parzysty * Nieparzysty = Parzysty
  • Nieparzysty * Parzysty = Parzysty
  • Nieparzysty * Nieparzysty = Nieparzysty

Zatem jeśli znasz równość lub nieparzystość wszystkich zmiennych w wyrażeniu matematycznym, które obejmuje tylko dodawanie i mnożenie, możesz wywnioskować, czy wynik będzie parzysty czy nieparzysty.

Na przykład możemy śmiało powiedzieć, że (68 + 99) * 37wynikiem jest nieparzysty, ponieważ parzysty plus nieparzysty ( 68 + 99) jest nieparzysty, a ten razy nieparzysty inny nieparzysty ( odd * 37) daje nieparzysty.

Wyzwanie

Napisz program lub funkcję, która pobiera ciąg zawierający tylko cztery znaki eo+*. Ten ciąg reprezentuje wyrażenie matematyczne podane w notacji przedrostkowej obejmującej tylko dodawanie ( +) i mnożenie ( *). Każda ereprezentuje dowolną liczbę parzystą, a każda oreprezentuje dowolną liczbę nieparzystą.

Twoim zadaniem jest uproszczenie wyrażenia, drukowanie lub powrotu pojedynczy elub ona podstawie tego, czy wynikiem wyrażenia jest parzyste, czy nieparzyste.

Możesz założyć, że dane wejściowe zawsze będą miały poprawną notację przedrostkową. W szczególności, każdy +i *zawsze będzie miał dwa odpowiadające operandy występujące po nim. Te argumenty mogą być pojedyncze elub olub inny +albo *wyrażenie, które z kolei ma argumentów.

Na przykład dane wejściowe *+eoomożna odczytać jako mul(add(e, o), o)lub (e + o) * ow normalnej notacji infiksowej . Pierwszy ei pierwszy oto operandy odpowiadające +, a +eoostatni oto operandy odpowiadające *.

Aby to wyjaśnić, oto niektóre niepoprawne dane wejściowe, które mają niepoprawny zapis prefiksu:

eo
ooe
o+e
ee*
+*oe
+e*o

Pojedynczy znak nowej linii na wyjściu jest w porządku, ale poza tym wszystko, co powinno być wyprowadzone , to zwykły eparzysty lub onieparzysty.

Najkrótszy kod w bajtach wygrywa.

Przypadki testowe

(Puste wiersze służą jedynie do wizualnego oddzielenia podobnych przypadków.)

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
Hobby Calvina
źródło
8
Czy możemy przyjąć 1 i 0 zamiast e i o jako dane wejściowe?
ghosts_in_the_code
8
@ghosts_in_the_code Nie, przepraszam.
Calvin's Hobbies
2
Jest używane eval OK?
xnor
1
@xnor Sure. Cokolwiek działa.
Calvin's Hobbies
2
Wątpię, czy mogę użyć tego, aby pobić 13 bajtów już opublikowanych, ale zauważam, że dodanie pasuje do wyłączności lub, a mnożenie jest proste lub.
WGroleau

Odpowiedzi:

43

CJam, 18 17 13 bajtów

Dzięki aditsu za oszczędność 4 bajtów.

qW:O%eu~"eo"=

Wypróbuj pakiet testowy tutaj. (Pakiet testowy jest za długi na permalink. Po prostu skopiuj go ze specyfikacji wyzwania).

Wyjaśnienie

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.
Martin Ender
źródło
27

Pyth 16 14 bajtów

@"eo".vjdXzGU9

Pyth może sam ocenić ciąg znaków, który jest w składni Pyth. Dlatego wymieniame i oz 4a 5. Następnie ocena da mi parzystą lub nieparzystą liczbę i mogę łatwo wydrukować wynik.

Wypróbuj online: pakiet demonstracyjny lub testowy

Wyjaśnienie:

@"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"

Dodatkowe objaśnienie do zamiany. Gjest zmienną zainicjowaną alfabetem abc...xyz. U9jest lista [0, 1, ..., 8]. XzGU9zastępuje litery alfabetu wartościami listy. Więc azostaje zastąpiony przez 0, bz 1, ..., ez 4, ..., iz 8, jz 0, ... i oz 5. Dlatego zostałem ezastąpiony liczbą parzystą i oliczbą nieparzystą. Wszystkie pozostałe zamienniki nie mają żadnego efektu.

Jakube
źródło
Dlaczego odwracasz wyrażenie? Ponadto, czy nie trzeba brać wyniku modulo 2, czy indeksowanie jest teraz zawijane?
xnor
@xnor uzyskując dostęp do elementu w łańcuchu odbywa się zawijanie modulo. Więc nie ma potrzeby modulo 2.
Jakube
@xnor Ale dzięki za odwrotną rzecz. Oczywiście nie jest to konieczne. (Jestem dzisiaj trochę zmęczony.)
Jakube,
16

Perl, 50 45 40 znaków

(Kod 39 znaków + opcja wiersza poleceń 1 znak.)

1while s/\+oe|\+eo|\*oo/o/||s/\W\w\w/e/

Przykładowy przebieg:

bash-4.3$ echo -n '**o++*ee*++eoe*eo+eoo' | perl -pe '1while s/\+oe|\+eo|\*oo/o/||s/\W\w\w/e/'
o
człowiek w pracy
źródło
Jak o while/../?
primo
Doh Głupi Właściwie użyłem tego warunku podczas wypróbowania jego sedwersji… Dziękuję, @primo.
manatwork
Albo jeszcze lepiej 1while s/\+oe.... Jestem również pewien, że [+*]można go zastąpić \W.
primo
Jeszcze raz dziękuję, @primo. Myślę, że powinienem raz skoncentrować się na jednym rozwiązaniu. ( gemadoprowadza mnie do szaleństwa…)
manatwork
To samo podejście z Sedem teraz o 2 bajty krótsze!
Cyfrowy uraz
13

Siatkówka , 29 bajtów

(+`\*oo|\+(eo|oe)
o
\W\w\w
e

Dla wygodnej wersji jednego pliku -sużywana jest flaga.

Możemy zamienić wyrazy nieparzyste ( *oo, +oe, +eo) doo momentu możemy, a następnie zamienić pozostałych wyrażeń symbol-letter list do e. Powtarzamy to, dopóki nie możemy, a ostatnia litera jest naszym wynikiem.

(To rozwiązanie jest podobne do odpowiedzi Perla dla manatwork .)

Wypróbuj online! (autor: Dennis)

randomra
źródło
12

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)]

Ta iterfunkcja jest dobrym sposobem przekształcenia łańcucha wejściowego w kolejkę FIFO, która zapamiętuje, ile łańcucha zostało przeanalizowane przez wywołania f. Jest idempotentny, więc wywoływanie go, gdy wejście jest już iteratorem, a nie ciągiem, jest niegroźne. Końcowa połowa odpowiedzi zaczynająca się od or'oe'... wydaje się, że powinna być możliwa do gry w golfa, ale nic nie mogłem znaleźć.

-1 dzięki Sp3000.

feersum
źródło
Świetne rozwiązanie! Używanie funkcji rekurencyjnych iternaprawdę oszałamia mój umysł.
xnor
3
Oto sposób na bezpośrednie obliczenie arytmetyki za pomocą eval:def f(s,e=0,o=1):i=iter(s);a=next(i);return'eo'[eval(a*(a>'a')or f(i)+a+f(i))%2]
xnor
1
@ xnor Równie dobrze możesz opublikować to jako odpowiedź. To znacznie różni się od tego rozwiązania.
feersum
9

Mathematica, 91 84 bajtów

#//.s_:>s~StringReplace~{"+ee"|"+oo"|"*ee"|"*eo"|"*oe"->"e","+eo"|"+oe"|"*oo"->"o"}&

Szukasz sposobu na skompresowanie tego ...

LegionMammal978
źródło
3
//.jest krótszy niż FixedPoint.
alephalpha
8

Python 2, 80 bajtów

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]

Jest to oparte na bardzo sprytnej odpowiedzi Feersum, która wykorzystuje iterdo implementacji operacji notacji polskiej. Nowym pomysłem jest użycie evaldo oceny wyrażeń +i za *pomocą eval(f(i)+a+f(i)), w których operator ajest umieszczony na stałe między wynikami rekurencyjnymi. Eval używa powiązań e=0,o=1w opcjonalnych argumentach funkcji. Wyjście jest następnie pobierane mod 2.

xnor
źródło
Działa to również w Pythonie 3. Przy okazji, jak eval potrzebuje powiązań „e = 0, o = 1”?
karhell
@karhell Ocenia wyrażenia podobne e+o, więc potrzebuje zmiennych, aby odwoływały się do liczb.
xnor
8

C, 79 bajtów

Prosta rekurencja. Opiera się na niektórych (przypadkowych?) Właściwościach bitowych czterech dozwolonych znaków wejściowych.

f(){int c=getchar();return c&4?c:c&1?f()^f()^'e':f()&f();}main(){putchar(f());}
Ruud Helderman
źródło
8

Narzędzia Shell + GNU, 33

dc -eFo`rev|tr oe OK`2%p|tr 10 oe

Dane pobierane są z STDIN.

Robi to samo, odwracając dane wejściowe i oceniając je za pomocą kalkulatora opartego na stosie - w tym przypadku dc. Możemy zamienić ei za opomocą 0i 1, ale wówczas trzeba będzie wstawić spacje, aby zapobiec zachłannemu przetwarzaniu cyfr na niepoprawne liczby.

Zamiast tego ejest zastąpiony Kktóry jest dcpolecenie, aby przesunąć bieżącą dokładność na stosie, który domyślnie jest 0. I ootrzymuje z Októrego jest dckomenda do pchania aktualną bazę wyjściową do komina. To musi być nieparzyste, więc ustawiliśmy go na 15, Fozanim zrobimy cokolwiek innego w DC.

Zatem wystarczy po prostu wziąć mod 2 i wydrukować 2%p. Jedyne możliwe wartości to teraz 0i 1tak nie ma znaczenia, że baza wyjściowa jest 15. Następnie trprzekłada powrotem do olub e.


Podoba mi się, jeśli zmrużysz oczy, to źródło prawie wygląda dc Forever OK.

Cyfrowa trauma
źródło
5

Poważnie , 24 bajty

,R'2'e(Æ'1'o(Æ£ƒ'e'o2(%I

Bardziej wydajne manipulowanie stosami może prawdopodobnie uczynić to krótszym, ale jestem zadowolony.

Pobiera dane wejściowe jako ciąg znaków, np "+*oee"

Wypróbuj online (dane należy wprowadzić ręcznie)

Wyjaśnienie:

,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"
Mego
źródło
5

Rubin, 61 bajtów

Korzystanie z parsowania rekurencyjnego i algebry boolowskiej.

def f
gets(1)==?+?f^f : ~/\*/?f&f : $_==?o
end
puts f ? ?o:?e

Funkcja odczytuje po jednym znaku ze standardowego wejścia. Jeśli czyta a +lub a *, wywołuje się dwukrotnie, aby określić nieparzyste lub parzyste. Funkcja zwraca truedla nieparzystych i falsedla even. Operatory ^ XOR i & AND służą do określenia „nieparzystości” odpowiednio wyrażeń dodawania i mnożenia.

Oto wersja bez golfa:

def f
  x = gets(1)
  case x
  when '+'
    f ^ f
  when '*'
    f & f
  else
    x == 'o'
  end
end

puts f ? 'o' : 'e'

Dzięki @Shel za wskazanie błędu w początkowej wersji.

daniero
źródło
1
To nie działa, +eedaje o. Podoba mi się ten pomysł
Shelvacu,
wymienić f^fze !f^fi f&fze f|fi to działa. Program do uruchamiania przypadków testowych: pastebin.com/ufXfd1vc
Shelvacu
1
Dzięki, dobry chwyt! Wygląda na to, że się trochę tam pomyliłem. Niezły zestaw testów! Testowane jest droga, również podczas gry w golfa :)
daniero
@Shel Aha ..! Zmieniłem się f^fi f&fodwróciłem $_==?ei ?e:?ozamiast tego :)
daniero
1
Wow, ucz się czegoś nowego każdego dnia ... ruby-doc.org/core/Regexp.html#method-i-7E
Shelvacu
4

Minkolang 0,14 , 40 bajtów

Próbowałem wykonać sprytną metodę eval, ale okazuje się, że żadne wartości dodane do codbox poza pierwotną przestrzenią nigdy nie zostaną osiągnięte przez licznik programu. Więc zrobiłem mniej sprytną metodę ewaluacji. : P

$o"eo+*"r0I4-[4g1Z2*1F]l*"e"+O.
0f1f+f*f

Wypróbuj tutaj.

Wyjaśnienie

$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
El'endia Starman
źródło
1
Łał! good ol 'shell bije w (pół) golfowy język ;-P
Digital Trauma
4

JavaScript, 110 106 94 bajty

while(i.length>2)i=i.replace(/([+*][eo]{2})/,(o,e)=>{return"+oe+eo*oo".indexOf(o)<0?"e":"o"});

Z pewnością nie jest to najmniejsze rozwiązanie, ale prawdopodobnie najmniejsze możliwe rozwiązanie w pełnym języku, takim jak JavaScript!

Arkain
źródło
Używanie grup nie przechwytujących jest dobre dla wydajności, ale złe dla rozmiaru kodu. Lepiej je usuń ?:.
manatwork
zgodził się ... i tak zmodyfikowany.
Arkain,
Przyjrzał się teraz jeszcze raz. Twój kod można jeszcze bardziej zmniejszyć while(i.length>2)i=i.replace(/[+*][eo]{2}/,function(o){return"+oe+eo*oo".indexOf(o)>=0?"o":"e"}). Lub jeśli zmienisz funkcję grubej strzałki ECMAScript 6, to while(i.length>2)i=i.replace(/[+*][eo]{2}/,o=>"+oe+eo*oo".indexOf(o)>=0?"o":"e"). Ale niestety wymaganie mówi o programie lub funkcji, podczas gdy bieżący kod jest fragmentem kodu. Powinien obsługiwać dane wejściowe i wyjściowe lub argumenty i zwracane wartości.
manatwork
1
Niestety, aby być poprawnym na tej stronie, nie możemy założyć, że zmienna już istnieje. Będziesz musiał uczynić to funkcją, ijak powiedziałeś.
Alex A.,
1
@Arkain, nie musisz przechwytywać grupy w wyrażeniu regularnym, ponieważ i tak użyjesz całego dopasowanego podłańcucha jako jednego elementu. Z tego samego powodu nie ma potrzeby przekazywania parametru e do wywołania zwrotnego.
manatwork
4

O , 24 20 19 18 bajtów

i`2:e;1:o;~2%'o'e?

Zajmuje wejście, odwraca go, przypisuje edo 2 i odo 1 i stanowisk go do Tumblr ocenia go jako kod wyjścia.

Wyjaśnienie:

i` Uzyskaj dane wejściowe i odwróć je, ponieważ O używa notacji postfiksowej
2: e; Przypisz „e” do 2
1: o; Przypisz „o” do 1
~ 2% Eval i sprawdź, czy wynik jest parzysty
? Wyjście „e”, jeśli parzyste, „o”, jeśli nieparzyste
faza
źródło
4

GNU Sed, 36

:
s/*oo\|+eo\|+oe/o/
t
s/\W\w\w/e/
t

Po wysłaniu Widziałem to dokładnie takie samo podejście jak na Perl odpowiedź @ manatwork i @ randomra za Retina odpowiedź . Sądzę więc, że równie dobrze mogę pójść na całość i pożyczyć ich \W\w\w.

Dzięki @Ruud za golenie 4 bajtów.

Cyfrowa trauma
źródło
Po zniknięciu nawiasów opłaca się zrezygnować z rozszerzonego wyrażenia regularnego. Wygrywasz 2 bajty za brak ucieczki +, tracisz 2 bajty za ucieczkę |, ale końcowym rezultatem jest to, że wygrywasz 1 bajt za opcję upuszczenia -r.
Ruud Helderman,
@Ruud Zgadza się. Próbowałem już wcześniej, ale nie zdawałem sobie sprawy z |potrzeby ucieczki, gdy -rnie jest używany. Jeszcze 2 bajty więcej niż wynik - dzięki!
Cyfrowy uraz
2

Haskell, 160 bajtów

Zadzwoń 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"]
Leif Willerts
źródło
2

JavaScript, 92 71 bajtów

f=i=>i>"0"?i:f(i.replace(/.[eo]{2}/,e=>"eo"[eval((e[1]>"e")+"^&"[+(e[0]<"+")]+(e[2]>"e"))]))

Jest to trochę zaciemnione, ale chciałem zrobić coś przy użyciu evaloperatorów bitowych. Adnotacja:

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"
        ))

Powtarzanie (e[…]>"e")mnie trochę denerwuje, ale nie jest to również lepsze (103 bajty):

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])]))

W końcu podejście @ Arkain z prostym dopasowywaniem podciągów jest super. Utworzono funkcję z pewnymi optymalizacjami:

f=i=>i>"0"?i:f(i.replace(/.[eo]{2}/,v=>"eo"[+"+oe+eo*oo".includes(v)]))
Bergi
źródło
1

Dart, 173 bajtów

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]);}

To nie jest konkurencyjne, ale cokolwiek. Istotą rozwiązania jest, począwszy od 0, rekurencyjne zastępowanie każdego operatora oceną pary znaków następujących po tym operatorze, a następnie usuwanie tych znaków z listy.

Nacięcie
źródło
1

Haskell, 231 bajtów

Oto podejście przy użyciu poważnego języka;)

Wersja golfowa:

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

Przykład:

*Main> p [] "+**+***+**++**+eooeoeeoeeoeooeo"
'o'

Niegolfowana i dość kompleksowa wersja:

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

Przykład:

*Main> parse "+**+***+**++**+eooeoeeoeeoeooeo"
'o'

Funkcje: Dopasowywanie wzorców i rekurencja.

użytkownik3389669
źródło
1

Jolf, 11 bajtów

(Niekonkurencyjne, ponieważ język postdatuje pytanie.) Wypróbuj tutaj!

FVyAi"oe"@\x12

(Zamień \x12na rzeczywisty znak \x12. Powinno to nastąpić automatycznie w tłumaczu.)

Wyjaśnienie:

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
Conor O'Brien
źródło
1

Python 3, 171 145 135 bajtów

Nie jestem konkurencyjny, ale dobrze się bawiłem, więc nie mogłem tego zatrzymać dla siebie. W przeciwieństwie do (bardzo sprytnego) wpisu Pythona w iteratorze rekurencyjnym z iteratorem feersum , ten odwraca dane wejściowe, a następnie wykonuje starą, opartą na stosie analizę składni odwrotnej polskiej notacji.

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]]
Tim Pederick
źródło
To callable()jest eleganckie, ale długie. (Odwrócenie warunku i usunięcie notbyłoby krótsze.) Zamiast tego sprawdź, czy m jest liczbą całkowitą, m in[0,1]byłoby krótsze, ale sprawdzenie, czy c jest wartością, c in'eo'byłoby jeszcze krótsze. To później jest takie samo jak c>'a'w tym przypadku.
manatwork,
W rzeczywistości zmienna m i jej wartości liczbowe nie są potrzebne. Wstaw tylko to do for:s+=[c>'e'if c>'a'else{'*':o.and_,'+':o.xor}[c](s.pop(),s.pop())]
manatwork
@manatwork: Dzięki! Nie sądziłem, że mógłbym odwrócić ten warunek, ponieważ myślałem , że oznaczałoby to wywołanie s.pop()(dwa razy) każdej pętli. Do tej pory nie zawracałem sobie głowy testowaniem; ale hej, punkt jest teraz dyskusyjny.
Tim Pederick,
Jedno pytanie niepokoiło mnie od samego początku: po co korzystać z operator modułu? bool.__and__()i bool.__xor__()są bardziej poręczne: s+=[c>'e'if c>'a'else getattr(s.pop(),{'*':'__and__','+':'__xor__'}[c])(s.pop())]. Ale na podstawie gnibbler „s końcówki krojenie , które mogą być zamienione na s+=[c>'e'if c>'a'else getattr(s.pop(),'__'+('axnodr'[c>'*'::2])+'__')(s.pop())].
manatwork
@manatwork: Bo o tym nie myślałem. Rozważałem tylko operatory infix ( ^, &) i ich operatorodpowiedniki, zapominając o metodach, które faktycznie je implementują. Aha, a reversed()teraz został odrzucony dzięki kolejnej wskazówce golfowej Python .
Tim Pederick,
1

Haskell, 98 94 bajtów

Przepraszam, że przeszkadzam w kolejnej próbie Haskella; chciałem tylko udowodnić, że jest to bardzo możliwe w mniej niż 100 bajtach.

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

Definiuje funkcję, pktóra przyjmuje dowolne prawidłowe wyrażenie jako parametr i zwraca wynik jako ciąg długości 1.

Przykład:

*Main> p "**o++*ee*++eoe*eo+eoo"
"o"

Funkcja działa poprzez wielokrotne zmniejszanie najbardziej wysuniętego w prawo operatora w ciągu, aż nie pozostaną żadne operatory.

Ruud Helderman
źródło
0

Dodaj ++ , 46 bajtów

D,g,@,d"oe"$eA"e"=+o
D,f,@,bR€gbU32CjbV2%"eo":

Wypróbuj online!

Stopka po prostu wylicza wszystkie przykładowe dane wejściowe i odpowiadające im dane wyjściowe.

Jak to działa

Podobnie jak w przypadku utraty odpowiedzi tutaj, wykorzystuje to wymianę i ocenę. Naszym głównym zadaniem jest f, a gjest funkcją pomocnika. Użyjemy "*e*o*e*oe"(który jest e) jako przykład.

fzaczyna się od pobrania ciągu wejściowego i odwrócenia go, ustępując "eo*e*o*e*". Następnie mapujemyg każdy element:

gzaczyna się od zduplikowania argumentu, aby zachować kopię do ostatniego polecenia. Następnie sprawdzamy, czy argument znajduje się w ciągu "oe", dając 1 dla liter i 0 dla *lub +. Następnie ponownie wypychamy argument i sprawdzamy, czy jest on równy "e". Ten wynik jest następnie dodawany do poprzedniej kontroli. Daje to 0 do albo *lub +, 1 do oi 2 o e. Następnie bierzemy logiczne OR między tą wartością a argumentem. Jeśli wartość wynosi 0 , jest ona zastępowana argumentem (tj. *Lub +), w przeciwnym razie pozostawia się ją taką, jaka jest (tj. 1 i 2 ).

Konwertuje wszystkie litery na odwrocie wejścia na wartość liczbową. Następnie łączymy każdy element spacjami, aby cyfry nie były konkatenowane. W naszym przykładzie daje to ciąg znaków "2 1 * 2 * 1 * 2 *". Możemy to następnie ocenić za pomocą notacji Postfiksa Add ++, uzyskując 8 . Następnie bierzemy parzystość tej wartości, dając 0 dla liczb parzystych i 1 dla liczb nieparzystych, po czym indeksujemy do łańcucha "eo"i zwracamy odpowiednią literę.

Cairney Coheringaahing
źródło