Historyczna różnica między `/` a `÷` w wyrażeniach matematycznych


33

Wprowadzenie:

wprowadź opis zdjęcia tutaj

Zainspirowany trwającą od wielu lat dyskusją na temat wyrażenia 6÷2(1+2) .

Dzięki wyrażeniu 6÷2(1+2) matematycy szybko przekonają się, że poprawna odpowiedź to 1 , a osoby o prostym pochodzeniu matematycznym ze szkoły szybko przekonają się, że poprawna odpowiedź to 9 . Skąd więc ta kontrowersja, a zatem różne odpowiedzi? Istnieją dwie sprzeczne reguły w sposobie pisania 6÷2(1+2) . Jeden ze względu na część 2(, a drugi ze względu na symbol podziału ÷.

Chociaż zarówno matematycy, jak i „zwykli ludzie” będą używać PEMDAS (nawias - wykładniki - dzielenie / mnożenie - dodawanie / odejmowanie), dla matematyków wyrażenie jest oceniane w ten sposób poniżej, ponieważ 2(3) jest jak na przykład 2x2 monomial aka „ pojedynczy termin wynikający z domniemanego mnożenia przez zestawienie ” (a zatem część Pin PEMDAS), który zostanie oceniony inaczej niż 2×(3) (dwumianowy aka dwa terminy):

6÷2(1+2)62(3)661

Podczas gdy dla „zwykłych ludzi” 2(3) i 2×(3) będą takie same (a zatem część MDin PEMDAS), więc użyją tego zamiast tego:

6÷2(1+2)6/2×(1+2)6/2×33×39

Jednak nawet gdybyśmy zapisali pierwotne wyrażenie jako 6÷2×(1+2) , nadal mogą istnieć pewne kontrowersje związane z użyciem symbolu podziału ÷. We współczesnej matematyce symbole /i ÷mają dokładnie to samo znaczenie: dziel. Niektóre reguły sprzed 1918 dotyczące symbolu podziału ÷†† mówią, że miał on inne znaczenie niż symbol podziału /. Dzieje się tak, ponieważ ÷oznacza „ dziel liczbę / wyrażenie po lewej stronie przez liczbę / wyrażenie po prawej stronie††† . Zatem za÷b byłoby(za)/(b) lubzab teraz. W takim przypadku6÷2)×(1+2))byłyby oceniane w ten sposób przez osoby przed 1918 r .:

6÷2×(1+2)62×(1+2)62×3661

†: Chociaż znalazłem wiele źródeł wyjaśniających, w jaki sposób ÷był używany w przeszłości (patrz ††† poniżej), nie byłem w stanie znaleźć ostatecznego dowodu, że zmieniło się to gdzieś około 1918 roku. Ale dla tego wyzwania zakładamy, że 1918 był punkt zwrotny, w którym ÷i /zaczynają oznaczać to samo, gdzie różniły się w przeszłości.

††: Inne symbole były również używane w przeszłości do podziału, jak :w 1633 r. (Lub teraz nadal w Holandii i innych europejskich krajach nieanglojęzycznych, ponieważ tego właśnie nauczyłem się w szkole podstawowej xD) lub )w lata 40. Ale w przypadku tego wyzwania skupiamy się wyłącznie na znaczeniu symbolu obelusa sprzed 1918 r ÷.
†††: Źródła: ogólnie ten artykuł . A zasady dotyczące sprzed 1918 r. ÷Są wymienione w: tym artykule z amerykańskiego miesięcznika matematycznego z lutego 1917 r . ; niemiecka książka Teutsche Algebra z 1659 strona 9 i strona 76 ; ta pierwsza książka w algebrzeod 1895 strona 46 [48/189] .

Nieco tematyczny: dotyczący faktycznej dyskusji na temat tego wyrażenia: nigdy nie należy go tak pisać! Prawidłowa odpowiedź nie ma znaczenia, jeśli pytanie jest niejasne. * Klika przycisk „Zamknij, ponieważ nie jest jasne, o co pytasz” * .
I dla przypomnienia, nawet różne wersje kalkulatorów Casio nie wiedzą, jak poprawnie radzić sobie z tym wyrażeniem:
wprowadź opis zdjęcia tutaj

Wyzwanie:

Otrzymujesz dwa dane wejściowe:

  • (Prawidłowe) wyrażenie matematyczne składające się tylko z symboli 0123456789+-×/÷()
  • Rok

I wyprowadzasz wynik wyrażenia matematycznego na podstawie roku (gdzie ÷jest używany inaczej, gdy year<1918 , ale jest używany dokładnie tak samo, jak /gdy year1918 ).

Zasady konkursu:

  • Możesz założyć, że wyrażenie matematyczne jest poprawne i używa tylko symboli 0123456789+-×/÷(). Oznacza to również, że nie będziesz musiał radzić sobie z potęgowaniem. (Możesz także używać innych symboli dla ×lub ÷(tj. *Lub %), jeśli to pomaga w grze w golfa lub jeśli twój język obsługuje tylko ASCII.)
  • Dozwolone jest dodawanie separatorów spacji do wyrażenia wejściowego, jeśli pomaga to (być może ręcznie) w ocenie wyrażenia.
  • I / O jest elastyczny. Dane wejściowe mogą być ciągiem, tablicą znaków itp. Rok może być liczbą całkowitą, obiektem daty, ciągiem itp. Dane wyjściowe będą liczbą dziesiętną.
  • Możesz założyć, że nie będzie podziału na 0 przypadków testowych.
  • Możesz założyć, że liczby w wyrażeniu wejściowym będą nieujemne (więc nie będziesz musiał radzić sobie z rozróżnianiem -jako symbolu ujemnego vs -jako symbolu odejmowania). Wynik może być jednak nadal ujemny!
  • Możesz założyć, N(że zawsze będzie napisane jak N×(zamiast. Skupimy się tylko na drugą kontrowersje symboli podziału /vs ÷w tym wyzwaniem.
  • Dziesiętne wartości wyjściowe powinny mieć dokładność co najmniej trzech cyfr dziesiętnych.
  • ÷4÷2÷2year<19184÷2÷242241442÷22)÷2)2)2) ).
  • ÷×/4÷2)×2)÷3)
  • [0000,9999]

Główne zasady:

  • To jest , więc wygrywa najkrótsza odpowiedź w bajtach.
    Nie pozwól, aby języki gry w golfa zniechęcały Cię do publikowania odpowiedzi w językach niekodujących golfa. Spróbuj znaleźć możliwie najkrótszą odpowiedź na „dowolny” język programowania.
  • Do odpowiedzi mają zastosowanie standardowe reguły z domyślnymi regułami We / Wy , więc możesz używać STDIN / STDOUT, funkcji / metody z odpowiednimi parametrami i typem zwracanych, pełnych programów. Twoja decyzja.
  • Domyślne luki są zabronione.
  • Jeśli to możliwe, dodaj link z testem na swój kod (tj TIO ).
  • Zalecane jest również dodanie wyjaśnienia do odpowiedzi.

Przypadki testowe:

Input-expression:   Input-year:   Output:      Expression interpretation with parenthesis:

6÷2×(1+2)           2018          9            (6/2)×(1+2)
6÷2×(1+2)           1917          1            6/(2×(1+2))
9+6÷3-3+15/3        2000          13           ((9+(6/3))-3)+(15/3)
9+6÷3-3+15/3        1800          3            (9+6)/((3-3)+(15/3))
4÷2÷2               1918          1            (4/2)/2
4÷2÷2               1900          4            4/(2/2)
(1÷6-3)×5÷2/2       2400          -3.541...    ((((1/6)-3)×5)/2)/2
(1÷6-3)×5÷2/2       1400          1.666...     ((1/(6-3))×5)/(2/2)
1×2÷5×5-15          2015          -13          (((1×2)/5)×5)-15
1×2÷5×5-15          1719          0.2          (1×2)/((5×5)-15)
10/2+3×7            1991          26           (10/2)+(3×7)
10/2+3×7            1911          26           (10/2)+(3×7)
10÷2+3×7            1991          26           (10/2)+(3×7)
10÷2+3×7            1911          0.434...     10/(2+(3×7))
4÷2+2÷2             2000          3            (4/2)+(2/2)
4÷2+2÷2             1900          2            4/((2+2)/2)
4÷2×2÷3             9999          1.333...     ((4/2)×2)/3
4÷2×2÷3             0000          3            4/((2×2)/3)
((10÷2)÷2)+3÷7      2000          2.928...     ((10/2)/2)+(3/7)
((10÷2)÷2)+3÷7      1900          0.785...     (((10/2)/2)+3)/7
(10÷(2÷2))+3×7+(10÷(2÷2))+3×7
                    1920          62           (10/(2/2))+(3×7)+(10/(2/2))+(3×7)
(10÷(2÷2))+3×7+(10÷(2÷2))+3×7
                    1750          62           (10/(2/2))+(3×7)+(10/(2/2))+(3×7)
10÷2/2+4            2000          6.5          ((10/2)/2)+4
10÷2/2+4            0100          2            10/((2/2)+4)
9+6÷3-3+15/3        9630          13           9+(6/3)-3+(15/3)
9+6÷3-3+15/3        0369          3            (9+6)/(3-3+(15/3))

Odpowiedzi:


25

R , 68 66 bajtów

function(x,y,`=`=`/`)eval(parse(t=`if`(y<1918,x,gsub('=','/',x))))

Wypróbuj online!

Oczekuje znaku równości =zamiast ÷i *zamiast ×.

Kod wykorzystuje pewne nieprzyjemne przeciążenie operatora, wykorzystując fakt, że =jest to operator od prawej do lewej z bardzo niskim priorytetem (dokładnie takie zachowanie, jakiego oczekujemy od 1918 roku ÷), a R zachowuje swój pierwotny priorytet, gdy jest przeciążony. Reszta jest dla nas automatycznie wykonywana przez eval.

Jako bonus, tutaj jest to samo dokładne podejście zastosowane w składni terser. Tym razem naszym operatorem specjalnego podziału jest tilde ( ~):

Julia 0,7 , 51 bajtów

~=/;f(x,y)=eval(parse(y<1918?x:replace(x,'~','/')))

Wypróbuj online!


3
`=`=`/`jest diabelski! Świetne rozwiązanie!
Gregor

uuugggghhh Miałem myśli na tej samej linii. Niestety, dość mocno mnie pobiłeś. Wypróbuj online
Giuseppe

Chociaż nie ma jeszcze odpowiedzi w językach codegolf, akceptuję twoją odpowiedź Julii jako najkrótszą na razie. Oczywiście może się to zmienić w przyszłości, jeśli opublikowana zostanie krótsza odpowiedź.
Kevin Cruijssen

6

JavaScript (ES6),  130 129  120 bajtów

Zaoszczędź 9 bajtów dzięki @ScottHamper

Pobiera dane wejściowe jako (year)(expr). Oczekuje %i *zamiast ÷i ×.

y=>g=e=>(e!=(e=e.replace(/\([^()]*\)/,h=e=>eval(e.split`%`.reduceRight((a,c)=>y<1918?`(${c})/(${a})`:c+'/'+a))))?g:h)(e)

Wypróbuj online!

W jaki sposób?

Przetwarzanie wyrażeń liści

Funkcja pomocnika h oczekuje wyrażenia liścia mijako dane wejściowe przetwarza wszystkie %symbole zgodnie z zasadami rokuy (zdefiniowany w zakresie nadrzędnym) i ocenia wynikowy ciąg.

Jeśli y<1918przekształcamy X%Yw (X)/(Y), aby wymusić niski priorytet i powtórzyć ten proces dla całego łańcucha od prawej do lewej, aby wymusić skojarzenie od prawej do lewej.

Przykłady:

  • 8%2staje się (8)/(2), którego uproszczoną formą jest8/2
  • 2+3%3+2 staje się (2+3)/(3+2)
  • 8%2%2staje się (8)/((2)/(2)), którego uproszczoną formą jest8/(2/2)

Jeśli y1918, każdy %jest po prostu zamieniany w /.

h = e =>                    // e = input string
  eval(                     // evaluate as JS code:
    e.split`%`              //   split e on '%'
    .reduceRight((a, c) =>  //   for each element 'c', starting from the right and
                            //   using 'a' as the accumulator:
      y < 1918 ?            //     if y is less than 1918:
        `(${c})/(${a})`     //       transform 'X%Y' into '(X)/(Y)'
      :                     //     else:
        c + '/' + a         //       just replace '%' with '/'
    )                       //   end of reduceRight()
  )                         // end of eval()

Radzenie sobie z zagnieżdżonymi wyrażeniami

Jak wspomniano powyżej, funkcja h jest zaprojektowany do działania na wyrażeniu liścia, tj. wyrażeniu bez jakiegokolwiek innego podwyrażenia zawartego w nawiasach.

Dlatego używamy funkcji pomocnika sol rekurencyjnie identyfikować i przetwarzać takie wyrażenia liści.

g = e => (            // e = input
  e !=                // compare the current expression with
    ( e = e.replace(  // the updated expression where:
        /\([^()]*\)/, //   each leaf expression '(A)'
        h             //   is processed with h
      )               // end of replace()
    ) ?               // if the new expression is different from the original one:
      g               //   do a recursive call to g
    :                 // else:
      h               //   invoke h on the final string
)(e)                  // invoke either g(e) or h(e)

Oto wersja hkrótsza o 9 bajtów:h=e=>eval(e.split`%`.reduceRight((a,c)=>y<1918?`(${c})/(${a})`:c+'/'+a))
Scott Hamper

@ScottHamper Very nice. „Od prawej do lewej” powinien był zadzwonić ... ale nie zadzwonił.
Arnauld

5

Python 3.8 (wersja wstępna) , 324 310 306 bajtów

lambda s,y:eval((g(s*(y<1918))or s).replace('%','/'))
def g(s):
 if'%'not in s:return s
 l=r=j=J=i=s.find('%');x=y=0
 while j>-1and(x:=x+~-')('.find(s[j])%3-1)>-1:l=[l,j][x<1];j-=1
 while s[J:]and(y:=y+~-'()'.find(s[J])%3-1)>-1:r=[r,J+1][y<1];J+=1
 return g(s[:l]+'('+g(s[l:i])+')/('+g(s[i+1:r])+')'+s[r:])

Wypróbuj online!

Bierze %zamiast ÷i *zamiast×


1

Perl 5, 47 97 95 bajtów

/ /;$_="($`)";$'<1918?s-%-)/(-g:y-%-/-;$_=eval

$_="($F[0])";1while$F[1]<1918&&s-\([^()]+\)-local$_=$&;s,%,)/((,rg.")"x y,%,,-ee;y-%-/-;$_=eval

TIO


3
Bardzo fajny pomysł. Masz jednak problem, z 4%2%2którym zwraca 1 w obu przypadkach. (podczas gdy powinien zwrócić 4 przed 1918 r.)
Dada

to prawda, nie mogę na razie patrzeć
Nahuel Fouilleul

1
@Dada, naprawiono (+ 50 bajtów)
Nahuel Fouilleul

1

Rdza - 1066 860 783 755 740 bajtów

macro_rules! p{($x:expr)=>{$x.pop().unwrap()}}fn t(s:&str,n:i64)->f64{let (mut m,mut o)=(vec![],vec![]);let l=|v:&Vec<char>|*v.last().unwrap();let z=|s:&str|s.chars().nth(0).unwrap();let u=|c:char|->(i64,fn(f64,f64)->f64){match c{'÷'=>(if n<1918{-1}else{6},|x,y|y/x),'×'|'*'=>(4,|x,y|y*x),'-'=>(2,|x,y|y-x),'+'=>(2,|x,y|y+x),'/'=>(5,|x,y|y/x),_=>(0,|_,_|0.),}};macro_rules! c{($o:expr,$m:expr)=>{let x=(u(p!($o)).1)(p!($m),p!($m));$m.push(x);};};for k in s.split(" "){match z(k){'0'..='9'=>m.push(k.parse::<i64>().unwrap() as f64),'('=>o.push('('),')'=>{while l(&o)!='('{c!(o,m);}p!(o);}_=>{let j=u(z(k));while o.len()>0&&(u(l(&o)).0.abs()>=j.0.abs()){if j.0<0&&u(l(&o)).0<0{break;};c!(o,m);}o.push(z(k));}}}while o.len()>0{c!(o,m);}p!(m)}

Rdza nie ma czegoś takiego jak „eval”, więc jest to trochę trudne. Zasadniczo jest to standardowy ewidencja poprawek Djisktra z polem manewrowym z niewielką modyfikacją. ÷ jest operatorem ze zmiennym priorytetem: niższy niż wszystko inne (oprócz nawiasów) w trybie <1918, wyższy niż wszystko inne w trybie> = 1918. Jest również „prawobowiązany” (czy lewy?), Aby <1918 spełniał specyfikację 4 ÷ 2 ÷ 2, a powiązanie jest „sfałszowane” poprzez uczynienie ÷ priorytetu ujemnym, a następnie podczas oceny traktuje jakikolwiek priorytet <0 jako powiązany. Jest więcej miejsca na grę w golfa, ale myślę, że to dobry projekt.

Ungolfed na play.rust-lang.org


Czy naprawdę potrzebujesz tyle białych znaków? Myślę, że większość z nich można usunąć.
ivzem

@ivzem dobry punkt, ale wciąż jest 3 razy większy niż python
don bright
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.