Matemática de dois símbolos

8

Introdução

Os quatro operadores matemáticos básicos (+, -, *, /) podem ser reduzidos para apenas dois, devido ao fato de:

x + y = x - (-y)
x * y = x / (1/y), y != 0
x * 0 = 0/x

Desafio

O desafio é receber a entrada como uma "string" que contém:

  • Números
  • Variáveis ​​de caractere único ("x", "y")
  • Os quatro operadores matemáticos básicos (+, -, *, /)
  • Parêntese

e produzir uma string manipulada para produzir o mesmo resultado matemático da entrada, mas contendo apenas os símbolos matemáticos '-' e '/'

Específicos

  • A entrada pode estar em qualquer forma aceitável (arquivo, STDIN etc.) e pode ser representada como uma cadeia de caracteres ou matriz de caracteres (mas não uma matriz de matrizes)
  • A saída pode estar em qualquer forma aceitável (arquivo, STDIN etc.) e pode ser representada como uma cadeia de caracteres ou matriz de caracteres (mas não uma matriz de matrizes)
  • Você deve reconhecer e manter parênteses equilibrados
  • As brechas padrão não são permitidas
  • É sua escolha se você deseja representar x + ycomo x - -youx - (-y)
  • Você deve manter a ordem das operações
  • Você nunca precisa lidar com entradas inválidas
  • A entrada pode estar vazia ou um único número / variável; nesse caso, o programa deve emitir a entrada
  • Nota: Você não precisa usar as substituições na introdução, desde que o input = outputseu programa possa mudar 2 * 2para 8/2, se você desejar
  • Você pode assumir que "0" é a única maneira de um zero aparecer na equação (ou seja, você não precisa lidar com isso 1 * (4 - 4))
  • Sugestão: para testar seu programa, vá para este site, digite input = outputonde input é input e output é output, e se o resultado for "true", seu programa lidou com esse caso com êxito ( exemplo , exemplo )

Casos de teste

Abaixo estão alguns casos de teste, entrada como uma única sequência e saída como uma única sequência.

x + y
x - (-y)

x * y
x / (1/y)

x / y
x / y

x - y
x - y

1
1

5
5

-6
-6

+x
x

1 + (x * 4) - (512 * 3)
1 - (-(x / (1/4))) - (512 / (1/3))

1 - 3 / 4 + l / g
1 - 3/4 - (-(l / g))

5 * 0 / 2
0/5 / 2

(a + g) * 0
0/(a - (-g))

Pontuação

É , então a resposta mais curta em bytes vence. Os laços são resolvidos pela primeira postagem.

Phoenix socrático
fonte
2
A propósito x / 1/y= x/yporque a divisão não é associativa. Eu sei o que você está pensando, mas mesmo o WolframAlpha não reconhece que deseja espaços para alterar a ordem das operações ... então você provavelmente deve repensar isso ou não citar isso como uma maneira válida de verificar as coisas.
Linus
1
@ Linus: Também não é equivalente quando y=0, mas acho que o desafio implica isso implicitamente n/d => d != 0.
Tim Čas 4/16
@ TimČas ahh! Não pensei nisso. Vou atualizar o desafio, só sei que terão de ser tratadas adequadamente
socrático Phoenix
Tal como está, há muito pouco nos impedindo de simplesmente avaliar a expressão e retornar o resultado (eles são matematicamente iguais, afinal). Eu recomendaria mudar isso, a menos que você queira vser uma solução adequada em Pyth.
Steven H.
Espere, então, se houver variáveis ​​(como xey), como podemos dividir sem arriscar a divisão por zero? 5 * (a - b)se a = b. E temos que detectar coisas assim 5 * (a - a)? Que tal 5 * (4 - 4)e 5 * (a / a - 1)ou 5 * (4 / 4 - 1)?
Adám 6/09/16

Respostas:

4

Python 3, 267 bytes

Obrigado a @ ConorO'Brien

import re
q=re.sub
g=lambda m:'--'+m.group()[1:]
h=lambda m:'/(1/'+m.group()[1:]+')'
i=lambda m:'0/'+m.group()[:-2]
print(q(r'\*[^\(\)]+',h,q(r'[^\(\)]\*0',i,q(r'\+[^\(\)]+',g,q(r'\*\([^\)]+\)',h,q(r'\([^\)]+\)\*0',i,q(r'\+\([^\)]+\)',g,input().replace(' ',''))))))))

Ideone it!

Beta Decay
fonte
Honestamente, eu não tenho nenhuma idéia do que magia negra você empregada, mas +1 para FGITW
socrático Phoenix
@SocraticPhoenix Haha a magia negra é chamada regex;)
Decay Beta
1

Dyalog APL , 42 bytes

Isso mantém a ordem das operações dos APLs. Note que ÷xé1÷x

'\+' '×'R'--' '÷÷'('(.*)×0'R'0÷\1'~∘' ')

TryAPL online!

( no resultado de ...

~∘' ' remover espaços

'(.*)×0'⎕R'0÷\1' substitua qualquer coisa seguida por "× 0" por "0 ÷" seguida por ela

) Avalie...

'\+' '×'⎕R'--' '÷÷' substitua "+" por "-" e "×" por "÷÷"

Verificar:

  1. Atribuir aleatórias diferentes de zero para números x, y, l, g, e a.

  2. Execute as expressões originais.

  3. Execute as expressões modificadas.

  4. Compare os resultados.

Adão
fonte
0

SED 272 246 239 213

s,^\+,,;s,[^+*/()-]\+,(&),g;t;:;s,)[^)]*)\*(0,&,;tr;s,\((.*)\)\*(0),(0/\1),;ty;s,\*([^)]*(,&,;tr;s,\*\(([^)]*)\),/(1/\1),;ty;s,\+([^)]*(,&,;tr;s,\+\(([^)]*)\),-(-\1),;ty;p;q;:r;s,(\([^()]*\)),!\1@,;t;:y;y,!@,(),;b

Tome entrada sem espaços (por exemplo x+y*2).
Este é um dos poucos casos em que é realmente mais curto escapar (e )capturar grupos em vez de usar -r. Tenho certeza de que isso pode ser mais praticado, mas estou feliz por enquanto.

Ungolfed, com comentários:

s,^\+,, #remove leading +
s,[^+*/()-]\+,(&),g #suround numbers/variables in ()
t start #reset the test because the line above will always match

:start
#------------- deal with *0 ------------------
s,)[^)]*)\*(0,&, #remove inner matching ()
t replace
s,\((.*)\)\*(0),(0/\1),
t y
#------------- deal with generic * -----------
s,\*([^)]*(,&, #remove inner matching ()
t replace
s,\*\(([^)]*)\),/(1/\1),
t y
#------------- deal with + -------------------
s,\+([^)]*(,&, #remove inner matching ()
t replace
s,\+\(([^)]*)\),-(-\1),
t y

b end #all done, branch to the end

#------------- replace a set of () with !@ ---
#repeated application of this helps find the matching ( or )
:replace
s,(\([^()]*\)),!\1@,
t start

:y
y,!@,(),
b start

:end
Riley
fonte