Розшифруйте математичні символи


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+"), масив ( ["A*", "B-", "C+"]), або словник / двосхилий масив ( {"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)

EDIT (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

Пітон, 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")?
Аднан

Те, що запропонував @Adnan, справді працює. Ви також можете видалити пробіли навколо =у визначенні 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.