Decifrar os símbolos matemáticos

13

Se você leu o livro Contato de Carl Sagan, esse desafio pode lhe parecer familiar.


Dada a entrada de um conjunto de equações matemáticas que consiste em um número, um operador desconhecido, outro número e um resultado, deduza quais operadores representam adição, subtração, multiplicação ou divisão.

Cada equação de entrada sempre consistirá em

  • um número inteiro não negativo
  • uma das cartas A, B, C, ouD
  • outro inteiro não negativo
  • o personagem =
  • um número inteiro não negativo final

concatenados juntos. Por exemplo, uma entrada possível é 1A2=3, da qual você pode deduzir que Arepresenta adição. Cada um dos números inteiros irá satisfazer 0 ≤ x ≤ 1,000.

No entanto, nem sempre é tão simples assim. É possível que exista ambiguidade entre:

  • 5A0=5: adição subtração
  • 1A1=1: multiplicação / divisão
  • 0A5=0: multiplicação / divisão
  • 2A2=4: adição / multiplicação
  • 4A2=2: subtração / divisão
  • 0A0=0: adição / subtração / multiplicação

e assim por diante. O desafio é usar essa capacidade para restringir as opções, combinadas com o processo de eliminação, para descobrir qual operador cada letra representa. (Sempre haverá pelo menos uma equação de entrada e sempre será possível corresponder inequivocamente a cada letra usada na entrada com um único operador.)

Por exemplo, digamos que a entrada seja as seguintes equações:

  • 0A0=0: reduz A a adição, subtração ou multiplicação (não é possível dividir por 0).
  • 10B0=10: B deve ser adição ou subtração.
  • 5C5=10: C é obviamente adição, que faz subtração B, que faz multiplicação A.

Portanto, a saída para essas equações de entrada deve corresponder Aa *, B com -e Ccom +.

A entrada pode ser fornecida como uma única string delimitada por espaço em branco / vírgula ou uma matriz de strings, cada uma representando uma equação. A saída pode ser uma única string ( "A*B-C+"), uma matriz ( ["A*", "B-", "C+"]) ou uma matriz 2D do tipo dicionário / ditado ( {"A": "*", ...}ou [["A", "*"], ...]).

Você pode assumir que um número nunca será dividido por outro número pelo qual não é divisível (portanto, não é necessário se preocupar se a divisão deve ser ponto flutuante ou truncado).

Como esse é o , o código mais curto em bytes vence.

Casos de teste:

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/
Maçaneta da porta
fonte
1
Estamos fazendo divisão inteira (truncada)?
Martin Ender
@ MartinBüttner Você pode assumir que nunca haverá divisão por um número que não resulte em um número inteiro. (Editado em questão.)
Maçaneta da porta
Podemos produzir como um dicionário?
precisa saber é o seguinte
@ThomasKwa Claro, um dicionário também é uma saída aceitável.
Maçaneta
A maioria dos exemplos é inconsistente com " sempre será possível identificar de forma inequívoca e inequívoca qual letra representa qual operador ", embora sejam consistentes com " sempre será possível identificar inequivocamente qual operador é representado por cada letra usada no entrada ".
Peter Taylor

Respostas:

9

MATL , 53 bytes

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

Usa a versão atual (10.1.0)

EDIT (12 de junho de 2016): para se adaptar às mudanças no idioma, substitua Y}por ge 1L3$)por Y). O link abaixo incorpora essas modificações

Experimente online!

Explicação

Isso testa todas as permutações possíveis dos quatro operadores em um loop até que uma permutação torne todas as equações verdadeiras.

Para testar se as equações são verdadeiras, é aplicada uma regex para substituir as quatro letras pelos operadores (na ordem ditada pela permutação atual) e a sequência é convertida em números (avaliados). Isso fornece uma matriz com tantos números quanto equações, na qual as equações verdadeiras se tornam 1e as equações falsas se tornam 0. Se esse vetor contiver apenas 1valores, estamos prontos.

A solução encontrada atribui operadores às quatro letras, mas nem todas necessariamente aparecem na entrada. Portanto, é feito um teste final para descartar as letras não usadas (e seus operadores correspondentes).

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
fonte
6

Python, 278 caracteres

Minha primeira resposta no código de golfe ...

É apenas uma função que implementa um algoritmo de força bruta, que você chama de argumento como sequência de equações.

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
Prumo
fonte
Não tenho certeza se funciona, mas você pode substituir ["A","B","C","D"]por list("ABCD")?
Adnan
O que o @Adnan sugeriu realmente funciona. Você também pode remover os espaços ao redor =na definição de l.
Alex A.
@ Adnan e Alex A. obrigado, editei o código.
Bob
Aqui estão 257 bytes para a mesma abordagem, além de um ambiente de teste online.
Alex A.
Fez algumas alterações - repl.it/BfuU . Você pode cortar muito mais bytes escolhendo um formato de saída diferente. Esta solução funciona apenas em python 3 btw ( 4A2=2 4B3=1).
Nabb 22/01/16
4

JavaScript (ES6), 213208 bytes

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]:"")

Explicação

Entrada e saída são strings.

Define uma função fque funciona como uma função recursiva para gerar todas as permutações dos operadores e testa permutações completas com as equações de entrada usando 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]:"")

Teste

O teste não usa argumentos padrão para compatibilidade do navegador.

user81655
fonte