Générez une équation valide en utilisant des nombres spécifiés par l'utilisateur

10

Ceci est basé sur un jeu que l'un de mes professeurs de mathématiques jouait au collège. Il inscrirait 5 nombres aléatoires à un chiffre sur le tableau, puis un nombre aléatoire à deux chiffres. Nous essayons de créer une équation qui utilise les 5 nombres à un chiffre pour produire le nombre à deux chiffres. Voici quelques exemples avec des solutions pour mieux l'expliquer:

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

Ce défi consiste à écrire un programme capable de générer de telles équations pour une entrée donnée. L'entrée peut être fournie via la ligne de commande ou via une invite. Les 5 numéros à un chiffre seront toujours entrés en premier (dans aucun ordre particulier), suivis du numéro à deux chiffres. Le programme imprimera alors une équation de solution qu'il trouve; vous n'avez pas à gérer des situations où il n'y a pas de solution. La fonction doit être capable d'utiliser les opérations suivantes dans l'équation: addition, soustraction, multiplication et division. Si vous souhaitez autoriser des opérations de base supplémentaires, c'est bien tant qu'elles restent dans l'esprit du défi (la négation, l'exponentiation et le module seraient de jolis ajouts). L'ordre des opérations suit les règles mathématiques standard, donc des parenthèses seront nécessaires pour le regroupement.

Les programmes seront notés en fonction de la longueur du code (y compris les espaces requis). Remarque: la division doit être exacte, non arrondie ou tronquée à l'entier le plus proche.

Sir_Lagsalot
la source
C'est une tâche très similaire, mais je pense que le terme supplémentaire et aucune restriction sur la façon dont les expressions sont regroupées devraient étendre le problème suffisamment pour qu'il soit intéressant de façon différente. De plus, il s'agit d'un défi de golf au lieu d'un défi de code, qui nécessitera différentes solutions.
Sir_Lagsalot
Et la concaténation? Par exemple, si donné 7 5 4 8 4 34, la sortie 7 + 54/8 * 4 serait autorisée?
Patrick Roberts

Réponses:

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

Il donne une erreur (appelant une fonction inconnue b) sur la solution.

Fondamentalement, c'est une force brute gigantesque. Il prend l'entrée, la divise par ses espaces ( 1 2 -> [1,2]), puis permute à travers cette liste. À chaque permutation, il parcourra toutes les chaînes possibles de longueur 5 en utilisant les caractères +-*/. Avec chacune de ces itérations, il générera les combinaisons de longueur 2 de la liste [1,3,5,7,9,11], entrelacera la permutation et la chaîne ensemble ( 12345 *-/+- -> 1*2-3/4+5-), et mettra les parenthèses. Enfin, il l'évaluera et si la réponse et l'équation sont vraies, il imprime l'équation et s'arrête.

C'est horriblement inefficace, O(n!/(n-5)!)=O(n^5)mais cela fonctionne dans un délai raisonnable pour les entrées de test.

beary605
la source
1
Les mathématiques entières peuvent entraîner une sortie incorrecte lors de l'utilisation de la division. Par exemple, l'entrée "3 6 8 7 1 29" donne "(3 + 8/6) * 7 + 1", ce qui équivaut à 31 1/3, pas 29. Je mettrai à jour la description pour rendre cela explicite.
Sir_Lagsalot
Ça (3/6)*8*7+1me donne .
beary605
D'accord, je dirai que c'est un problème avec l'interprète que j'ai utilisé.
Sir_Lagsalot
3

Scala 368:

Le 2ème g = -Line est plus facile à tester, le premier est flexible pour prendre des arguments de commande, et les deux sont de longueur égale, donc je ne compte que pour le second - supprimez-le pour faire passer les arguments:

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

Exemple de sortie (vous pourriez avoir une question en ce moment - juste un instant):

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

Et cette chose 5D7? D1? Est-ce hexadécimal? Il y a Q1, Q3 - qu'est-ce que c'est.

Sir_Lagsalot a permis de nouvelles opérations de base dans l'esprit du défi, et oui, ce sont des opérations de base, Delta et Quotient.

Ils sont différents de a / b et ab en ce que aQb signifie b / a et aDb signifie ba. Appelons cela la notation ukrainienne.

Donc

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

veux dire

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

À la question la plus intéressante du comment et du pourquoi: Au début, je me suis fâché sur les possibilités de placer les parenthèses, et si (a + b) -c = a + bc = (a + bc) = ((a + b ) -c) = (b + a) -c et ainsi de suite. Vous pouvez vous énerver sur cette question, mais si vous écrivez les combinaisons de parenthèses possibles, vous jetez parfois la feuille de travail et faites face au fait: vous effectuez toujours 4 opérations entre 5 valeurs et vous commencez toujours par l'une d'entre elles. Si le motif est toujours (((_x_)x_)x_)x_ ?= _(x étant l'un des 4 opérateurs) et autorise la direction opposée (xb) et (bxa), vous avez évoqué toutes les possibilités.

Maintenant pour a + b et a * b nous n'avons pas besoin de direction opposée, ils sont commutatifs. J'ai donc inventé l'opérateur D et Q, qui vient de changer de direction. J'ai maintenant 2 opérateurs de plus, mais je n'ai pas besoin de changer de direction. Eh bien - cela se fait dans la fonction Sequence:

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

Ma compréhension comprend les valeurs du tableau g et les distribue sur a à e, puis je choisis 4 index pour choisir la fonction et plus tard (uniquement par index) le symbole opérateur associé. Je dois attraper des erreurs div / 0, car la soustraction peut conduire à des zéros, tandis que les données d'entrée d'échantillon ne contiennent pas de 0.

Utilisateur inconnu
la source
Les opérateurs Delta et Quotient vont bien. Si vous prévoyez de jouer au golf, vous devrez ajouter des parenthèses à la sortie.
Sir_Lagsalot
La sortie imprime maintenant des parenthèses.
utilisateur inconnu