証明2 + 2 = 2 * 2(および同様)


12

出力のような、そのような声明の完全な正式なパッと消える1+2=32+2=2*(1+1)など

はじめに

Peano Arithmeticを知っている場合は、おそらくこのセクションをスキップできます。

自然数の定義方法は次のとおりです。

(Axiom 1) 0 is a number
(Axiom 2) If `x` is a number, the `S(x)`, the successor of `x`, is a number.

したがって、たとえばS(S(S(0)))数字です。

コードで同等の表現を使用できます。たとえば、これらはすべて有効です。

0    ""    0           ()       !
1    "#"   S(0)        (())     !'
2    "##"  S(S(0))     ((()))   !''
3    "###" S(S(S(0)))  (((()))) !'''
...
etc

ルールを拡張して、次のように追加を定義できます。

(Rule 1) X+0 = X
(Rule 2) X+S(Y)=S(X)+Y

これにより、次のように2 + 2 = 4を証明できます。

         S(S(0)) + S(S(0)) = 2 + 2
[Rule 2 with X=S(S(0)), Y=S(0)]
         S(S(S(0))) + S(0) = 3 + 1
[Rule 2 with X=S(S(S(0))), Y=0]
         S(S(S(S(0)))) + 0 = 4 + 0
[Rule 1 with X=S(S(S(S(0))))
         S(S(S(S(0))))     = 4

これらの規則を拡張して、次のように乗算を定義できます。

(Rule 3) X*0 = 0
(Rule 4) X*S(Y) = (X*Y) + X

これを可能にするために、括弧の構造的な役割を定義する必要があります。

(Axiom 3) If X is a number, (X) is the same number.

加算演算子と乗算演算子は厳密にバイナリであり、括弧は常に明示的でなければなりません。A+B+C明確に定義されていませんが(A+B)+C、ありA+(B+C)ます。

乗算についての定理を証明するのに十分です:2 + 2 = 2 * 2

2 + 2
(2) + 2
(0 + 2) + 2
((0*2) + 2) + 2
(1*2) + 2
2*2

必要条件

次のようなリスト式である証明A=B

  • 最初のものですA
  • 最後はB
  • リスト内の最初の式を除く各式は、いずれかのルールの下で変換することにより、前の式から取得できます。

プログラムは、入力として2つの有効な式を取ります。各式には、上記で定義した数値、加算、乗算、および括弧が含まれます。

このような証明が存在する場合、プログラムは、2つの式が等しいことを証明する上記のリストを出力します。

2つの式が等しくない場合、プログラムは何も出力しません。

証明または反証は、有限数のステップで常に可能です。これは、各式を単一の数に減らし、これらの数の平等性を簡単にテストできるためです。

入力式が有効でない場合は、あなたのプログラムは、例外をスローし、エラーを印刷、またはその他のいくつかの観察可能な行動生成、エラーで終了しなければならない(例えばアンバランス括弧は、非数値、または非バイナリの演算子が含まれています)とは区別されます入力は有効だが、等しくない場合

要約すると、許容可能な入力の通常の出力は、入力を含む等しい数のリストであり、次の規則によって生成されます。

(Axiom 1) 0 is a number
(Axiom 2) If `x` is a number, the `S(x)`, the successor of `x`, is a number.
(Axiom 3) If X is a number, (X) is the same number

(Rule 1) X+0 = X
(Rule 2) X+S(Y)=S(X)+Y
(Rule 3) X*0 = 0
(Rule 4) X*S(Y) = (X*Y) + X
(Rule 5) X = (X)              (Axiom 3 expressed as a transformation rule.)

入力および出力の数の任意の適切な表現が許可されている、例えば0=""=()3="###"=(((())))などの空白は無関係です。

もちろん、ルールはどちらの方向にも適用できます。プログラムは、使用されるルールを出力する必要はなく、前の式に対するアクションによって生成された式のみを出力します。

最短のコードが優先されます。


回答:


5

Perl、166 + 1バイト

-p(1バイトのペナルティ)で実行します。

$r='\((S*)';(@b,@a)=@a;push@a,$_ while+s/\+S/S+/||s/$r\+\)/$1/||s/$r\*\)//||s/$r\*S(S*)/(($1*$2)+$1/||s/$r\)/$1/;$\.=/[^S]./s;$_=$b[-1]eq$a[-1]?join'',@b,reverse@a:""

より読みやすい:

                           #暗黙:入力行を$ _に読み込む
                           #改行をオンのままにします
$ r = '\((S *)';#この正規表現のフラグメントを頻繁に使用します。
(@ b、@ a)= @a; #@bを@aに、@ aを空に設定
@a、$ _をプッシュする#ループを回るたびに、$ _を@aに追加する
+ s / \ + S / S + / || #ルール2:「+ S」を「S +」に変更
s / $ r \ + \)/ $ 1 / || #ルール1:「(X + 0)」を「X」に変更
s / $ r \ * \)// || #ルール3:「(X * 0)」を「」に変更
s / $ r \ * S(S *)/(($ 1 * $ 2)+ $ 1 / ||#ルール4:「(X * Y」を「((X * Y)+ X」に変更
s / $ r \)/ $ 1 /; #ルール5:「(X)を「X」に変更
$ \。= / [^ S] ./ s; #次の場合、改行文字に1を追加します
                           #非Sに続いて何かが表示される
$ _ = $ b [-1] eq $ a [-1]?#@bと@aが同じ方法で終了する場合
  join ''、@ b、reverse @ a#次に$ _は@bになり、その後に(@a後方)
  : ""#それ以外の場合は空の$ _
                           #暗黙的:出力$ _

入力形式は、単項式の数値をの文字列として表現しS、別々の行に2つの入力を必要とします(それぞれに改行が続き、両方が表示された後にEOFが続きます)。私は、括弧が文字通りで( )あり、加算/乗算が文字通りでなければならないことを要求すると質問を解釈しました+ *。別の選択を許可されている場合は、エスケープを少なくすることで数バイトを節約できます。

アルゴリズムは実際に、入力の最初の行を空の行と比較し、2番目の行を最初の行と比較し、3番目の行と2番目の行を比較します。これは質問の要件を満たします。実行例を次に示します。

私の入力:

(SS + SS)
(SS * SS)

プログラム出力:

(SSS + S)
(SSSS +)
SSSS
SSSS
(SSSS +)
((SS +)SS +)
(((SS *)SS +)SS +)
(((SS *)S + S)SS +)
(((SS *)+ SS)SS +)
((SS * S)SS +)
((SS * S)S + S)
((SS * S)+ SS)

SSSS真ん中に複製されているのは迷惑ですが、仕様に違反していないと判断し、残しておくバイト数が少なくなっています。

無効な入力では1、改行文字に追加するため1、出力の最後に散らばったストレイが発生します。


echo -e "((SS+)+(S+S))\nSS*SS" | perl -p /tmp/x.pl出力1
spraff

それは正しいです、あなたは2行目の括弧が欠けています(それは言うべきです(SS*SS))。「加算演算子と乗算演算子は厳密にバイナリであり、括弧は常に明示的でなければなりません。」
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.