(Posso) Adicionar parênteses para tornar isso verdadeiro

8

Eu vi essa recente pergunta intrigante:

Adicione parênteses para tornar isso verdadeiro

E viu que uma resposta usava um script Python para tentar todas as possibilidades .

Seu desafio é, dada uma expressão (como uma string) e um número inteiro, criar um programa que possa dizer se você pode adicionar parênteses para tornar a expressão igual ao número inteiro.

Por exemplo, se a expressão é 1 + 2 * 3e o número inteiro é 9, você pode adicionar parênteses como (1 + 2) * 3, o que é igual a 9, portanto a saída deve ser verdadeira. Mas se a expressão é 1 + 2 - 3 * 4 / 5e o número inteiro é 9999999999999, você não pode adicionar nenhuma quantidade de parênteses para torná-lo igual 9999999999999, portanto a saída deve ser falsa.

Observe que a entrada inteira pode ser positiva ou negativa, mas a expressão conterá apenas números inteiros positivos. De fato, a expressão sempre corresponderá (\d+ [+*/-] )+ \d(regex). Em outras palavras, há parênteses, há expoentes, apenas +, -, *e /. Ordem padrão do operador ( *e /, então +e -).

Mais casos de teste:

1 + 2 - 3 * 4 / 9 and -1 -> truthy, ((1 + 2) - (3 * 4)) / 9
10 - 9 * 8 - 7 * 6 - 5 * 4 - 3 * 2 - 2 * 1 and 1, falsey, see linked question
10 + 9 - 8 * 7 + 6 - 5 * 4 + 3 - 2 * 1 and 82 -> truthy, (10 + (9 - 8)) * 7 + (6 - 5) * 4 + 3 - 2 * 1
34 + 3 and 15 -> falsey
1 + 2 + 5 + 7 and 36 -> falsey
1 / 10 * 3 + 3 / 10 * 10 and 6 -> truthy, (1/10*3+3/10)*10

Alguma pergunta?

Você pode gerar a expressão entre parênteses, se possível, por exemplo, (10 + (9 - 8)) * 7 + (6 - 5) * 4 + 3 - 2 * 1para o último caso de teste. Eu preferiria isso a apenas um valor verdadeiro, mas depende de você. O uso 2(5)para multiplicação não é permitido, apenas *.

programmer5000
fonte
/é a divisão de flutuação, certo?
Rod
@ Rod sim, é.
Programmer5000
1
Você deve ter um caso de teste que exija que um resultado intermediário não inteiro seja usado.
feersum
Você deve adicionar um caso de teste, onde pode ocorrer a divisão por zero, como3 / 2 - 1 - 1 and 2 -> 3 / (2 - 1) - 1
mbomb007

Respostas:

3

Python 2, 286 285 282 bytes

from fractions import*
P=lambda L:[p+[L[i:]]for i in range(len(L))for p in P(L[:i])]or[L]
x,y=input()
x=x.split()
for p in P(['Fraction(%s)'%e for e in x[::2]]):
 try:print 1/(eval(''.join(sum(zip(eval(`p`.replace("['","'(").replace("']",")'")),x[1::2]+[0]),())[:-1]))==y)
 except:0

Experimente online

Explicação:

Esta versão imprimirá todas as expressões de trabalho (com os Fractionobjetos).

from fractions import*
# Sublist Partitions (ref 1)
P=lambda L:[p+[L[i:]]for i in range(len(L))for p in P(L[:i])]or[L]
x,y=input()
x=x.split()
# Convert all numbers to Fractions for division to work
n=['Fraction(%s)'%e for e in x[::2]]
# Operators
o=x[1::2]
# Try each partition
for p in P(n):
    # Move parens to be inside strings
    n=eval(`p`.replace("['","'(").replace("']",")'"))
    # Alternate numbers and operators (ref 2)
    x=''.join(sum(zip(n,o+[0]),())[:-1])
    # Prevent division by zero errors
    try:
        # Evaluate and check equality
        if eval(x)==y:print x
    except:0

Experimente online

Referências:

  1. Função de particionamento

  2. Zip alternado

Guardado 3 bytes graças a Felipe Nardi Batista

mbomb007
fonte
1- Você pode usar python3 ( /é a divisão float) e largar todos os fractionsusos? 2 - E as divisões por 0?
Rod
@ Rod Não, você não pode. A divisão de flutuação é a razão pela qual é necessária.
Mbomb007
Qual é o motivo então?
Rod
oh, questões de arredondamento
Rod
Corrigi a divisão pelo problema zero. Ainda funcionava para qualquer exemplo em que a solução chegasse antes da divisão por zero, mas encontrei um caso de teste que a quebrou. É o último caso de teste no meu conjunto de testes.
Mbomb007