Расшифровать математические символы


13

Если вы читали книгу « Контакт Карла Сагана», этот вызов может показаться вам знакомым.


Учитывая ввод набора математических уравнений, состоящих из числа, неизвестного оператора, другого числа и результата, определите, какие операторы представляют сложение, вычитание, умножение или деление.

Каждое входное уравнение всегда будет состоять из

  • неотрицательное целое число
  • одна из букв A, B, CилиD
  • другое неотрицательное целое число
  • персонаж =
  • окончательное неотрицательное целое число

соединены вместе. Например, возможный ввод 1A2=3, из которого вы можете вывести, что Aпредставляет сложение. Каждое из целых чисел будет удовлетворять 0 ≤ x ≤ 1,000.

Однако это не всегда так просто. Возможна неясность между:

  • 5A0=5: сложение / вычитание
  • 1A1=1: умножение / деление
  • 0A5=0: умножение / деление
  • 2A2=4: сложение / умножение
  • 4A2=2: вычитание / деление
  • 0A0=0: сложение / вычитание / умножение

и так далее. Задача состоит в том, чтобы использовать эту возможность, чтобы сузить выбор в сочетании с процессом исключения, чтобы выяснить, какого оператора представляет каждая буква. (Всегда будет хотя бы одно входное уравнение, и всегда можно будет однозначно, однозначно сопоставить каждую букву, использованную во вводе, с одним оператором.)

Например, предположим, что входными данными являются следующие уравнения:

  • 0A0=0: это сужает A до сложения, вычитания или умножения (не может делиться на 0).
  • 10B0=10: B должно быть либо сложением, либо вычитанием.
  • 5C5=10: C, очевидно, сложение, которое делает B вычитанием, которое делает A умножением.

Следовательно, выходные данные для этих входных уравнений должны совпадать Aс *, B с -и Cс +.

Входные данные могут быть представлены в виде одной строки с пробелами / запятыми или массива строк, каждая из которых представляет одно уравнение. Выходными данными может быть либо одиночная строка ( "A*B-C+"), array ( ["A*", "B-", "C+"]), либо словарь / dict-подобный 2D-массив ( {"A": "*", ...}или [["A", "*"], ...]).

Вы можете предположить, что число никогда не будет разделено на другое число, на которое оно не делится (поэтому вам не нужно беспокоиться о том, должно ли деление быть плавающим или усеченным).

Поскольку это , выигрывает самый короткий код в байтах.

Тестовые случаи:

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/

1
Делаем ли мы (усеченное) целочисленное деление?
Мартин Эндер

@ MartinBüttner Вы можете предположить, что никогда не будет деления на число, которое не приводит к целому числу. (Отредактировано под вопросом.)
Ручка двери

Можем ли мы вывести в виде словаря?
lirtosiast

@ThomasKwa Конечно, словарь также приемлемый вывод.
Дверная ручка

Большинство примеров не соответствуют « всегда будет возможно однозначно, однозначно определить, какая буква обозначает какой оператор », хотя они согласуются с « всегда можно однозначно определить, какой оператор представлен каждой буквой, используемой в вход ".
Питер Тейлор

Ответы:


9

MATL , 53 байта

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

Использует текущую версию (10.1.0)

РЕДАКТИРОВАТЬ (12 июня 2016 г.): чтобы адаптироваться к изменениям языка, заменить Y}на gи 1L3$)на Y). Ссылка ниже включает эти модификации

Попробуйте онлайн!

объяснение

Это проверяет все возможные перестановки четырех операторов в цикле, пока одна перестановка не сделает все уравнения верными.

Чтобы проверить, являются ли уравнения истинными, применяется регулярное выражение для замены четырех букв операторами (в порядке, определяемом текущей перестановкой), и строка преобразуется в числа (оцененные). Это дает массив с таким количеством чисел, что и уравнения, в которых становятся истинные 1уравнения и ложные уравнения 0. Если этот вектор содержит только 1значения, все готово.

Найденное решение назначает операторы четырем буквам, но не все из них обязательно появляются во входных данных. Таким образом, последний тест проводится для удаления неиспользуемых букв (и их соответствующих операторов).

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

6

Python, 278 символов

Мой первый ответ по коду гольфа ...

Это просто функция, реализующая алгоритм перебора, вы называете его передачей в качестве аргумента строку уравнений.

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

Я не уверен, что это работает, но вы можете заменить ["A","B","C","D"]на list("ABCD")?
Аднан

То, что предложил @Аднан, действительно работает. Вы также можете удалить пробелы вокруг =в определении l.
Алекс А.

@ Adnan и Alex A. спасибо, я редактировал код.
Боб

Вот 257 байт для того же подхода плюс среда онлайн-тестирования.
Алекс А.

Сделал некоторые изменения - repl.it/BfuU . Вы можете сократить больше байтов, выбрав другой формат вывода. Это решение работает только на python 3 btw ( 4A2=2 4B3=1).
Набб

4

JavaScript (ES6), 213 208 байт

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

объяснение

Вход и выход являются строками.

Определяет функцию, fкоторая удваивается как рекурсивная функция для генерации всех перестановок операторов и тестирует полные перестановки с использованием входных уравнений 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]:"")

Тестовое задание

Тест не использует аргументы по умолчанию для совместимости браузера.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.