Gere uma equação válida usando números especificados pelo usuário

10

Isso é baseado em um jogo que um dos meus professores de matemática costumava jogar no ensino médio. Ele escrevia cinco números aleatórios de um dígito no quadro e depois um número aleatório de dois dígitos. Tentaríamos criar uma equação que usasse todos os 5 números de um dígito para gerar o número de dois dígitos. Aqui estão alguns exemplos com soluções para explicar melhor isso:

Input:           Solution:
7 5 4 8 4 34     5*8-7+4/4 = 34
3 1 5 7 6 54     (7+3)*6-5-1 = 54
3 9 2 1 6 87     9*(2+1)*3+6 = 87
2 1 6 9 7 16     (9-7+6*1)*2 = 16
2 4 5 8 6 96     8*(5+6)+2*4 = 96
3 8 4 5 4 49     8*(4+4)-3*5 = 49

Esse desafio é escrever um programa que possa gerar essas equações para uma determinada entrada. A entrada pode ser fornecida pela linha de comando ou por um prompt. Os 5 números de um dígito sempre serão inseridos primeiro (em nenhuma ordem específica), seguidos pelo número de dois dígitos. O programa imprimirá uma equação de solução que encontrar; você não precisa lidar com situações em que não há solução. A função deve ser capaz de usar as seguintes operações na equação: adição, subtração, multiplicação e divisão. Se você deseja permitir operações básicas adicionais, tudo bem, desde que permaneçam no espírito do desafio (negação, exponenciação e módulo seriam boas adições). A ordem das operações segue as regras matemáticas padrão, portanto, parênteses serão necessários para o agrupamento.

Os programas serão classificados com base no tamanho do código (incluindo espaço em branco necessário). Nota: a divisão deve ser exata, não arredondada ou truncada para o número inteiro mais próximo.

Sir_Lagsalot
fonte
Essa é uma tarefa muito semelhante, mas acho que o termo adicional e nenhuma restrição sobre como as expressões são agrupadas deve expandir o problema o suficiente para que seja interessante diferente. Além disso, este é um desafio de golfe em vez de um desafio de código, que exigirá soluções diferentes.
Sir_Lagsalot
E a concatenação? por exemplo, se dado 7 5 4 8 4 34, a saída 7 + 54/8 * 4 seria permitida?
Patrick Roberts

Respostas:

7

Python 2.7 (284), Python 3.x (253)

from __future__ import division #(Remove for Python 3.x)
from itertools import *
a=raw_input().split()
for i in permutations(a[:-1],5):
 for j in product('+-*/',repeat=5):
  for k,l in combinations(range(1,12,2),2):
   d=''.join(sum(zip(i,j),()))[:-1];d='('+d[:l]+')'+d[l:]
   if eval(d)==int(a[-1]):print d;b

Dá um erro (chamando função desconhecida b) na solução.

Basicamente, é uma força bruta gigantesca. Ele recebe a entrada, divide-a por seus espaços ( 1 2 -> [1,2]) e, em seguida, permite a passagem nessa lista. A cada permutação, ele percorre todas as sequências possíveis de comprimento 5, usando os caracteres +-*/. Com cada uma dessas iterações, ele gera as combinações de comprimento 2 da lista [1,3,5,7,9,11], entrelaça a permutação e a string juntas ( 12345 *-/+- -> 1*2-3/4+5-) e coloca os parênteses. Finalmente, ele será avaliado e, se a resposta e a equação forem verdadeiras, imprime a equação e para.

Isso é terrivelmente ineficiente, O(n!/(n-5)!)=O(n^5)mas é executado em um tempo razoável para as entradas de teste.

beary605
fonte
11
A matemática inteira pode causar uma saída incorreta ao usar a divisão. Por exemplo, a entrada "3 6 8 7 1 29" produz "(3 + 8/6) * 7 + 1", que é igual a 31 1/3, e não 29. Atualizarei a descrição para tornar isso explícito.
Sir_Lagsalot
(3/6)*8*7+1pra mim.
beary605
Ok, vou considerar isso um problema com o intérprete que usei.
precisa saber é o seguinte
3

Scala 368:

O segundo g = -Line é mais fácil de testar, o primeiro é flexível para receber argumentos de comando, e ambos têm o mesmo comprimento, então conto apenas a partir do segundo - remova-o para passar argumentos:

val g=(args.map(_.toDouble))
val g=Array(3,9,2, 1, 6, 87)
val k="+*/-DQ"
val i=(0 to 5)
val f:Seq[(Double,Double)=>Double]=Seq(_+_,_*_,_/_,_-_,(a,b)=>b-a,(a,b)=>b/a)
val h=g.init.permutations;
for(j<-h;o<-i;p<-i;q<-i;r<-i;z=try{f(r)(f(q)(f(p)(f(o)(j(0),j(1)),j(2)),j(3)),j(4))}catch{case _ => 0}
if(z==g(5)))printf("(((%d%c%d)%c%d)%c%d)%c%d=%d\n",j(0),k(o),j(1),k(p),j(2),k(q),j(3),k(r),j(4),g(5))

Exemplo de saída (você pode ter uma pergunta agora - apenas um momento):

(((5+7)/1)+6)*3=54
(((5-7)D1)*6)*3=54
(((5D7)+1)*6)*3=54
(((5+7)+6)Q1)Q3=54

E essa coisa 5D7? D1? É hexadecimal? Há Q1, Q3 - o que é isso.

Sir_Lagsalot permitiu novas operações básicas no espírito do desafio e, sim, são operações básicas, Delta e Quociente.

Eles são diferentes de a / be ab, em que aQb significa b / a e aDb significa ba. Vamos chamá-lo de notação ucraniana.

então

(((5-7)D1)*6)*3=54

significa

((1-(5-7))*6)*3=54
 (1-(-2))*6*3
   3*6*3 = 18*3=54

Para a questão mais interessante de como e por quê: No começo, fiquei bravo com as possibilidades de colocar os parênteses e se (a + b) -c = a + bc = (a + bc) = ((a + b ) -c) = (b + a) -c e assim por diante. Você pode ficar bravo com essa pergunta, mas se você escrever as possíveis combinações de parênteses, às vezes jogará fora a folha de rascunho e encarará o fato: você sempre executa 4 operações entre 5 valores e sempre começa com uma delas. Se o padrão é sempre (((_x_)x_)x_)x_ ?= _(x sendo um dos 4 operadores) e permite a direção oposta (xb) e (bxa), você abordou todas as possibilidades.

Agora, para a + b e a * b, não precisamos de uma direção oposta, eles são comutativos. Então, eu inventei o operador D e Q, que apenas muda a direção. Agora tenho mais 2 operadores, mas não preciso mudar de direção. Bem - isso é feito na função Sequence:

 (a,b)=>b-a,(a,b)=>b/a

Minha compreensão extrai os valores da matriz g e os distribui de a para e, em seguida, escolho 4 índices para selecionar a função e, posteriormente, o símbolo do operador associado (apenas por índice). Eu tenho que pegar erros div / 0, pois a subtração pode levar a zeros, enquanto os dados de entrada de amostra não contêm um 0.

Usuário desconhecido
fonte
Os operadores Delta e Quociente estão bem. Se você planeja jogar golfe, precisará adicionar parênteses à saída.
precisa saber é o seguinte
A saída agora imprime parênteses.
usuário desconhecido