Kanıtlamak 2 + 2 = 2 * 2 (ve benzeri)


12

Çıktı gibi bu tür ifadelerin tam biçimsel puf 1+2=3, 2+2=2*(1+1)vb

Introuction

Peano Aritmetiği biliyorsanız, muhtemelen bu bölümü atlayabilirsiniz.

Doğal Sayıları şu şekilde tanımlıyoruz:

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

Dolayısıyla, örneğin S(S(S(0)))bir sayıdır.

Kodunuzdaki herhangi bir eşdeğer temsili kullanabilirsiniz. Örneğin, bunların tümü geçerlidir:

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

Eklemeyi aşağıdaki gibi tanımlamak için kuralları genişletebiliriz.

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

Bu şekilde 2 + 2 = 4'ü şu şekilde kanıtlayabiliriz:

         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

Bu kuralları çarpımı şu şekilde tanımlayabiliriz:

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

Buna izin vermekle birlikte, parantezlerin yapısal rolünü tanımlamamız gerekir.

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

Toplama ve çarpma işleçleri kesinlikle ikilidir ve parantezler her zaman açık olmalıdır. A+B+Ciyi tanımlanmamıştır (A+B)+Cve A+(B+C)vardır.

Misal

Şimdi çarpma hakkında bir teorem kanıtlamak için yeterli var: 2 + 2 = 2 * 2

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

Gereksinimler

Bir kanıtıA=B bir liste ifadeler şekildedir:

  • birincisi A,
  • sonuncusu B, ve
  • listedeki her ifade, birinciden ayrı olarak, öncekinden kurallardan biri altında dönüştürülerek elde edilebilir.

Programınız girdi olarak iki geçerli ifade alacaktır , her ifade yukarıda tanımlandığı gibi sayılar, toplama, çarpma ve parantez içerir.

Programınız, böyle bir kanıt varsa, iki ifadenin eşit olduğuna dair bir kanıt, yukarıda tanımlandığı gibi bir liste çıkarır.

İki ifade eşit değilse, programınız hiçbir şey vermez.

Kanıtlama veya çürütme her zaman sonlu sayıda adımda mümkündür, çünkü her ifade tek bir sayıya indirgenebilir ve bu sayılar önemsiz bir şekilde eşitlik açısından test edilebilir.

Giriş ifadeleri geçerli değilse (örn. Dengesiz parantezler, sayı olmayan veya ikili olmayan işleçler içeriyorsa), programınız hatadan çıkmalı, bir istisna atmalı, bir hata yazmalı veya başka bir şekilde gözlemlenebilir davranış üretmelidir . girişlerin geçerli olduğu ancak eşit olmadığı durumlarda .

Özet olarak, kabul edilebilir girdiler için normal çıktı, aşağıdaki kurallar tarafından üretilen girdiler dahil olmak üzere eşit sayıların bir listesidir.

(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.)

Giriş ve çıkış sayıların herhangi bir uygun temsili örneğin, izin verilir 0=""=(), 3="###"=(((())))vs Boşluk önemsizdir.

Kurallar elbette her iki yönde de uygulanabilir. Programınızın hangi kuralın kullanıldığını, yalnızca önceki ifade üzerindeki eylemiyle üretilen ifadeyi çıkarması gerekmez.

En kısa kod kazanır.


Yanıtlar:


5

Perl, 166 + 1 bayt

İle koş -p(1 byte ceza).

$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:""

Daha okunabilir:

                           # implicit: $ _ içine bir girdi satırı okuyun
                           # satır sonunu
$ r = '\ ((S *)'; # bu normal ifade parçasını çok kullanıyoruz, çarpanlarına ayırıyoruz
(@b, @) = @; # @b'yi @a, @a'yı boş olarak ayarlayın
@a'yı itin, $ _ ise # döngü boyunca her seferinde @a'ya $ _ ekleyin
+ S / \ + S / S + / || # kural 2: "+ S" yi "S +" olarak değiştirin
s / $ r \ + \) / 1 $ / || # kural 1: "(X + 0)" değerini "X" olarak değiştirin
s / $ r \ * \) // || # kural 3: "(X * 0)" ifadesini "" olarak değiştirin
s / $ r \ * S (S *) / (($ 1 * $ 2) + $ 1 / || # kural 4: "(X * Y" yerine "((X * Y) + X")
s / $ r \) / $ 1 /; # kural 5: "(X) 'i" X "olarak değiştirin
$ \ = / [^ S] ./ s.; # satırsonu karakterine 1 eklersek
                           # S olmayan herhangi bir şeyi ve ardından herhangi bir şeyi görün
$ _ = $ B [-1] eşdeğer $ a [-1]? # @b ve @a aynı şekilde biterse
  '', @ b, ters @ a # sonra $ _ @b olur ve ardından (@a geriye doğru)
  : "" # aksi takdirde boş $ _
                           # örtük: çıktı $ _

Girdi biçimi, sayıları dizge olarak tekli olarak ifade eder Sve ayrı satırlarda iki giriş gerektirir (her biri bir satırsonu ve her ikisinden sonra bir EOF). Soruyu, parantezlerin tam anlamıyla ( )ve toplama / çarpma işlemlerinin tam anlamıyla yapılması gerektiğini + *; Farklı seçimler yapmama izin verilirse birkaç baytı daha az kaçarak kaydedebilirim.

Algoritma aslında ilk girdi satırını boş bir satırla, ikincisi birinciyle, üçüncüsünü ikincisiyle vs. karşılaştırır. Bu, sorunun gerekliliklerini yerine getirir. İşte bir örnek çalışma:

Girişim:

(SS + SS)
(SS * SS)

Program çıktısı:

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

SSSSOrtadaki kopya can sıkıcı ama şartnameyi ihlal etmediğine karar verdim ve bırakmak için daha az bayt var.

Geçersiz girişte, 1yeni satır karakterine ekledim, böylece 1çıktının sonunda başıboş serpilirsiniz.


echo -e "((SS+)+(S+S))\nSS*SS" | perl -p /tmp/x.plçıktılar 1.
16:46 spraff

Bu doğru, ikinci satırdaki parantezleri kaçırıyorsunuz (ki bu söylenmelidir (SS*SS)). "Toplama ve çarpma işleçleri kesinlikle ikili ve parantezler her zaman açık olmalıdır."
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.