พิสูจน์ 2 + 2 = 2 * 2 (และคล้ายกัน)


12

เอาท์พุทกะเทยอย่างเป็นทางการเต็มรูปแบบของงบดังกล่าวเช่น1+2=3, 2+2=2*(1+1)ฯลฯ

Introuction

หากคุณรู้เลขคณิตของ Peano คุณสามารถข้ามส่วนนี้ได้

นี่คือวิธีที่เรากำหนดหมายเลขธรรมชาติ:

(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และ
  • แต่ละนิพจน์ในรายการนอกเหนือจากตอนแรกสามารถรับได้จากก่อนหน้าโดยเปลี่ยนภายใต้กฎข้อใดข้อหนึ่ง

โปรแกรมของคุณจะใช้สองนิพจน์ที่ถูกต้องเป็นอินพุตแต่ละนิพจน์ประกอบด้วยตัวเลขการเพิ่มการคูณและวงเล็บตามที่กำหนดไว้ด้านบน

โปรแกรมของคุณจะแสดงผลการพิสูจน์รายการตามที่กำหนดไว้ด้านบนว่าทั้งสองนิพจน์มีค่าเท่ากันหากมีหลักฐานดังกล่าวอยู่

หากทั้งสองนิพจน์ไม่เท่ากันโปรแกรมของคุณจะไม่แสดงผลใด ๆ

การพิสูจน์หรือหักล้างเป็นไปได้เสมอในจำนวนขั้นตอนที่ จำกัด เนื่องจากแต่ละนิพจน์สามารถลดลงเป็นจำนวนเดียวและตัวเลขเหล่านี้สามารถทดสอบได้เล็กน้อยเพื่อความเท่าเทียมกัน

หากการแสดงออกของการป้อนข้อมูลไม่ถูกต้อง (เช่นวงเล็บที่ไม่สมดุลมีหมายเลขที่ไม่ใช่หรือตัวดำเนินการที่ไม่ใช่ไบนารี) โปรแกรมของคุณควรออกโดยมีข้อผิดพลาดโยนข้อผิดพลาดพิมพ์ข้อผิดพลาดหรือสร้างพฤติกรรมที่สังเกตได้ซึ่งแตกต่างจาก ในกรณีที่ปัจจัยการผลิตที่ถูกต้อง แต่ที่ไม่เท่ากัน

โดยสรุปเอาต์พุตปกติสำหรับอินพุตที่ยอมรับได้คือรายการของตัวเลขที่เท่ากันรวมถึงอินพุตซึ่งสร้างโดยกฎต่อไปนี้

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

อ่านเพิ่มเติมได้:

                           # implicit: อ่านบรรทัดอินพุตเป็น $ _
                           # เราปล่อยบรรทัดใหม่ไว้
$ r = '\ ((S *)'; # เราใช้แฟรกเมนต์ regex จำนวนมากตัดออก
(@b, @a) = @a; # set @b เป็น @a, @a ว่างเปล่า
กด @a, $ _ ขณะที่ # ทุกครั้งที่วนลูปเพิ่มผนวก $ _ to @
+ S / \ + S / S + / || # rule 2: เปลี่ยน "+ S" เป็น "S +"
s / $ r \ + \) / $ 1 / || # rule 1: เปลี่ยน "(X + 0)" เป็น "X"
s / $ r \ * \) // || # rule 3: เปลี่ยน "(X * 0)" เป็น ""
s / $ r \ * S (S *) / (($ 1 * $ 2) + $ 1 / || # กฎ 4: เปลี่ยน "(X * Y" เป็น "((X * Y) + X"
s / $ r \) / $ 1 /; # rule 5: เปลี่ยน "(X) เป็น" X "
$ \ = / [^ S] ./ s. # ต่อท้าย 1 กับอักขระขึ้นบรรทัดใหม่ถ้าเรา
                           # ดู non-S ใด ๆ ก็ตามตามด้วยอะไรก็ได้
_ $ = $ ข [-1] EQ $ a [-1]? # if @b และ @a สิ้นสุดด้วยวิธีเดียวกัน
  เข้าร่วม '', @ b, กลับ @ a # จากนั้น $ _ กลายเป็น @b ตามด้วย (@a ข้างหลัง)
  : "" # เว้นว่าง $ _
                           # implicit: output $ _

รูปแบบการป้อนข้อมูลแสดงตัวเลขในเอกภาพว่าเป็นสายอักขระSและต้องการอินพุตทั้งสองในบรรทัดแยกกัน (แต่ละบรรทัดตามด้วยขึ้นบรรทัดใหม่และ EOF หลังจากเห็นทั้งคู่) ผมตีความคำถามเป็นต้องว่าวงเล็บควรจะเป็นตัวอักษร( )และการเพิ่ม / คูณควรจะเป็นตัวอักษร+ *; ฉันสามารถบันทึกไม่กี่ไบต์ผ่านการหลบหนีน้อยลงถ้าฉันได้รับอนุญาตให้เลือกที่แตกต่างกัน

อัลกอริทึมจะเปรียบเทียบบรรทัดแรกของอินพุตกับบรรทัดว่างที่สองกับที่หนึ่งที่สามกับที่สองและอื่น ๆ สิ่งนี้ตอบสนองความต้องการของคำถาม นี่คือตัวอย่างการเรียกใช้:

อินพุตของฉัน:

(เอสเอสเอสเอส +)
(เอสเอสเอสเอส *)

ผลลัพธ์ของโปรแกรม:

(SSS + S)
(SSSS +)
SSSS
SSSS
(SSSS +)
((SS +) เอสเอส +)
(((SS *) เอสเอส +) เอสเอส +)
(((SS *) S + S) เอสเอส +)
(((SS *) + SS) เอสเอส +)
((SS * S) เอสเอส +)
((SS * S) S + S)
((SS * S) + SS)

การทำซ้ำSSSSตรงกลางนั้นน่ารำคาญ แต่ฉันคิดว่ามันไม่ได้ละเมิดสเปคและน้อยกว่าที่จะปล่อยไว้

ในการป้อนข้อมูลที่ไม่ถูกต้องฉันผนวก1กับอักขระขึ้นบรรทัดใหม่เพื่อให้คุณได้รับการหลงทาง1ในตอนท้ายของผลลัพธ์


echo -e "((SS+)+(S+S))\nSS*SS" | perl -p /tmp/x.pl1เอาท์พุท
spraff

ถูกต้องคุณไม่มีวงเล็บเหลี่ยมในบรรทัดที่สอง (ซึ่งควรจะพูด(SS*SS)) "ตัวดำเนินการการบวกและการคูณเป็นไบนารีอย่างเคร่งครัดและวงเล็บต้องชัดเจน"
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.