Déchiffrer les symboles mathématiques

13

Si vous avez lu le livre Contact de Carl Sagan, ce défi peut vous sembler familier.


Étant donné l'entrée d'un ensemble d'équations mathématiques consistant en un nombre, un opérateur inconnu, un autre nombre et un résultat, déduisez quels opérateurs représentent l'addition, la soustraction, la multiplication ou la division.

Chaque équation d'entrée sera toujours composée de

  • un entier non négatif
  • une des lettres A, B, CouD
  • un autre entier non négatif
  • le personnage =
  • un entier non négatif final

concaténés ensemble. Par exemple, une entrée possible est 1A2=3, dont vous pouvez déduire que Areprésente l'addition. Chacun des entiers satisfera 0 ≤ x ≤ 1,000.

Cependant, ce n'est pas toujours aussi simple que cela. Il est possible qu'il y ait ambiguïté entre:

  • 5A0=5: addition soustraction
  • 1A1=1: multiplication / division
  • 0A5=0: multiplication / division
  • 2A2=4: addition / multiplication
  • 4A2=2: soustraction / division
  • 0A0=0: addition / soustraction / multiplication

etc. Le défi consiste à utiliser cette capacité à affiner les choix, combinée à un processus d'élimination, pour déterminer quel opérateur chaque lettre représente. (Il y aura toujours au moins une équation d'entrée, et il sera toujours possible de faire correspondre sans ambiguïté et de façon unique chaque lettre utilisée dans l'entrée avec un seul opérateur.)

Par exemple, supposons que l'entrée soit les équations suivantes:

  • 0A0=0: cela réduit A à l'addition, la soustraction ou la multiplication (ne peut pas diviser par 0).
  • 10B0=10: B doit être soit une addition soit une soustraction.
  • 5C5=10: C est évidemment l'addition, ce qui fait la soustraction B, ce qui fait la multiplication A.

Par conséquent, la sortie de ces équations d'entrée doit correspondre Aavec *, B avec -et Cavec +.

L'entrée peut être donnée sous la forme d'une chaîne unique séparée par des espaces / virgules ou d'un tableau de chaînes, chacune représentant une équation. La sortie peut être une chaîne unique ( "A*B-C+"), un tableau ( ["A*", "B-", "C+"]) ou un tableau 2D de type dictionnaire / dict ( {"A": "*", ...}ou [["A", "*"], ...]).

Vous pouvez supposer qu'un nombre ne sera jamais divisé par un autre nombre auquel il n'est pas divisible (vous n'avez donc pas à vous soucier de savoir si la division doit être flottante ou tronquée).

Puisque c'est du , le code le plus court en octets l'emporte.

Cas de test:

In                       Out
-------------------------------
0A0=0 10B0=10 5C5=10     A*B-C+
100D100=10000            D*
4A2=2 4B2=2 0A0=0        A-B/
15A0=15 4B2=2 2C2=0      A+B/C-
1A1=1 0A0=0              A*
0A0=0 2A2=4 5B0=5 2B2=4  A*B+
2A2=4 0C0=0 5B0=5 5A0=5  A+B-C*
0A1000=0 4A2=2           A/
Poignée de porte
la source
1
Faisons-nous une division entière (tronquée)?
Martin Ender
@ MartinBüttner Vous pouvez supposer qu'il n'y aura jamais de division par un nombre qui ne donne pas un nombre entier. (Modifié en question.)
Poignée de porte
Pouvons-nous produire en tant que dictionnaire?
lirtosiast
@ThomasKwa Bien sûr, un dictionnaire est également une sortie acceptable.
Poignée de porte
La plupart des exemples ne sont pas cohérents avec " il sera toujours possible d'identifier sans ambiguïté, de façon unique quelle lettre représente quel opérateur ", bien qu'ils soient cohérents avec " il sera toujours possible d'identifier sans ambiguïté quel opérateur est représenté par chaque lettre utilisée dans le entrée ".
Peter Taylor

Réponses:

9

MATL , 53 octets

j61tthYX'+-*/'X{Y@!"t'ABCD'!XKX{@YXU?K@Y}hwxKGm1L3$).

Utilise la version actuelle (10.1.0)

EDIT (12 juin 2016): pour s'adapter aux changements de langue, remplacer Y}par get 1L3$)par Y). Le lien ci-dessous intègre ces modifications

Essayez-le en ligne!

Explication

Cela teste toutes les permutations possibles des quatre opérateurs dans une boucle jusqu'à ce qu'une permutation rend toutes les équations vraies.

Pour tester si les équations sont vraies, une expression régulière est appliquée pour remplacer les quatre lettres par les opérateurs (dans l'ordre dicté par la permutation actuelle), et la chaîne est convertie en nombres (évalués). Cela donne un tableau avec autant de nombres que d'équations, dans lequel les équations qui sont vraies deviennent 1et les équations qui sont fausses deviennent 0. Si ce vecteur ne contient que1 valeurs, nous avons terminé.

La solution trouvée attribue des opérateurs aux quatre lettres, mais elles n'apparaissent pas toutes nécessairement dans l'entrée. Un dernier test est donc effectué pour éliminer les lettres non utilisées (et leurs opérateurs correspondants).

j            % input data string
61           % '=' (ASCII)
tth          % duplicate twice and concat: '==' (ASCII)
YX           % regexprep to change '=' into '==' in input string
'+-*/'       % push string
X{           % transform into cell array {'+','-','*','/'}
Y@!          % all permutations, each in a column
"            % "for" loop. Iterate columns (that is, permutations)
  t          %   duplicate data string containing '=='
  'ABCD'!XK  %   create column array ['A';'B';'C';'D'] and copy to clipboard K
  X{         %   transform into column cell array {'A';'B';'C';'D'} 
  @          %   push column cell array with current permutation of operator symbols
  YX         %   regexprep. Replaces 'A',...,'D' with current permutation of operators
  U          %   convert to numbers, i.e. evaluate string
  ?          %   if all numbers are 1 (truthy result): found it! But before breaking...
    K        %     push column array ['A';'B';'C';'D']
    @Y}      %     push column array with current permutation of operator symbols
    h        %     concatenate horizontally into 4x2 char array
    wx       %     delete original input so it won't be displayed
    K        %     push ['A';'B';'C';'D']
    G        %     push input string
    m        %     logical index that tells which of 'A',...,'D' were in input string
    1L3$)    %     apply that index to select rows of the 4x2 char array
    .        %     we can now break "for" loop
             %   implicitly end "if"
             % implicitly end "for"
             % implicitly display stack contents
Luis Mendo
la source
6

Python, 278 caractères

Ma première réponse sur le code golf ...

C'est juste une fonction implémentant un algorithme de force brute, vous l'appelez en passant comme argument la chaîne d'équations.

from itertools import *
def f(s):
    l=list("ABCD")
    for p in permutations("+-*/"):
        t=s
        for v,w in zip(l+["="," "],list(p)+["=="," and "]):
            t=t.replace(v, w)
        try:
            o=""
            if eval(t):
                for c,r in zip(l,p):
                    if c in s:
                        o+=c+r
                return o
        except:
            pass
Bob
la source
Je ne sais pas si cela fonctionne, mais pouvez-vous remplacer ["A","B","C","D"]par list("ABCD")?
Adnan
Ce que @Adnan a suggéré fonctionne effectivement. Vous pouvez également supprimer les espaces autour =dans la définition de l.
Alex A.
@Adnan et Alex A. merci, j'ai édité le code.
Bob
Voici 257 octets pour la même approche, plus un environnement de test en ligne.
Alex A.
Apporté quelques modifications - repl.it/BfuU . Vous pouvez réduire davantage d'octets en choisissant un format de sortie différent. Cette solution ne fonctionne que sur python 3 btw ( 4A2=2 4B3=1).
Nabb du
4

JavaScript (ES6), 213 208 octets

f=(l,s="+-*/",p="",r)=>s?[...s].map(o=>r=f(l,s[g="replace"](o,""),p+o)||r)&&r:l.split` `.every(x=>(q=x.split`=`)[1]==eval(q[0][g](/[A-D]/g,m=>p[(a="ABCD").search(m)])))&&a[g](/./g,(c,i)=>l.match(c)?c+p[i]:"")

Explication

L'entrée et la sortie sont des chaînes.

Définit une fonction fqui se double d'une fonction récursive pour générer toutes les permutations des opérateurs et teste les permutations complètes avec les équations d'entrée à l'aide eval.

f=(
  l,                          // l = input expression string
  s="+-*/",                   // s = remaining operators
  p="",                       // p = current permutation of operators
  r                           // r is here so it is defined locally
)=>
  s?                          // if there are remaining operators
    [...s].map(o=>            // add each operator o
      r=f(
        l,
        s[g="replace"](o,""), // remove it from the list of remaining operators
        p+o                   // add it to the permutation
      )
        ||r                   // r = the output of any permutation (if it has output)
    )
    &&r                       // return r
  :                           // else if there are no remaining operators
    l.split` `.every(x=>      // for each expression
      (q=x.split`=`)          // q = [ equation, result ]
      [1]==eval(              // if the results is equal to the eval result

        // Replace each letter with the current permutation
        q[0][g](/[A-D]/g,m=>p[(a="ABCD").search(m)])
      )
    )

    // If all results matched, add permutation symbols to present characters and return
    &&a[g](/./g,(c,i)=>l.match(c)?c+p[i]:"")

Tester

Le test n'utilise pas d'arguments par défaut pour la compatibilité du navigateur.

user81655
la source