Diferença histórica entre `/` e `÷` nas expressões matemáticas


33

Introdução:

enter image description here

Inspirado por uma discussão que já está em andamento há muitos anos sobre a expressão 6÷2(1+2) .

Com a expressão 6÷2(1+2) , os matemáticos verão rapidamente que a resposta correta é 1 , enquanto as pessoas com uma formação matemática simples da escola verão rapidamente que a resposta correta é 9 . Então, de onde vem essa controvérsia e, portanto, respostas diferentes? Existem duas regras conflitantes na forma como 6÷2(1+2) é escrito. Um devido à parte2( e um devido ao símbolo de divisão ÷.

Embora matemáticos e 'pessoas comuns' usem PEMDAS (Parênteses - Expoentes - Divisão / Multiplicação - Adição / Subtração), para matemáticos a expressão é avaliada como esta abaixo, porque 2(3) é como, por exemplo, 2x2 um monomial também conhecido como " um único termo devido à multiplicação implícita por justaposição " (e, portanto, parte do Pin PEMDAS), que será avaliado diferentemente de 2×(3) (um binômio, também conhecido como dois termos):

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

Considerando que para 'pessoas comuns', 2(3) e2×(3) será o mesmo (e, portanto, parte doMDemPEMDAS), então eles vão usar isso em vez disso:

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

No entanto, mesmo que teria escrito a expressão original como 6÷2×(1+2) , pode ainda haver alguma controvérsia devido ao uso do símbolo de divisão ÷. Na matemática moderna, os símbolos /e ÷têm exatamente o mesmo significado: dividir. Algumas regras anteriores a 1918 relativas ao símbolo de divisão ÷†† afirmam que ele tinha um significado diferente do símbolo de divisão /. Isso ocorre porque ÷costumava significar " dividir o número / expressão à esquerda com o número / expressão à direita " ††† . Então a÷b então, seria(a)/(b) ouab agora. Nesse caso6÷2×(1+2) iria ser avaliado da seguinte maneira por pessoas pré-1918:

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

†: Embora eu tenha encontrado várias fontes explicando como ÷foi usado no passado (veja ††† abaixo), não consegui encontrar provas definitivas de que isso tenha mudado em algum lugar por volta de 1918. Mas, para o desafio, presumimos que 1918 foi o ponto de virada em que ÷e /começando a significar a mesma coisa, onde diferiam no passado.

††: Outros símbolos também foram usados ​​no passado para divisão, como :em 1633 (ou agora ainda na Holanda e em outros países europeus de língua não inglesa, pois é isso que eu aprendi pessoalmente na escola primária xD) ou )em os anos 1540. Mas para esse desafio, focamos apenas o significado anterior ao símbolo de obelus antes de 1918 ÷.
†††: Fontes: este artigo em geral . E as regras anteriores a 1918 ÷são mencionadas em: este artigo do The American Mathematics Monthly de fevereiro de 1917 ; este livro de álgebra alemã Teutsche de 1659, página 9 e página 76 ; este um primeiro livro em álgebrade 1895, página 46 [48/189] .

Ligeiramente fora de tópico: sobre a discussão real sobre essa expressão: ela nunca deve ser escrita assim em primeiro lugar! A resposta correta é irrelevante, se a pergunta não estiver clara. * Clica no botão "fechar, porque não está claro o que você está perguntando" * .
E, para que conste, mesmo versões diferentes das calculadoras Casio não sabem como lidar adequadamente com esta expressão:
enter image description here

Desafio:

Você recebe duas entradas:

  • Uma expressão matemática (válida) que consiste apenas nos símbolos 0123456789+-×/÷()
  • Um ano

÷year<1918/year1918

Regras do desafio:

  • Você pode assumir que a expressão matemática é válida e usa apenas os símbolos 0123456789+-×/÷(). Isso também significa que você não terá que lidar com exponenciação. (Você também estão autorizados a utilizar uma símbolos diferentes para ×ou ÷(ie *ou %), se isso ajuda a jogar golfe ou se a sua língua só suporta ASCII.)
  • Você pode adicionar delimitadores de espaço à expressão de entrada se isso ajudar na avaliação (talvez manual) da expressão.
  • A E / S é flexível. A entrada pode ser como uma sequência de caracteres, uma matriz de caracteres, etc. O ano pode ser como um número inteiro, objeto de data, sequência de caracteres etc. A saída será um número decimal.
  • Você pode assumir que não haverá divisão por 0 casos de teste.
  • Você pode assumir que os números na expressão de entrada não serão negativos (portanto, não será necessário diferenciar o -símbolo como negativo versus o -símbolo de subtração). A saída ainda pode ser negativa!
  • Você pode assumir N(que sempre será escrito como N×(alternativa. Vamos nos concentrar apenas na segunda controvérsia dos símbolos de divisão /vs ÷neste desafio.
  • Os valores decimais de saída devem ter uma precisão de pelo menos três dígitos decimais.
  • Se a entrada-expressão contém múltiplos ÷(ou seja4÷2÷2) com yeumar<1918, eles são avaliados assim: 4÷2÷2422414. (Ou em palavras: número4 é dividido pela expressão 2÷2onde expressão 2÷2 por sua vez significa número 2 é dividido pelo número 2.)
  • Observe que a maneira como ÷funciona implicitamente significa que ele tem precedência sobre o operador ×e /(consulte o caso de teste4÷2×2÷3)
  • Você pode assumir que o ano de entrada está dentro da faixa [0000,9999].

Regras gerais:

  • Isso é , então a resposta mais curta em bytes vence.
    Não permita que idiomas com código de golfe o desencorajem a postar respostas com idiomas que não sejam codegolf. Tente encontrar uma resposta o mais curta possível para 'qualquer' linguagem de programação.
  • As regras padrão se aplicam à sua resposta com as regras de E / S padrão , para que você possa usar STDIN / STDOUT, funções / método com os parâmetros adequados e programas completos do tipo retorno. Sua chamada.
  • As brechas padrão são proibidas.
  • Se possível, adicione um link com um teste para o seu código (ou seja, TIO ).
  • Além disso, é altamente recomendável adicionar uma explicação para sua resposta.

Casos de teste:

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

Respostas:


25

R , 68 66 bytes

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

Experimente online!

Espera sinal de igualdade em =vez de ÷e em *vez de ×.

O código utiliza alguma sobrecarga de operador desagradável, aproveitando o fato de =ser um operador da direita para a esquerda com precedência muito baixa (o comportamento exato que queremos desde 1918 ÷), e R mantém sua precedência original quando é sobrecarregado. O resto é feito automaticamente por nós eval.

Como um bônus, aqui está a mesma abordagem exata implementada na sintaxe do terser. Desta vez, nosso operador de divisão especial é til ( ~):

Julia 0,7 , 51 bytes

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

Experimente online!


3
`=`=`/`é diabólico! Ótima solução!
Gregor

uuugggghhh eu tinha pensamentos nas mesmas linhas. Infelizmente, você me venceu bastante. Experimente online
Giuseppe

Embora ainda não haja respostas nas linguagens codegolf, estou aceitando a sua resposta Julia como a mais curta por enquanto. É possível que isso mude no futuro, se uma resposta mais curta for publicada.
Kevin Cruijssen 5/04

6

JavaScript (ES6),  130 129  120 bytes

Guardado 9 bytes graças a @ScottHamper

Toma entrada como (year)(expr). Espera %e em *vez de ÷e ×.

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

Experimente online!

Quão?

Processando expressões folha

A função auxiliar h espera uma expressão foliar ecomo entrada, processa todos os %símbolos de acordo com as regras do anoy (definido no escopo pai) e avalia a sequência resultante.

E se y<1918, transformamos X%Yem (X)/(Y), para impor baixa precedência e repetir esse processo para toda a cadeia de caracteres da direita para a esquerda para aplicar a associatividade da direita para a esquerda.

Exemplos:

  • 8%2torna-se (8)/(2), cuja forma simplificada é8/2
  • 2+3%3+2 torna-se (2+3)/(3+2)
  • 8%2%2torna-se (8)/((2)/(2)), cuja forma simplificada é8/(2/2)

E se y1918, cada um %é simplesmente transformado em um /.

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

Lidando com expressões aninhadas

Como mencionado acima, a função h foi projetado para operar com uma expressão de folha, ou seja, uma expressão sem nenhuma outra subexpressão entre parênteses.

É por isso que usamos a função auxiliar g identificar e processar recursivamente essas expressões de folha.

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)

Aqui está uma versão h9 bytes mais curta:h=e=>eval(e.split`%`.reduceRight((a,c)=>y<1918?`(${c})/(${a})`:c+'/'+a))
Scott Hamper

@ScottHamper Very nice. 'Direita para a esquerda' deveria ter tocado um sino ... mas não tocou.
Arnauld

5

Python 3.8 (pré-lançamento) , 324 310 306 bytes

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

Experimente online!

Toma em %vez de ÷e em *vez de×


1

Perl 5, 47 97 95 bytes

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

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

TIO


3
Idéia muito boa. No entanto, você tem um problema com o 4%2%2qual retorna 1 nos dois casos. (considerando que deve retornar 4 antes de 1918)
Dada

é verdade, eu não posso mais olhar por enquanto
Nahuel Fouilleul 28/02

1
@Dada, fixo (+ 50bytes)
Nahuel Fouilleul 28/02

1

Ferrugem - 1066 860 783 755 740 bytes

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

Rust não tem nada como 'eval', então isso é um pouco difícil. Basicamente, este é um avaliador de infix padrão do pátio de desvio do Djisktra com uma pequena modificação. ÷ é um operador com precedência variável: menor que tudo o resto (exceto parênteses) no modo <1918, maior que tudo no modo> = 1918. Também é 'associado à direita' (ou à esquerda?) Para que <1918 atenda à especificação 4 ÷ 2 ÷ 2, e a associação é "falsificada" ao tornar ÷ a precedência negativa e, durante a avaliação, trata qualquer precedência <0 como associada. Há mais espaço para jogar golfe, mas acho que é um bom rascunho.

Ungolfed em play.rust-lang.org


Você realmente precisa de tanto espaço em branco? Eu acho que a maior parte poderia ser removida.
ivzem 9/03

@ivzem bom ponto, mas ainda é 3 vezes maior que python
don bright
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.