数学記号を解読する


13

Carl Saganの Contact」という本を読んだことがあれば、この課題はおなじみかもしれません。


数、未知の演算子、別の数、および結果で構成される一連の数学方程式の入力が与えられると、どの演算子が加算、減算、乗算、または除算を表すかを推測します。

各入力方程式は常に

  • 負でない整数
  • 文字の1 ABC、またはD
  • 別の非負整数
  • キャラクター =
  • 最終的な非負整数

連結されます。たとえば、可能な入力はであり1A2=3、そこからA加算を表すと推定できます。各整数はを満たし0 ≤ x ≤ 1,000ます。

ただし、必ずしもそれほど単純ではありません。次の間にあいまいさが存在する可能性があります。

  • 5A0=5:加算/減算
  • 1A1=1:乗算/除算
  • 0A5=0:乗算/除算
  • 2A2=4:加算/乗算
  • 4A2=2:減算/除算
  • 0A0=0:加算/減算/乗算

等々。課題は、この機能を使用して選択肢を絞り込み、消去プロセスと組み合わせて、各文字が表す演算子を把握することです。(常に少なくとも1つの入力方程式があり、入力で使用される各文字を1つの演算子で明確に一意に一致させることが常に可能です。)

たとえば、入力が次の方程式であるとします。

  • 0A0=0:これは、Aを加算、減算、または乗算に絞り込みます(0で除算できません)。
  • 10B0=10:Bは加算または減算のいずれかでなければなりません。
  • 5C5=10:Cは明らかに加算であり、B減算を行い、A乗算を行います。

したがって、これらの入力方程式の出力は次と一致Aする必要があります。*B-、とCを有します+

入力は、それぞれが1つの方程式を表す、単一の空白/コンマ区切りの文字列または文字列の配列として指定できます。出力は単一の文字列("A*B-C+")、配列(["A*", "B-", "C+"])、または辞書/辞書のような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整数にならない数値による除算は決してないと仮定できます。(質問に編集。)
ドアノブ

辞書として出力できますか?
リルトシアスト

@ThomasKwa確かに、辞書も許容可能な出力です。
ドアノブ

例のほとんどは、「と矛盾することは常に明確に、一意にそのオペレータを表している文字を識別することが可能となり、彼らは"と一致しているが、」常に明確で使用される各文字で表されているオペレータ識別することが可能となります入力」。
ピーターテイラー

回答:


9

MATL、53バ​​イト

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

現在のバージョン(10.1.0)を使用します

EDIT(2016年6月12日):置き換え、言語の変化に適応するY}ことにより、gおよび1L3$)Y)。以下のリンクには、これらの変更が組み込まれています

オンラインでお試しください!

説明

これは、1つの順列がすべての方程式を真にするまで、ループ内の4つの演算子のすべての可能な順列をテストします。

方程式が真であるかどうかをテストするために、正規表現が適用されて、4文字が演算子に置き換えられ(現在の順列によって指示された順序で)、文字列が数値に変換されます(評価)。これにより、式と同じ数の配列が得られます。この式では、真の方程式がになり1、偽の方程式がになり0ます。このベクトルのみが含まれている場合1値場合は、完了です。

見つかった解決策では、演算子を4文字に割り当てていますが、必ずしもすべてが入力に表示されるわけではありません。したがって、使用されていない文字(および一致する演算子)を破棄する最終テストが行​​われます。

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")か?
アドナン

@Adnanが提案したことは実際に機能します。=の定義で周囲のスペースを削除することもできますl
アレックスA.

@AdnanとAlex A.ありがとう、コードを編集しました。
ボブ

同じアプローチの257バイトと、オンラインテスト環境を次に示します。
アレックスA.

いくつかの変更を行った- 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]:"")

テスト

テストでは、ブラウザの互換性のためにデフォルト引数を使用しません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.