อักขระน้อยที่สุด (ชัดเจน) สำหรับทัวริงครบถ้วน


107

สรุป:

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

ท้าทาย:

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


ตัวอย่าง:

  • JavaScript: +!()[]( http://www.jsfuck.com )

  • Brainfuck: +<>[](ถือว่าเป็นขนาดเซลล์ห่อ)

  • Python 2: ()+1cehrx(ทำจากสคริปต์เหมือนexec(chr(1+1+1)+chr(1)))

เกณฑ์การให้คะแนน:

ความท้าทายนี้จะได้คะแนนในตัวละครไม่ไบต์ ตัวอย่างเช่นคะแนนสำหรับตัวอย่างคือ 6, 5 และ 9


หมายเหตุ:

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

  • แม้ว่าคุณสามารถทำได้โปรดอย่าโพสต์คำตอบโดยไม่ลดจำนวนอักขระที่ใช้ ตัวอย่าง: Brainfuck ที่มี 8 ตัวอักษร (เนื่องจากตัวละครอื่น ๆ ทุกตัวจะแสดงความคิดเห็นเป็นค่าเริ่มต้น)

  • คุณต้องให้คำอธิบายสั้น ๆ ว่าทำไมชุดย่อยของคุณถึง Turing-Complete


90
เอกภาพ 1 ตัวละคร ถอนหายใจ
เดนนิส

4
@Dennis มันไม่ได้แตกต่างจาก Jelly หรือ 05AB1E ที่มีอยู่แล้วภายในสำหรับปัญหาทฤษฎีจำนวนที่น่าสนใจ ความท้าทายนี้ยังคงดูเหมือนว่าเป็นปัญหาการเพิ่มประสิทธิภาพที่น่าสนใจและไม่สำคัญในภาษาใด ๆ ที่ไม่ได้รับการออกแบบมาให้เป็นผ้าใบกันน้ำ
Martin Ender

7
@MartinEnder ฉันสนใจที่จะเห็นคำตอบในภาษาเช่น Java หรือ C. เป็นพิเศษ
Julian Lachniet

9
กรุณาอย่าโพสต์โซลูชั่นใน esolangs ที่การแก้ปัญหาเป็นตัวละครที่ถูกต้องในภาษา มันไม่ได้น่าสนใจหรือฉลาด
Pavel

20
@Pavel ไม่น่าสนใจหรือฉลาดอาจหมายความว่าไม่ควรอัปโหลด แต่ไม่แน่นอนว่าไม่ควรโพสต์
Dennis

คำตอบ:


77

Haskell, 4 ตัวอักษร

()=;

เมื่อ()=เราสามารถกำหนด S, K และ I ได้คำจำกัดความต้องถูกคั่นด้วย;NL หรืออย่างใดอย่างหนึ่ง

เรากำหนด(==)เป็น S (บรรทัดที่สองแสดงรุ่นที่อ่านได้มากขึ้น):

((=====)==(======))(=======)=(=====)(=======)((======)(=======))
( a     == b      ) c       = a      c       ( b       c       )

(===) ถาม:

(=====)===(======)=(=====)
 a     === b      = a

และ(====)ในขณะที่ฉัน:

(====)(=====)=(=====)
(====) a     = a 

โชคดี(==), (===), (====)ฯลฯ เป็นฟังก์ชั่น / ชื่อพารามิเตอร์ที่ถูกต้อง

@ @ ais523 ชี้ให้เห็นว่า SKI นั้นไม่เพียงพอในภาษาที่พิมพ์ออกมาอย่างรุนแรงเช่น Haskell ดังนั้นเราจำเป็นต้องเพิ่มผู้แก้ไข combpoint (=====):

(=====)(======)=(======)((=====)(======))
(=====) f      = f      ((=====) f      )

17
การก่อสร้างนี้ไม่สามารถใช้งานได้โดยตรง SKI ไม่ได้ทำให้ทัวริงสมบูรณ์ในภาษาที่พิมพ์อย่างยิ่งเช่น Haskell อย่างไรก็ตามฉันเชื่อว่าคุณสามารถใช้เทคนิคเดียวกันในการกำหนดfixและ SKI + fix นั้นก็กำลังทัวริงสมบูรณ์แม้จะเป็นภาษาที่พิมพ์อย่างรุนแรงก็ตาม

โอ้คุณจะนำหน้าคำจำกัดความเหล่านั้นที่จุดเริ่มต้นของแต่ละโปรแกรมหรือไม่
PyRulez

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

1
คุณควรเปลี่ยน(==)เพื่อไม่ให้ขัดแย้งกับโอเปอเรเตอร์ความเท่าเทียมเริ่มต้น
ภูมิใจ haskeller

@proudhaskeller: ใช่ถ้าคุณต้องการที่จะโปรแกรมมันจะดีกว่าที่จะเปลี่ยนชื่อ(==)แต่รหัสข้างต้นเป็นเพียงการพิสูจน์ความสมบูรณ์ทัวริง
nimi

61

JavaScript (ES6), 5 ตัวอักษร

ขอบคุณ @ETHproductions และ @ATaco ที่ให้ความช่วยเหลือ นี่เป็นโครงการกลุ่มและแม้ว่าความคิดดั้งเดิมเป็นของฉันรายละเอียดหลายอย่างเป็นของพวกเขา ดูการอภิปรายแชทที่นี้เซต JavaScript ได้รับการพัฒนาที่นี่

[]+=`

มันค่อนข้างดีเป็นที่ยอมรับว่าโปรแกรมใด ๆ Javascript สามารถเขียนด้วยตัวอักษร ( []()+!) แต่ 5 ตัวอักษรไม่เพียงพอ อย่างไรก็ตามนี่ไม่ใช่ความท้าทายเกี่ยวกับการเขียน JavaScript ตามอำเภอใจ มันเป็นความท้าทายเกี่ยวกับการเขียนภาษาทัวริงที่สมบูรณ์และการใช้ภาษาทัวริงที่สมบูรณ์ไม่จำเป็นต้องเข้าถึง DOM หรือแม้แต่ I / O แบบโต้ตอบมันกลายเป็นว่าเราสามารถเขียนโปรแกรมที่มีฟังก์ชั่นการใช้งานที่จำเป็นทั้งหมด แม้ไม่มีความสามารถในการเรียกใช้evalหรือเทียบเท่า

การเริ่มต้นขั้นพื้นฐาน

JavaScript เป็นมากมีความยืดหยุ่นกับประเภท ตัวอย่างเช่น[]อาร์เรย์ว่าง แต่+[]เป็น 0 และ[]+[]เป็นสตริงว่าง ยวดความจริงที่ว่าเราสามารถสร้าง 0 ด้วยชุดอักขระนี้ทำให้สามารถจำลองผลของวงเล็บสำหรับการจัดกลุ่ม สามารถเขียนเป็น(a) [a][+[]]เราสามารถใช้เคล็ดลับประเภทนี้เพื่อสร้างตัวละครต่าง ๆ โดยใช้เพียง+[]:

  • [][+[]]คือundefined(เป็นองค์ประกอบแรกของอาเรย์ที่ว่างเปล่า); ดังนั้น
  • []+[][+[]]คือ"undefined"(การทำให้เป็นสตริงของundefined); ดังนั้น
  • [[]+[][+[]]]คือ["undefined"](ห่อที่อยู่ในอาร์เรย์); ดังนั้น
  • [[]+[][+[]]][+[]]คือ"undefined"(องค์ประกอบแรก); ดังนั้น
  • [[]+[][+[]]][+[]][+[]]คือ"u"(ตัวอักษรตัวแรกของมัน)

uเป็นหนึ่งในตัวละครที่ง่ายที่สุดในการสร้าง แต่เทคนิคที่คล้ายคลึงกันให้เราสร้างช่วงของตัวละครอื่น ๆ การเชื่อมโยงเช่นเดียวกับก่อนทำให้เรามีรายชื่อต่อไปนี้ของตัวละครที่สามารถเข้าถึงได้ด้วย+[](นี่คือรายการเช่นเดียวกับ+[]()ไม่รวม,เพราะมันเป็นงานก่อสร้างที่ใช้วงเล็บเพื่อวัตถุประสงค์อื่นนอกเหนือจากการจัดกลุ่ม / ความสำคัญ a):

0123456789acdefinotuvyIN (){}.

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

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

object.property

แต่คุณสามารถเขียนแบบนี้ได้:

object["property"]

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

object["c"+"o"+"n"+"s"+"t"+"r"+"u"+"c"+"t"+"o"+"r"]

(ด้วยตัวอักษรที่สร้างขึ้นตามที่อธิบายไว้ข้างต้นรหัสได้อย่างรวดเร็วยาวมาก !); มันเทียบเท่ากับobject.constructorซึ่งช่วยให้เราสามารถเข้าถึงตัวสร้างของวัตถุใด ๆ

มีลูกเล่นมากมายที่เราสามารถทำได้ จากโลกีย์ไปสู่มหัศจรรย์:

  • ตัวสร้างของวัตถุเป็นฟังก์ชั่น โดยเฉพาะอย่างยิ่งมันมีชื่อและชื่อนั้นเป็นส่วนหนึ่งของ stringification ของฟังก์ชัน ตัวอย่างเช่นเราสามารถทำได้[[]+[]][+[]]["constructor"]เพื่อรับที่ตัวสร้างสำหรับสตริงที่มีชื่อเป็นสตริงแล้ว stringify เพื่อให้ได้ที่Sตัวอักษรตัวใหญ่ นี่เป็นการขยายตัวอักษรของเราเล็กน้อยและเราจะต้องการตัวละครใหม่บางตัวในภายหลัง
  • อาร์เรย์ทั้งหมดมี Constructor เดียวกัน []["constructor"] == []["constructor"]คือtrue(ไม่เหมือน[] == []ซึ่งเป็นเท็จ) สิ่งนี้อาจดูเล็กน้อย แต่มีความสำคัญมากเพราะมันทำให้เรามีวิธีเก็บค่าไว้อย่างต่อเนื่อง เราสามารถตั้งค่าคุณสมบัติแบบสุ่มในตัวสร้างและอ่านได้ในภายหลัง (นี่คือหนึ่งในเหตุผลที่เราใช้=โดยเฉพาะอย่างยิ่งแทนที่จะเป็นหนึ่งในวิธีอื่น ๆ ในการสร้างtrueและfalse.) ตัวอย่างเช่นเราสามารถประเมิน[[]["constructor"]["a"]=[]]และในภายหลังในการอ่าน[]["constructor"]["a"]และรับอาร์เรย์เดิมที่เราเก็บไว้ที่นั่น

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

  • มันช่วยให้เราได้รับการสร้างสำหรับฟังก์ชั่น (มีฟังก์ชั่นมากมายที่เราสามารถเข้าถึงได้ด้วยตัวอักษรที่ จำกัด ของเรา; []["find"]เช่น Array.find เป็นที่เข้าถึงได้ง่ายที่สุด แต่มีคนอื่น ๆ ) ทำไมจึงมีประโยชน์ ทีนี้เราสามารถใช้มันเพื่อจุดประสงค์ของตัวสร้างและสร้างฟังก์ชั่นได้! น่าเสียดายที่ชุดอักขระของเราทำให้เราไม่สามารถส่งสตริงที่คำนวณจากฟังก์ชันได้ อย่างไรก็ตามการใช้`ทำให้เราผ่านมันเป็นตัวอักษรสตริง(เช่น[]["find"]["constructor"]`function body goes here`); นี้หมายความว่าเราสามารถกำหนดค่าที่กำหนดเองจากประเภทฟังก์ชั่นที่มีพฤติกรรมใด ๆ []+=เมื่อดำเนินการดังนั้นตราบใดที่เราสามารถแสดงพฤติกรรมที่ใช้ทั้งหมด ตัวอย่างเช่น[]["find"]["constructor"]`[]+[]`เป็นฟังก์ชั่นที่ค่อนข้างน่าเบื่อที่คำนวณสตริงว่างทิ้งมันและออก; ที่ฟังก์ชั่นไม่เป็นประโยชน์ แต่จะมีความซับซ้อนมากกว่า โปรดทราบว่าถึงแม้ว่าฟังก์ชั่นไม่สามารถรับพารามิเตอร์หรือคืนค่าเหล่านั้นก็ไม่ใช่ปัญหาในทางปฏิบัติเนื่องจากเราสามารถใช้ที่เก็บข้อมูลคอนสตรัคเตอร์เพื่อสื่อสารจากฟังก์ชั่นหนึ่งไปยังอีกฟังก์ชั่นหนึ่ง ข้อ จำกัด อีกประการหนึ่งคือเราไม่สามารถใช้งาน`ในส่วนของฟังก์ชั่นได้

    ตอนนี้เราสามารถกำหนดฟังก์ชั่นที่กำหนดเองได้ แต่สิ่งที่ทำให้เรากลับมาถึงจุดนี้คือความยากลำบากในการเรียกพวกเขา ที่ระดับสูงสุดของโปรแกรมเราสามารถเรียกใช้ฟังก์ชั่นได้``แต่การเรียกฟังก์ชั่นเฉพาะจากระดับบนสุดนั้นไม่อนุญาตให้เราทำการวนซ้ำใด ๆ แต่เราต้องการฟังก์ชั่นเพื่อให้สามารถโทรหากัน

    เราทำสิ่งนี้ให้สำเร็จด้วยกลอุบายที่ค่อนข้างดี จำเมืองหลวงที่Sเราสร้างไว้ก่อนหน้านี้ได้ไหม "toString"ที่ช่วยให้เราสะกด เราจะไม่เรียกมันว่า เราสามารถแปลงสิ่งต่าง ๆ เป็นสตริงได้โดยการเพิ่ม[]เข้าไป แต่เราจะแทนที่มัน เราสามารถใช้หน่วยเก็บข้อมูลคอนสตรัคเตอร์เพื่อกำหนดอาร์เรย์ถาวรที่ติดอยู่รอบ ๆ จากนั้นเราสามารถกำหนดฟังก์ชั่นที่สร้างขึ้นให้กับtoStringวิธีการของอาร์เรย์และการกำหนดเหล่านั้นจะติดอยู่รอบ ๆ ตอนนี้สิ่งที่เราต้องทำคือง่าย ๆ+[]ในอาเรย์และทันใดนั้นฟังก์ชั่นที่กำหนดเองของเราจะทำงาน ซึ่งหมายความว่าเราสามารถใช้ตัวละคร+=[]เพื่อเรียกฟังก์ชั่นและดังนั้นฟังก์ชั่นของเราสามารถโทรหากัน - หรือตัวเอง สิ่งนี้ทำให้เราเรียกซ้ำซึ่งทำให้เรามีลูปและทันใดนั้นเรามีทุกสิ่งที่เราต้องการสำหรับทัวริงสมบูรณ์

ต่อไปนี้เป็นบทสรุปของชุดคุณลักษณะที่ให้ทัวริงสมบูรณ์และวิธีการใช้งาน:

  • หน่วยเก็บข้อมูลที่ไม่ถูกผูก : อาร์เรย์ที่ซ้อนกันในหน่วยเก็บข้อมูลของตัวสร้าง
  • การควบคุมการไหล : นำมาใช้โดยใช้ifและการเรียกซ้ำ:
    • if: แปลงบูลีนเป็นตัวเลขและจัดทำดัชนีเป็นอาร์เรย์ 2 องค์ประกอบ องค์ประกอบหนึ่งเรียกใช้ฟังก์ชันสำหรับthenเคสเมื่อทำการทำให้เป็นสตริงองค์ประกอบอื่นจะรันฟังก์ชันสำหรับelseเคสเมื่อทำสตริง
    • การเรียกซ้ำ : ทำให้องค์ประกอบที่เหมาะสมของหน่วยเก็บข้อมูลตัวสร้าง
  • คำสั่งลำดับ : [a]+[b]+[c]ประเมินa, bและcจากซ้ายไปขวา (อย่างน้อยในเบราว์เซอร์ที่ผมตรวจสอบ)

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


16
หากไม่มีชื่อฉันแนะนำ J5h * t
CalculatorFeline

1
โปรแกรมตัวอย่างที่ดีจะเป็นอย่างไร การทดสอบที่สำคัญ? สวัสดีชาวโลก?
CalculatorFeline

3
ที่ฉันเป็นเช่นนี้วัด ... คำตอบที่อร่อยเหมือนหนังสยองขวัญที่ดี
หยุดที่จะเปลี่ยนรหัสลับเมื่อ

4
ฉันคิดว่าการใช้งานของ Angular1 toString()สำหรับการฉีดพึ่งพาเป็นวิธีที่สร้างสรรค์ที่สุดในการใช้ฟังก์ชั่น ตอนนี้ฉันเปลี่ยนใจ
ซันนี่ปุน

1
นี่คือตัวอย่าง: pastebin.com/QGbjmB5Y
แยกผลไม้

55

เอกภาพ 1 ตัวละคร

0

การเลือกตัวละครนั้นไม่สำคัญเลย ความยาวของโปรแกรมกำหนดโปรแกรม brainfuck ที่ transpiles ไป ในขณะที่ข้อมูลจำเพาะสั่ง0ตัวละคร transpilers ส่วนใหญ่ดูเหมือนจะไม่ตรวจสอบเรื่องนี้


44
เราน่าจะเปิดปัญหากับ transpilers ที่ตรวจสอบ spec นี่เป็นปัญหาที่ร้ายแรงมาก
Captain Man

5
ฉันตกตะลึง ฉันต้องการ 20 นาทีเพื่อบอกว่าเป็นเรื่องตลกหรือไม่
Peter A. Schneider

3
@ PeterA.Schneider googling บางคนจะพบว่ามีคนใช้ Quine ด้วยวิธีนี้ในทางทฤษฎีแม้ว่าสตริงผลลัพธ์ของ 0 อาจเป็นจำนวนมากที่สุดที่ฉันเคยเห็นในบริบทที่ใช้งานจริงและไม่สามารถนำมาใช้กับเครื่องจริงได้
Darren Ringer

12
ศูนย์ของสตริงนั้นเป็นจำนวนที่เล็กที่สุดที่ฉันเคยเห็นในบริบทใด ๆ
Matthew อ่าน

1
ฮ่า ๆ ถ้าคุณทำอะไรโง่ ๆ เหมือนการกำหนดสัญลักษณ์เฉพาะของคุณในฐานะตัวตนเพิ่มเติม ... : p
Darren Ringer

37

เป็นกลุ่ม, 9 8 7 6 ตัวอักษร

<C-v><esc>1@ad

เราสามารถสร้างและดำเนินการโปรแกรม vimscript ตามอำเภอใจดังนี้

  1. ใช้ลำดับaa<C-v><C-v>1<esc>dd@1<esc>ddddที่จะได้รับในการลงทะเบียน<C-a>1

  2. เข้าสู่โหมดแทรกด้วยaจากนั้นแทรกaซึ่งจะใช้ในการเข้าสู่โหมดแทรกอีกครั้งในมาโครในภายหลัง

  3. สำหรับอักขระแต่ละตัวในโปรแกรม vimscript ที่ต้องการ

    1. ใช้<C-v><C-v>1<esc>การแทรกลำดับตัวอักษร<C-v>1,

    2. ใช้@1(ซึ่งคือ<C-a><cr>ที่สุดท้าย<cr>เป็น no-op เนื่องจากอยู่ในบรรทัดสุดท้าย) หลายครั้งเท่าที่จำเป็นเพื่อเพิ่มขึ้น1จนกว่าจะถึงค่า ASCII ของตัวละครที่ต้องการจะถึง

    3. aและอีกครั้งเข้าสู่โหมดแทรกด้วย

  4. ลบเส้น (พร้อมกับการขึ้นบรรทัดใหม่ต่อท้าย) ลงทะเบียนกับ1<esc>dd

  5. ดำเนินการผลลัพธ์เป็น vim keystrokes โดยใช้@1จากนั้น<esc>ddลบบรรทัดที่ป้อนโดยการขึ้นบรรทัดใหม่จากขั้นตอนก่อนหน้า

  6. เรียกใช้ลำดับไบต์ที่ได้ตามdd@1ต้องการ ถ้ามันเริ่มต้นด้วย:ก็จะถูกตีความว่าเป็นรหัส vimscript ddและมันจะถูกเรียกใช้เนื่องจากการขึ้นบรรทัดใหม่จาก

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


2
คุณไม่i<C-v>1<ESC>สามารถเขียน<C-a>และddใช้@1เพื่อเพิ่มจำนวนและส่งผลให้ไม่ต้องใช้<C-a>?
วัวต้มตุ๋น

4
ว้าวคำตอบนี้ช่างเหลือเชื่อ! +1!
DJMcMayhem

@KritixiLithos นั่นมันจบลงด้วยการทำงานหลังจากการปรับโครงสร้างเล็กน้อยขอบคุณ!
Doorknob

2
@ mbomb007 ที่จริงแล้ว ... เนื่องจากรายละเอียดการใช้งานที่น่าสนใจ<C-v>10แทรก NUL แทน \ n (ไม่ต้องถาม) ไม่ว่าในกรณีใดก็ตามมันไม่สำคัญว่าด้วยความสมบูรณ์แบบของทัวริง
Doorknob

1
มันสั้นกว่านี้ไหม? golf.shinh.org/p.rb?Hello+broken+keyboard#Vim
mbomb007

33

Perl, 5 ตัวอักษร

<>^es

เช่นเดียวกับภาษาสคริปต์อื่น ๆ แนวคิดก็คือevalสตริงที่กำหนดเอง อย่างไรก็ตามชุดอักขระของเราไม่รวมเครื่องหมายคำพูดหรือตัวดำเนินการเรียงต่อกันดังนั้นการสร้างสตริงโดยพลการจะมีความซับซ้อนมากขึ้น โปรดทราบว่าeval^"จะง่ายกว่ามากในการจัดการ แต่มีอักขระอีกหนึ่งตัว

เครื่องมือหลักของเราคือs<^><CODE>eeevals ซึ่งCODEจะทำการส่งออก เพิ่มเติมeสามารถเพิ่มกับผลที่คาดว่า

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

โดยการรวมสตริงเหล่านั้นเข้าด้วยกันเราจะได้ชุดอักขระจาก^B^V^S(*-/9;<>HJMOY[`\^begqstvตราบใดที่เรายอมรับว่ามีขยะรอบตัว (สามตัวแรกคือตัวควบคุม)

"v99"ตัวอย่างเช่นสมมติว่าเราต้องการที่จะได้รับ วิธีการหนึ่งที่จะได้รับv99คือ"><<" ^ "e>>" ^ "see" ^ "^^^"แต่เราไม่สามารถเป็นตัวแทนของสายเหล่านั้นเนื่องจากข้อ จำกัด <>ด้านบน ดังนั้นเราจึงใช้:

<^<<^>><>>^<^^^^^<>>^<^^^^^^e>^<^^^^^^^>^<^^^^^e>^<^^^^e^>^<e^^es>^<^ee^^>^<^<^^^^^>>^<^<>^^^^>^<^^^^^^^e>^<^^^^^^^^>

อัตราผลตอบแทนดังกล่าวข้างต้นY9;v99;ซึ่งเมื่อ eval-ed ให้ผลเช่นเดียวกับธรรมดาv99(กล่าวคือตัวละครที่มีรหัส ASCII 99)

ดังนั้นเราสามารถใช้^B^V^S(*-/9;<>HJMOY[`\^begqstvชุดอักขระทั้งหมดในการสร้างสตริงโดยพลการของเราแล้วแปลงเป็นข้างต้นและติดในs<><CODE>eeeeเพื่อดำเนินการ น่าเสียดายที่ชุดอักขระนี้ยังมีข้อ จำกัด มากโดยไม่มีวิธีที่ชัดเจนในการทำการต่อข้อมูล

แต่โชคดีที่มันมีดาวอยู่ นี้จะช่วยให้เราเขียนซึ่งประเมินสตริง*b "*main::b"จากนั้น*b^<^B[MMH^V^SY>(^ B, ^ V ^ S และมีการควบคุมตัวอักษรตัวอักษร) จะช่วยให้เรา(6, $&);ซึ่งเมื่อ EVAL-เอ็ดอีกครั้งผลตอบแทนที่คุ้มค่าของตัวแปรการแข่งขันของ Perl $&ที่ สิ่งนี้ช่วยให้เราใช้รูปแบบที่ จำกัด ของการต่อข้อมูล: เราสามารถเติมสิ่งที่ต้องการ$_ใช้ซ้ำs<^><THINGS>eแล้วใช้s<\H*><*b^<^B[MMH^V^SY>>eeeเพื่อ eval $_( \Hจับคู่อะไรก็ได้ยกเว้นช่องว่างแนวนอนเราใช้แทนจุดซึ่งไม่ได้อยู่ในชุดอักขระของเรา)

ใช้9-/เราสามารถสร้างตัวเลขทั้งหมดได้อย่างง่ายดาย การใช้ดิvจิตและการต่อข้อมูลเราสามารถสร้างตัวละครโดยพลการ (vXXX ให้ผลอักขระด้วยรหัส ASCII XXX) และเราสามารถเชื่อมโยงสิ่งเหล่านั้นเข้าด้วยกันเพื่อให้เราสามารถสร้างสตริงโดยพลการ ดังนั้นดูเหมือนว่าเราจะทำอะไรก็ได้

ลองเขียนตัวอย่างที่สมบูรณ์ สมมติว่าเราต้องการโปรแกรมที่พิมพ์ PID ของตัวเอง เราเริ่มต้นด้วยโปรแกรมธรรมชาติ:

say$$

เราแปลงเป็นสัญกรณ์ v:

s<><v115.v97.v121.v36.v36>ee

เราเขียนสิ่งนี้โดยใช้เฉพาะ^B^V^S(*-/9;<>HJMOY[`\^begqstv(ช่องว่างสำหรับการอ่านเท่านั้นและไม่มีผลต่อการส่งออก):

s<^><
    s<^><9*9-9-9-9-9-9>e;
    s<^><v>;
    s<v\H\H><*b^<^B[MMH^V^SY>>eee;
    s<^><9*9-9-9-9-9-9>e;
    s<^><v>;
    s<v\H\H><*b^<^B[MMH^V^SY>>eee;
    s<^><99-99/-9-99/-9>e;
    s<^><v>;
    s<v\H\H\H><*b^<^B[MMH^V^SY>>eee;
    s<^><99-9/9-9/9>e;
    s<^><v>;
    s<v\H\H><*b^<^B[MMH^V^SY>>eee;
    s<^><999/9-9/-9-9/-9-9/-9-9/-9>e;
    s<^><v>;
    s<v\H\H\H><*b^<^B[MMH^V^SY>>eee;
    s<\H*><*b^<^B[MMH^V^SY>>eee;
>eee;

สุดท้ายเราแปลงโปรแกรมข้างต้นเพียง<>^es: Pastebin น่าเศร้าที่นี่ทำให้เกิดปัญหากับ Perl Excessively long <> operatorแต่นั่นเป็นเพียงข้อ จำกัด ทางเทคนิคและไม่ควรนำมาพิจารณา

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

แก้ไข: <>โดยใช้วิธีการที่แตกต่างกันเล็กน้อยที่เราสามารถหลีกเลี่ยงการตีขีดจำกัดความยาวบน ฟังก์ชั่นล่ามสมองอย่างสมบูรณ์โดยใช้งานเท่านั้น<>^es: ลองออนไลน์! . อัตโนมัติ Perl เพื่อ<>^estranspiler: Pastebin


1
ฉันเห็น .. การเข้ารหัสของคุณได้รับการระเบิดเป็นกำลังสองเนื่องจากตัวละครของคุณแบ่งออกเป็นสองกลุ่มกลุ่มหนึ่งที่สามารถสร้างได้โดย xor'ing จำนวนตัวอักษรฐานคู่เท่านั้นและอีกตัวหนึ่งที่สามารถสร้างได้โดยเลขคี่บังคับให้คุณ เพิ่ม glob อีกเมื่อใดก็ตามที่มีการเปลี่ยนแปลงระหว่างพวกเขา มีโอกาสใดที่คุณสามารถแบ่งโปรแกรมออกเป็นชิ้นส่วนที่สั้นกว่าซึ่งประเมินได้ที่เชื่อมโยงกับ^หรือตัวละครฐานอื่น ๆ ?
Ørjan Johansen

@ ØrjanJohansenอ๋อทำได้ดีมาก ตอนนี้ฉันกำลังหาทางแก้ไข
Grimy

คุณสามารถทำให้ตัวอย่างที่ย่อขนาดนั้นเป็นลิงก์ TIO ลองใช้งานออนไลน์!
Ørjan Johansen

7
คำขอ: อธิบาย "วิธีการที่แตกต่างกันเล็กน้อย" นี้
เครื่องคิดเลข

32

Python 2, 7 ตัวอักษร

exc="%\n

โปรแกรม Python 2 ใด ๆ สามารถเข้ารหัสได้โดยใช้อักขระ 7 ตัวเหล่านี้ (ขึ้น\nบรรทัดใหม่)

การสร้างสตริงโดยพลการ

เราสามารถทำการต่อข้อมูลโดยการใช้ตัวดำเนินการการแทนที่%บนสตริงเดี่ยวซ้ำ ๆ ตัวอย่างเช่นถ้าa=1, b=2, c=3, จะให้เราสตริง"%d%%d%%%%d" % a % b % c "123"โชคดีที่ตัวอักษรในexecให้เราสามารถเข้าถึง%xและ%cที่มีพื้นและhex() chr()ด้วย%c, เราสามารถสร้างสตริงใด ๆ ตราบเท่าที่เรามีตัวเลขที่จำเป็นที่แสดงถึงตัวละคร จากนั้นเราสามารถรันสตริงนี้เป็นโค้ดไพ ธ อนได้โดยใช้execคีย์เวิร์ด

ทำตัวเลข

เราสามารถเข้า0และ1ออกจากค้างคาวด้วยการเปรียบเทียบ ( ==) ผ่านการรวมกันของตัวเลขและโมดูโลที่ต่อกันกันเป็นไปได้ที่จะสร้างตัวเลข43ที่แสดง+ใน ASCII สิ่งนี้ช่วยให้เราสามารถสร้างตัวเลขที่เราต้องการสำหรับรหัสของเรา

วางไว้ด้วยกัน

ฉันละเว้นรายละเอียดหลายอย่างในคำอธิบายนี้เนื่องจากไม่จำเป็นในการทำความเข้าใจว่าโปรแกรมภายใต้ข้อ จำกัด เหล่านี้สามารถเขียนได้อย่างไร ด้านล่างเป็นโปรแกรม Python 2 ที่ฉันเขียนซึ่งแปลงโปรแกรม python ให้เป็นรุ่นที่เทียบเท่ากับการใช้งานซึ่งใช้เพียง 7 ตัวอักษรเท่านั้น เทคนิคที่ใช้เป็นแรงบันดาลใจนี้ส่งกอล์ฟอนาธิปไตยโดย k เทคนิคง่าย ๆ บางอย่างยังใช้เพื่อรักษาขนาดของโปรแกรมที่สร้างขึ้นภายในขีด จำกัด ที่สมเหตุสมผล

import sys

var = {
    43: 'e',
    'prog': 'x', # the program will be stored in this variable
    'template': 'c',
    0: 'ee',
    1: 'ex',
    2: 'ec',
    4: 'xe',
    8: 'xx',
    16: 'xc',
    32: 'ce',
    64: 'cc',
    'data': 'cx', # source program will be encoded here
}

unpacker = 'exec"".join(chr(eval(c))for c in {}.split())'.format(var['data'])

source = sys.stdin.read()
charset = sorted(list(set(source+unpacker)))
codepoints = map(ord, charset)

output = (
    # create template for joining multiple characters
    '{}="%c%%c%%%%c%%%%%%%%c"\n'.format(var['template']) +

    # create 1
    '{0}={1}=={1}\n'.format(var[1], var['template']) +

    # create 0
    '{}={}==""\n'.format(var[0], var['template']) +

    # create 3
    # store it at var[43] temporarily
    (
        'exec"{0}=%x%%x"%{2}%{2}\n' +
        'exec"{0}%%%%%%%%=%x%%x%%%%x"%{1}%{2}%{1}\n'
    ).format(var[43], var[0], var[1]) +

    # create 4
    # this step overwrites the value stored at var[0]
    (
        'exec"{1}=%x%%x"%{0}%{1}\n' +
        'exec"{1}%%%%=%x%%x"%{2}%{0}\n'
    ).format(var[43], var[0], var[1]) +

    # create 43
    'exec"{0}=%x%%x"%{1}%{0}\n'.format(var[43], var[0])
)

# create powers of 2
for i in [2, 4, 8, 16, 32, 64]:
    output += 'exec"{0}={1}%c{1}"%{2}\n'.format(var[i], var[i/2], var[43])

for i, c in enumerate(codepoints):
    # skip if already aliased
    if c in var:
        continue

    # generate a new name for this variable
    var_name = ''
    if i < 27:
        for _ in range(3):
            var_name += 'exc'[i%3]
            i /= 3
    else:
        i -= 27
        for _ in range(4):
            var_name += 'exc'[i%3]
            i /= 3
    var[c] = var_name

    # decompose code point into powers of two
    rem = c
    pows = []
    while rem:
        pows.append(rem&-rem)
        rem -= rem&-rem

    # define this variable
    front = 'exec"{}={}'.format(var[c], var[pows.pop()])
    back = '"'
    for i, p in enumerate(pows):
        front += '%'*(2**i) + 'c' + var[p]
        back += '%' + var[43]
    output += front + back + '\n'

# initialise the unpacker
output += 'exec"""{}=""\n"""\n'.format(var['prog'])
i = 0
length = len(unpacker)
while i < length:
    if (length-i) % 4 == 0:
        # concat 4 characters at a time
        w, x, y, z = [var[ord(unpacker[i+j])] for j in range(4)]
        output += 'exec"{}%c={}%%{}%%{}%%{}%%{}"%{}\n'.format(var['prog'], 
                    var['template'], w, x, y, z, var[43])
        i += 4
    else:
        output += 'exec"""{}%c="%%c"%%{}"""%{}\n'.format(var['prog'],
                    var[ord(unpacker[i])], var[43])
        i += 1

# encode source data
output += var['data'] + '="""'
output += '\n'.join(var[ord(c)] for c in source)
output += '"""\n'

# execute the program
output += 'exec"exec%c{}"%{}'.format(var['prog'], var[32])

print output

ลองออนไลน์


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

26

Mathematica, 5 4 ตัวละคร

I[]

เป็นอักขระ Unicode ที่ใช้งานส่วนตัวซึ่งทำหน้าที่เป็นโอเปอเรเตอร์สำหรับFunctionให้คุณเขียนตัวอักษรสำหรับฟังก์ชันที่ไม่มีชื่อที่มีอาร์กิวเมนต์ที่กำหนดชื่อ ตัวละครดูเหมือนใน Mathematica มากดังนั้นฉันจะใช้ตัวนั้นเป็นคำตอบที่เหลือเพื่อความชัดเจน

การใช้สิ่งเหล่านี้เราสามารถนำและS, combinatorsKIของตรรกะ combinatory:

I -> II↦II
K -> II↦III↦II
S -> II↦III↦IIII↦II[IIII][III[IIII]]

ประเด็นทางวากยสัมพันธ์ประการหนึ่งของสิ่งเหล่านี้คือมันมีลำดับความสำคัญต่ำมากซึ่งจะเป็นปัญหาหากเราพยายามส่งข้อโต้แย้งไปยังผู้รวมกลุ่มเหล่านี้ ตามปกติคุณจะแก้ไขได้ด้วยการรวม combinator Cไว้ในวงเล็บเช่น(C)แต่เราไม่มีวงเล็บ อย่างไรก็ตามเราสามารถใช้Iและ[]ห่อCด้วยเวทมนตร์อื่น ๆ ที่มีความสำคัญสูงพอที่เราสามารถใช้ในภายหลังได้:

I[C][[I[[]]I]]

ในที่สุดเมื่อต้องการเขียนแอปพลิเคชันA x y z(โดยที่Acombinator "วงเล็บ" ดังที่แสดงไว้ด้านบนและx, หรือy, zอาจหรืออาจจะไม่วงเล็บ, หรืออาจเป็นการแสดงออกที่ใหญ่กว่า) เราสามารถเขียน:

A[x][y][z]

คำถามนี้แสดงให้เห็นว่าการเทียบเท่าวงเล็บนั้นใช้งานได้จริงอย่างไร ฉันจะพยายามอธิบายอย่างคร่าวๆตามลำดับที่ได้รับมา

ดังนั้นสิ่งที่เรามีบางสิ่งบางอย่างที่จะ syntactically []กลุ่มวงเล็บ วงเล็บปรากฏในสองวิธีใน Mathematica ไม่ว่าจะเป็นการเรียกใช้ฟังก์ชั่นf[x]หรือเป็นผู้ดำเนินการทำดัชนีf[[i]](ซึ่งจริงๆแล้วเป็นเพียงการจดชวเลขPart[f, i]) โดยเฉพาะอย่างยิ่งนั่นหมายความว่าไม่ใช่[C]หรือ[[C]]เป็นไวยากรณ์ที่ถูกต้อง เราต้องการบางสิ่งอยู่ข้างหน้ามัน ในทางทฤษฎีสามารถเป็นอะไรก็ได้ ถ้าเราใช้Iเรามีอยู่แล้วที่เราจะได้รับI[C]เช่น สิ่งนี้ยังคงไม่ได้รับการประเมินค่าเพราะIไม่ใช่ฟังก์ชั่นที่ไม่ใช่แบบเอกภาพ (ไม่ใช่ฟังก์ชั่นเลย)

แต่ตอนนี้เราต้องการวิธีที่จะแยกCอีกครั้งเพราะมิฉะนั้นมันจะไม่ได้รับการประเมินจริงเมื่อเราพยายามที่จะผ่านการโต้แย้งxไป

นี่คือที่มาในสะดวกที่f[[i]]สามารถใช้สำหรับการแสดงออกโดยพลการfไม่เพียง แต่รายการ สมมติว่าfตัวเองเป็นรูปแบบhead[val1,...,valn]แล้วf[[0]]ให้head, f[[1]]ให้val1, f[[-1]]ให้valnและอื่น ๆ ดังนั้นเราจึงจำเป็นต้องได้รับอย่างใดอย่างหนึ่ง1หรือ-1เพื่อแยกCอีกครั้งเพราะทั้งสองI[C][[1]]หรือประเมินI[C][[-1]]C

เราสามารถได้รับ1จากสัญลักษณ์ที่ไม่ได้กำหนดโดยพลการเช่นxแต่จะทำอย่างไรที่เราจะต้องตัวอักษรสำหรับส่วนอื่น ( x/xให้1สำหรับที่ไม่ได้กำหนดx) คูณเป็นเพียงการดำเนินการทางคณิตศาสตร์ที่เราสามารถดำเนินการได้โดยไม่ต้องตัวอักษรใด ๆ เพิ่มเติม (ในหลักการ) ดังนั้นเราจึงจำเป็นค่าบางอย่างที่สามารถคูณขึ้นเพื่อให้หรือ-1 1นี่คือเหตุผลที่ฉันเลือกIตัวระบุของเราโดยเฉพาะ เพราะIตัวมันเองเป็นสัญลักษณ์ในตัวของ Mathematica สำหรับหน่วยจินตภาพ

แต่นั่นทำให้เกิดปัญหาสุดท้าย: เราจะเพิ่มจำนวนIตัวเองได้อย่างไร เราไม่สามารถเขียนIIเพราะมันได้รับการแจงเป็นสัญลักษณ์เดียว เราจำเป็นต้องแยกโทเค็นเหล่านี้โดยไม่ต้อง a) เปลี่ยนค่าและ b) โดยใช้ตัวละครใหม่ ๆ

บิตสุดท้ายของเวทมนตร์คือชิ้นส่วนของพฤติกรรมที่ไม่มีเอกสาร: f[[]](หรือเทียบเท่าPart[f]) คือไวยากรณ์ที่ถูกต้องและส่งคืนfตัวเอง ดังนั้นแทนที่จะคูณIโดยIเราคูณโดยI[[]] Iการแทรกวงเล็บทำให้ Mathematica ค้นหาโทเค็นใหม่หลังจากนั้นและI[[]]Iประเมิน-1ตามต้องการ I[C][[I[[]]I]]และนั่นคือวิธีการที่เราจบลงด้วย

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


คำตอบที่ยอดเยี่ยม
Patrick Stevens

23

Python 2, 8 ตัวอักษร

exc'%~-0

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

นอกจากนี้ยังสามารถใช้เครื่องหมายอัญประกาศคู่และตัวเลขหลักเดียวนอกเหนือจากศูนย์ได้อีกด้วย (ตอนนี้ที่ผมคิดเกี่ยวกับมัน1แน่นอนจะดีกว่าส่งผลให้ในโปรแกรมสั้นเนื่องจากคุณสามารถใช้1, 11และ111เช่นเดียว.)

นี่คือโปรแกรมprint:

exec'%c%%c%%%%c%%%%%%%%c%%%%%%%%%%%%%%%%c'%-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~0%-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~0%-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~0%-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~0%-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~0

ลองออนไลน์

โปรแกรมฐานต้องใช้

exec''

ตัวละครแต่ละตัวที่xถูกเพิ่มเข้ามาในโปรแกรมต้องการ

  • % - 2**(n-1)
  • c - 1
  • - - ord(x)*2
  • ~ - ord(x)*2
  • 0 - 1

ข้อยกเว้นนี้คือการปรับให้เหมาะสมที่สุด / ทางลัดบางอย่างอาจทำให้โปรแกรมที่เข้ารหัสสั้นลงเช่นใช้%'0'สำหรับตัวละคร0แทน 48 -~เป็นต้น

การใช้งานในทางปฏิบัติ (การเล่นกอล์ฟ AKA): ฉันใช้กลยุทธ์นี้เพื่อแก้ไขความท้าทายนี้โดยไม่ต้องใช้ตัวละครแต้มต่อเพิ่มเติม

เครดิตสำหรับรายชื่อตัวละครและโปรแกรมเข้ารหัส: ที่นี่

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

จำนวนไบต์ที่ต้องการเพิ่มขึ้นO(2**n)ดังนั้นวิธีนี้จึงไม่แนะนำสำหรับการเล่นกอล์ฟ ควินที่ใช้การ จำกัด แหล่งที่มานี้จะยาวอย่างเมามัน


หากผู้ดำเนินการที่สำคัญเท่านั้นที่จะดำเนินการ+หรือ-ก่อนหน้า%เราสามารถลบอักขระ
mbomb007

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

นี่ไม่ใช่เทคนิคการใช้ภาษา Turning สมบูรณ์แม้ว่าใช่หรือไม่? มันมีความสามารถในการเรียกล่ามสำหรับการเปิดภาษาที่สมบูรณ์ซึ่งเป็นล่าม Python ฝังตัว สิ่งนี้จะทำงานในภาษาใด ๆ ไม่ว่าการกลึงเสร็จสมบูรณ์หรือไม่ก็ตามตราบใดที่มีความสามารถในการเรียกใช้คำสั่งเชลล์ไปยังล่ามอื่น
mmachenry

@mmachenry Python ใช้คอมไพเลอร์และล่ามของตัวเอง ไม่ได้ใช้ภาษาอื่นแยกต่างหาก และล่ามสมองถูกสร้างขึ้นใน Python ดังนั้นจึงเป็นทัวริง การใช้ความรู้นั้นการโต้แย้งของคุณเป็นเท็จ
mbomb007

@ mbomb007 ไม่มีการโต้แย้งของฉันไม่ได้เป็นเท็จ Python เป็นภาษา Turning สมบูรณ์เห็นได้ชัด การคำนวณกำลังดำเนินการโดยการเรียกล่าม Python จาก Python โดยใช้อักขระใด ๆ ที่คุณต้องการสำหรับการโทรภายใน ภาษาที่คุณระบุโปรแกรมนั้นเป็นเพียงการเข้ารหัสไม่ใช่ภาษาโปรแกรม การใช้สิ่งนี้ทำให้การเขียนโปรแกรมภาษาทัวริงสมบูรณ์เป็นเรื่องเล็กน้อยโดยใช้อักขระ 0 และ 1 และดูไฟล์ต้นฉบับเป็นแบบไบนารี่ จิตวิญญาณของคำถามคือการค้นหาประโยคย่อยของภาษาจริงแม้ว่า
mmachenry

23

C (unportable), 24 18 13 ตัวอักษร

aimn[]={};,1+

ซึ่งจะครอบคลุมโปรแกรมทั้งหมดของแบบฟอร์ม

main[]={<sequence of constants>};

... โดยที่ลำดับของค่าคงที่ (ของแบบฟอร์ม 1 + 1 + 1 ... ) มีการแสดงรหัสเครื่องของโปรแกรมของคุณ สิ่งนี้ถือว่าสภาพแวดล้อมของคุณอนุญาตให้เรียกใช้หน่วยความจำทุกส่วน (เห็นได้ชัดว่าเป็นจริงสำหรับ tcc [ขอบคุณ @Dennis!] และเครื่องบางเครื่องที่ไม่มีบิตบิต) มิฉะนั้นสำหรับ Linux และ OSX คุณอาจต้องเพิ่มคำหลักไว้ล่วงหน้าconstและสำหรับ Windows คุณอาจต้องเพิ่มการ#pragmaทำเครื่องหมายกลุ่มอย่างชัดเจนว่าสามารถเรียกใช้งานได้

เป็นตัวอย่างโปรแกรมต่อไปนี้ที่เขียนในสไตล์ข้างต้นพิมพ์Hello, World!บน Linux และ OSX บน x86 และ x86_64

main[]={111111111+111111111+11111111+11111111+1111111+1111111+1111111+1111111+1111111+11111+11111+11111+11111+11111+11111+11111+11111+111+11+11+11+11+11+11+1+1,1111111111+11111111+11111111+11111111+11111111+11111111+11111111+11111111+11111111+1111111+1111111+1111111+1111111+1111111+1111111+1111111+111111+11111+11111+11111+11111+11111+11111+1111+1111+1111+111+111+111+111+111+111,1111111111+111111111+111111111+111111111+111111111+111111111+111111111+11111111+11111111+11111111+11111111+11111111+11111111+11111111+11111111+1111111+1111111+111111+111111+111111+111111+11111+11111+11111+1111+1111+1111+1111+1111+1111+1111+1111+111+111+111+111+111+111+111+111+111+11+11+11+11+11+1+1+1+1+1+1+1,1111111111+111111111+111111111+111111111+111111111+111111111+111111111+11111111+11111111+11111111+11111111+11111111+11111111+11111111+11111111+1111111+111111+11111+11111+11111+11111+11111+11111+11111+11111+1111+1111+111+111+111+111+111+111+111+11+11+11+11+11+11+1+1+1+1,111111111+111111111+111111111+111111111+111111111+1111111+1111111+1111111+1111111+111111+111111+1111+1111+1111+1111+1111+1111+111+111+111+111+111+11+11+11+11+1+1+1+1,111111111+111111111+111111111+111111111+111111111+111111111+111111111+111111111+111111111+11111111+11111111+11111111+11111111+11111111+11111111+11111111+1111111+1111111+1111111+1111111+1111111+1111111+1111111+111111+111111+111111+111111+111111+111111+111111+1111+1111+1111+111+111+111+111+111+11+11+11+11+11+11+1+1+1+1+1+1,111111111+111111111+11111111+11111111+11111111+11111111+11111111+11111111+1111111+1111111+1111111+1111111+111111+111111+111111+111111+11111+11111+11111+11111+11111+11111+11111+11111+111+111+111+111+111+111+11+11+11+11+11+11+11+1,1111111111+111111111+111111111+111111111+11111111+11111111+11111111+11111111+1111111+1111111+1111111+111111+111111+111111+111111+111111+111111+111111+111111+11111+11111+11111+11111+11111+1111+1111+1111+1111+1111+1+1+1+1+1,1111111111+111111111+111111111+111111111+111111111+111111111+111111111+1111111+1111111+1111111+1111111+1111111+111111+111111+111111+11111+11111+11111+11111+1111+1111+111+111+111+111+111+111+111+111+111+11+11+11+11+11+1+1+1+1+1+1+1+1+1,1111111111+1111111111+111111111+111111111+111111111+111111111+111111111+111111111+11111111+11111111+11111111+11111111+11111111+11111111+1111111+1111111+111111+111111+111111+111111+11111+11111+1111+1111+1111+1111+1111+1111+1111+111+111+111+111+111+11+11+1+1+1+1+1,1111111111+111111111+111111111+111111111+111111111+111111111+111111111+111111111+111111111+111111111+11111111+11111111+11111111+11111111+1111111+1111111+1111111+1111111+111111+111111+111111+111111+111111+111111+111111+111111+11111+11111+11111+11111+1111+1111+1111+1111+1111+111+11+1+1+1+1+1,1111111111+1111111111+111111111+111111111+111111111+111111111+111111111+111111111+111111111+111111111+111111111+11111111+11111111+11111111+11111111+1111111+1111111+1111111+1111111+1111111+111111+111111+111111+11111+11111+11111+11111+11111+11111+11111+11111+11111+111+111+111+111+1+1+1+1+1+1+1,1111111111+1111111111+1111111111+111111111+111111111+111111111+111111111+111111111+111111111+111111111+111111111+11111111+11111111+11111111+11111111+11111111+11111111+1111111+1111111+1111111+1111111+1111111+111111+111111+111111+111111+11111+11111+1111+1111+111+111+111+111+111+111+111+111+111+11+11+11+11+11+11+1+1+1,1111111111+111111111+111111111+111111111+1111111+1111111+1111111+111111+111111+111111+111111+111111+111111+111111+1111+1111+1111+1111+1111+1111+1111+1111+111+111+111+111+111+111+111+111+111+1+1+1+1+1+1,111111+111111+11111+11111+11111+11111+11111+11111+11111+1111+1111+1111+1111+1111+1111+1111+1111+111+111+111+11+11+11+11+11+11+11+11+11+11,11111111+11111111+11111111+11111111+11111111+11111111+11111111+1111111+1111111+1111111+1111111+1111111+1111111+111111+111111+111111+11111+11111+11111+11111+11111+11111+11111+11111+1111+1111+111+111+111+111+111+111+11+11+11+11+11+11+11+1+1+1,111111111+111111111+111111111+111111111+111111111+111111111+111111111+11111111+11111111+11111111+11111111+1111111+1111111+1111111+1111111+1111111+111111+111111+111111+11111+11111+11111+11111+11111+11111+11111+11111+1111+1111+111+111+111+11+11+11+1,111111111+111111111+11111111+11111111+1111111+1111111+1111111+1111111+1111111+1111111+111111+111111+111111+111111+111111+11111+11111+11111+11111+11111+11111+11111+11111+11111+1111+1111+111+11+11+1+1+1+1+1,11111+11111+11111+11111+1111+1111+1111+1111+111+111+111+111+111+111+111+111+111+11+11+11+1+1+1+1+1};

ลองออนไลน์!


2
@GB: ศูนย์ค่อนข้างง่ายที่จะหลีกเลี่ยงการใช้รหัสเครื่องอย่างน้อย x86 (ไม่ใช่คำสั่งที่สำคัญอย่างยิ่ง) โดยเฉพาะอย่างยิ่งเพราะปัญหาจะเกิดขึ้นเฉพาะเมื่อคุณมีสี่ไบต์ต่อแถว

2
@GB บนเครื่องที่มี 32 บิต int0==1111111111+1111111111+1111111111+111111111+111111111+111111111+111111111+111111111+111111111+111111111+111111111+11111111+11111111+11111111+11111111+11111111+11111111+1111111+1111111+1111111+1111111+1111111+111111+111111+111111+111111+11111+11111+11111+11111+11111+11111+11111+111+111+111+111+111+11+11+11+11+11+11+11+1
ceilingcat

3
constทีซีซีจะช่วยให้คุณได้รับไปโดยไม่ต้อง tio.run/nexus/…
Dennis

8
@GB ฉันเพิ่งตระหนักถึงการเป็นตัวแทนที่สั้นกว่าของ 0 คือ1==11
ceilingcat

3
@ wizzwizz4 มันไม่บริสุทธิ์ C ไม่ว่าในกรณีใดก็ตามไม่ได้ทำให้รู้สึกทัวริงสมบูรณ์ มันไม่มีความหมาย C อะไรเลย เนื่องจากคุณยังต้องพึ่งพารายละเอียดของคอมไพเลอร์และสภาพแวดล้อมในการดำเนินการเพื่อให้สามารถใช้งานอะไรได้เลยคุณอาจอนุญาตให้มีจุดเข้าใช้งานที่มีชื่อตามอำเภอใจ
John Bollinger

20

จอประสาทตา 6 ตัว

$%`{¶

เช่นเดียวกับ linefeeds (0x0A)

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

เมื่อวันที่เพื่อพิสูจน์ ฉันจะอธิบายวิธีง่ายๆในการแปลระบบแท็กแบบวงกลมเป็น Retina โดยใช้อักขระด้านบน

ปิดครั้งแรกที่เราจะใช้`และ{สำหรับตัวอักษรไบนารีแทนและ0 1สิ่งเหล่านี้สะดวกเพราะไม่จำเป็นต้องหลบหนีใน regex แต่มีความหมายสำหรับ Retina หรือในไวยากรณ์การแทนที่ ฉันใช้`สำหรับ0และ{สำหรับ1แต่ตัวเลือกนี้โดยพลการ นอกจากนี้เราจะย้อนกลับสตริง (และโปรดักชั่น) ในหน่วยความจำเนื่องจากการทำงานกับอักขระตัวสุดท้ายทำให้เราสามารถใช้$และ$`แทนที่จะใช้^และ$'เพื่อเพิ่มการใช้อักขระซ้ำให้ได้มากที่สุด

หากคำแรกถูกแทนด้วยSและมีiการเรียกการผลิต th (กลับรายการ) โปรแกรมผลลัพธ์จะมีลักษณะดังนี้:pi


S
{`

{$
¶p1$%``
``$

{$
¶p2$%``
``$

{$
¶p3$%``
``$

...

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

ลองดูสิ่งที่โปรแกรมทำ:


S

เราเริ่มต้นด้วยการเริ่มต้นสตริงการทำงานเป็นคำเริ่มต้น

{`

สิ่งนี้ล้อมรอบส่วนที่เหลือของโปรแกรมใน a ที่ทำงานจนกว่าจะล้มเหลวในการเปลี่ยนสตริงที่เป็นผลลัพธ์ ตัวป้อนบรรทัดสองตัวที่นั่นไม่จำเป็นจริงๆ แต่พวกมันแยกลูปออกจากกันอย่างชัดเจนมากขึ้นจากการผลิตแต่ละอย่าง ส่วนที่เหลือของโปรแกรมจะผ่านการผลิตแต่ละครั้งและเนื่องจากการวนซ้ำเราจึงประมวลผลอย่างมีประสิทธิภาพวนซ้ำไปเรื่อย ๆ

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

{$
¶pi$%``

regex จะจับคู่ก็ต่อเมื่อสตริงนั้นลงท้าย{ด้วย หากเป็นเช่นนั้นเราจะแทนที่ด้วย:

  • ตัวป้อนบรรทัด ( ) เราจะทำงานร่วมกับบรรทัดสุดท้ายของสตริงการทำงานเท่านั้นดังนั้นนี่จึงเป็นการทิ้งสตริงการทำงานอย่างมีประสิทธิภาพ (ซึ่งเป็นสาเหตุที่การใช้หน่วยความจำของโปรแกรมจะเพิ่มขึ้นเรื่อย ๆ )
  • การผลิตในปัจจุบัน ( ) ซึ่งเราขอต่อท้ายไปยังสตริงการทำงาน (โดยที่ระบบแท็กไซคลิกต่อท้าย)pi
  • สตริงการทำงานที่เหลืออยู่ก่อนหน้า ( $%`) นี่คือเหตุผลที่เราต้องแทรก: $%`เลือกทุกอย่างที่เหลือของการแข่งขัน แต่เฉพาะในบรรทัดเดียวกัน ดังนั้นนี่จะไม่เห็นขยะทั้งหมดที่เราทิ้งไว้จากการผลิตก่อนหน้านี้ เคล็ดลับนี้ช่วยให้เราจับคู่บางอย่างที่ส่วนท้ายของสตริงการทำงานเพื่อแทรกบางอย่างที่จุดเริ่มต้นของสตริงการทำงานโดยไม่ต้องใช้สิ่งที่ชอบ(.+)และสิ่ง$1ที่จะทำให้จำนวนอักขระที่เราต้องการเพิ่มขึ้น
  • backtick เดียว ( `) สิ่งนี้จะแทนที่{( 1-symbol) ที่เราจับคู่กับ`( 0-symbol) ได้อย่างมีประสิทธิภาพเพื่อให้ขั้นตอนต่อไปไม่จำเป็นต้องรู้ว่าเราได้ดำเนินการผลิตในปัจจุบันแล้วหรือไม่

ส่วนที่สองของการผลิตแต่ละครั้งนั้นเป็นกรณีเล็กน้อยที่การผลิตถูกข้ามไป:

``$

`เราเพียงแค่ลบต่อท้าย เหตุผลที่เราต้องการสอง`บรรทัดแรกคือ Retina คิดว่า backtick ตัวแรกเป็นตัวแบ่งระหว่างการกำหนดค่าและ regex นี่เป็นเพียงการกำหนดค่าที่ว่างเปล่าเพื่อให้เราสามารถใช้ backticks ใน regex ได้


20

Java 7, 18 17 ตัวอักษร

\bcdefu0123456789

ซอร์สโค้ดจาวาทั้งหมดสามารถลดลงเป็น unicode code points ได้ ไม่จำเป็นต้องใช้ "a" เนื่องจากใช้สำหรับ*:jJzZเท่านั้น เครื่องหมายดอกจันใช้สำหรับการคูณหรือบล็อกความคิดเห็น การคูณเป็นเพียงการเพิ่มซ้ำและคุณสามารถใช้ความคิดเห็นบรรทัดเดียวแทน (หรือเพียงแค่ละเว้น) โคลอนใช้สำหรับตัวดำเนินการที่ประกอบไปด้วยสามตัวซึ่งคุณสามารถใช้คำสั่ง if แทนและ foreach loops ซึ่งสามารถแทนที่ด้วยปกติสำหรับลูป j และ z ไม่ได้เป็นส่วนหนึ่งของคำหลักใด ๆ ใน java

ความพยายามที่จะเอาตัวละครอื่น ๆ class a{public static void main(String[]a){}}ที่เราต้องเพิ่มอย่างน้อยหนึ่งในตัวละครที่จำเป็นในจานหม้อไอน้ำ ดูด้านล่าง:

1 -> a (which has already been removed)
2 -> r (required for "String")
3 -> S (required for "String")
4 -> t (required for "static")
5 -> S (required for "String")
6 -> v (required for "void")
7 -> g (required for "String")
8 -> ( (required for "main(String[]a)"
9 -> i (required for "static")
b -> { (required for "class a{")
c -> l (required for "class")
d -> } (required for "(String[]a){}}")
e -> n (required for "main")
f -> o (required for "void")

นี่คือตัวอย่างของโปรแกรม Hello World ลองออนไลน์!

Java 8, 16 ตัวอักษร

\bdefu0123456789

ขอบคุณ ais523 ที่ชี้เรื่องนี้ออกมา Java 8 อนุญาตให้ส่วนต่อประสานมีวิธีการคงที่ซึ่งหมายความว่าเราสามารถวาง "c" ได้เพราะเราไม่ต้องการใช้ "l" ใน "class" "c" ใช้เพื่อ,<lL\|ทำให้เราสูญเสียการทำงานของจาวาเล็กน้อยกว่าเมื่อเราลบ "a" ออก แต่เรายังมีเพียงพอที่จะทำให้สมบูรณ์ ลองออนไลน์!


3
แน่นอนว่าการตัดตัวเลขฐานสิบหกตัวใดที่น่าสนใจในการแก้ปัญหานี้ใน Java? :)
Martin Ender

@ มาร์ตินเอนเดอร์อย่างแน่นอน ฉันวางแผนที่จะทำสิ่งนี้มากขึ้นเมื่อฉันมีเวลา
Poke

6
และฉันที่พร้อมจะเขียนบางสิ่งJava, 127 characters... Nice one, Poke;)
Olivier Grégoire

จากตัวละครที่ต้องการในคำตอบของฉันฉันไม่เชื่อว่าเลขฐานสิบหกอื่น ๆ จะถูกลบออก

3
หากคุณเปลี่ยนเป็น Java 8 คุณสามารถทำได้ใน 16 Java 8 อนุญาตให้ส่วนต่อประสานมีวิธีการแบบคงที่ช่วยให้คุณสามารถปล่อยc(ตัวอักษรทั้งหมดในinterfaceยังคงสามารถเข้าถึงได้โดยไม่ต้องaหรือcในตัวอักษรฐานสิบหกของคุณ)

19

เขาวงกต 5 ตัวอักษร

~{}

เพิ่ม linefeeds (0x0A) และช่องว่าง (0x20)

ฉันจะร่างหลักฐานในรูปแบบของการลดลงจากSmallfuck (ตัวแปร Brainfuck ลดลงที่ใช้เซลล์ 1 บิต) โปรดทราบว่า Smallfuck ตัวเองไม่ได้ทัวริงสมบูรณ์เพราะภาษาระบุว่าเทปของมันจะต้องมี จำกัด แต่เราจะสมมติตัวแปรของ Smallfuck ด้วยเทปที่ไม่มีที่สิ้นสุดซึ่งจะเป็นการทัวริงที่สมบูรณ์ (เนื่องจากเขาวงกตไม่มีหน่วยความจำ ข้อ จำกัด โดยการออกแบบ)

ค่าคงที่ที่สำคัญตลอดการลดลงนี้คือทุกโปรแกรม (หรือโปรแกรมย่อย) จะส่งผลให้โปรแกรมเขาวงกต (หรือโปรแกรมย่อย) ที่เริ่มต้นและสิ้นสุดในแถวเดียวกันและมีจำนวนคอลัมน์เท่ากัน

เขาวงกตมีสองกองที่เต็มไปครั้งแรกกับอนันต์ (นัย) ปริมาณของ0s {และ}เปลี่ยนค่าสูงสุดระหว่างสแต็คเหล่านี้ หากเราพิจารณาว่าด้านบนสุดของสแต็กหลักเป็น "เซลล์" ปัจจุบันสแต็กทั้งสองนี้สามารถมองเห็นได้เป็นครึ่งเซเว่นไม่สิ้นสุดครึ่งหนึ่งของเทปอนันต์ที่ Smallfuck ใช้ อย่างไรก็ตามจะสะดวกกว่าที่จะมีสองสำเนาของแต่ละค่าเทปบนสแต็กเพื่อให้แน่ใจว่าค่าคงที่ดังกล่าวข้างต้น ดังนั้น<และ>จะถูกแปลเป็น{{และ}}ตามลำดับ (คุณสามารถสลับได้หากต้องการ)

แทนที่จะอนุญาตให้ใช้ค่าเซลล์0และ1เรากำลังใช้ 0และ-1ซึ่งเราสามารถสลับไปมาระหว่างด้วย~(การปฏิเสธค่าบิต) ค่าที่แน่นอนนั้นไม่สำคัญสำหรับวัตถุประสงค์ของทัวริง เราต้องเปลี่ยนทั้งสองชุดของค่าในกองซึ่งจะช่วยให้เราแปลแม้ความยาวอีกครั้ง: กลายเป็น*~}~{

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

ก่อนอื่นให้สังเกตว่า~~ไม่มีการใช้งานเนื่องจากทั้งสอง~ถูกยกเลิกอย่างมีประสิทธิภาพ เราสามารถใช้สิ่งนี้เพื่อให้มีเส้นทางยาวโดยพลการในรหัสตราบใดที่ความยาวของพวกเขาเป็นคู่ ตอนนี้เราสามารถใช้สิ่งก่อสร้างต่อไปนี้เพื่อแปลAA[BB]CCเป็น Labyrinth (ฉันใช้ตัวอักษรสองตัวเพื่อให้ขนาดของตัวอย่างใน Labyrinth เท่า ๆ กันซึ่งรับประกันโดยค่าคงที่)

      ~~~~
      ~  ~~~
AA~~..~~~~ ~CC
   ~     ~
   ~     ~
   ~     ~
   ~~~BB~~

ที่นี่..เป็นจำนวนที่เหมาะสมซึ่งตรงกับความกว้างของ~BB

โปรดทราบอีกครั้งว่าความกว้างของการก่อสร้างยังคงเท่าเดิม

ตอนนี้เราสามารถผ่านการทำงานของวงนี้ AAป้อนรหัสผ่าน ครั้งแรกที่~~ไม่ทำอะไรเลยและช่วยให้เราไปถึงทางแยก เรื่องนี้เกี่ยวข้องกับ[:

  • ถ้าค่าเซลล์ปัจจุบันเป็นศูนย์ IP BBยังคงตรงไปข้างหน้าซึ่งในที่สุดจะข้าม ..ส่วนหนึ่งยังคงเป็นไม่มี-op จากนั้นเราก็ไปถึง~จุดแยกที่อีกจุดหนึ่ง ตอนนี้เรารู้แล้วว่าค่าปัจจุบันไม่เป็นศูนย์ดังนั้น IP จึงหันไปทางทิศเหนือ มันจะไปรอบโค้งที่ด้านบน, ~จนกว่าจะถึงทางแยกอีกครั้งหลังจากที่หก ดังนั้นจุดที่คุ้มค่าในปัจจุบันยังไม่เป็นศูนย์และ IP CCเตะเปิดอีกครั้งเพื่อย้ายไปทางตะวันออกสู่ โปรดทราบว่าทั้งสาม~ก่อนที่จะCCส่งกลับค่าปัจจุบันไป0ตามที่ควรจะเป็นเมื่อวงถูกข้าม
  • หากค่าเซลล์ปัจจุบันที่จุดเริ่มต้นของลูปไม่ใช่ศูนย์ IP จะเลี้ยวไปทางใต้ มันวิ่งอีกหก~ก่อนถึงBB(ซึ่งไม่ทำอะไรเลย) และอีกหก~ก่อนถึงทางแยกถัดไป สิ่งนี้ประมาณ]ว่า
    • หากเซลล์ปัจจุบันเป็นศูนย์ IP จะเคลื่อนที่ไปทางเหนือ ถัดไป~ทำให้ค่าไม่เป็นศูนย์เพื่อให้ IP ใช้จุดเชื่อมต่อที่สองนี้ซึ่งรวมเส้นทางกับกรณีที่มีการข้ามลูปอย่างสมบูรณ์ อีกครั้งที่สามกลับค่าเป็นศูนย์ก่อนที่จะถึง~CC
    • หากเซลล์ปัจจุบันไม่ใช่ศูนย์ IP จะเลี้ยวไปทางตะวันตก มีอยู่~ก่อนทางแยกถัดไปซึ่งหมายความว่า ณ จุดนี้ค่าปัจจุบันเป็นศูนย์เพื่อให้ IP ยังคงไปทางตะวันตก จากนั้นจะมีจำนวนคี่~ก่อนที่ IP จะถึงจุดเชื่อมต่อเริ่มต้นอีกครั้งดังนั้นค่าจะถูกส่งคืน-1และ IP จะย้ายไปทางทิศใต้ในการวนซ้ำถัดไป

หากโปรแกรมมีลูปใด ๆ ดังนั้นสิ่งแรกที่AAต้องถูกขยายไปยังด้านบนของโปรแกรมเพื่อให้ IP ค้นหาเซลล์ที่ถูกต้องเพื่อเริ่มต้น:

~     ~~~~
~     ~  ~~~
AA~~..~~~~ ~CC
   ~     ~
   ~     ~
   ~     ~
   ~~~BB~~

นั่นคือที่ โปรดทราบว่าโปรแกรมที่เป็นผลมาจากการลดนี้จะไม่สิ้นสุด แต่ไม่ได้เป็นส่วนหนึ่งของข้อกำหนดของทัวริง - ความสมบูรณ์ (พิจารณากฎ 101 หรือ Fractran)

ในที่สุดเราก็เหลือคำถามว่ามันเหมาะสมหรือไม่ ในแง่ของภาระงานตัวละครฉันสงสัยว่าเป็นไปได้ที่จะทำได้ดีกว่าสามคำสั่ง ฉันเห็นการสร้างทางเลือกโดยใช้เครื่องจักร Minsky ที่มีสองรีจิสเตอร์ แต่ต้องใช้=()หรือ=-~มีคำสั่ง stack-manipulation เพียงคำสั่งเดียว แต่จากนั้นคำสั่งทางคณิตศาสตร์สองคำ ฉันยินดีที่จะได้รับการพิสูจน์ผิดเกี่ยวกับเรื่องนี้ :)

สำหรับคำสั่งเลย์เอาต์ฉันเชื่อว่าจำเป็นต้องใช้ linefeeds เนื่องจากการควบคุมการไหลที่เป็นประโยชน์เป็นไปไม่ได้ในบรรทัดเดียว อย่างไรก็ตามช่องว่างไม่จำเป็นทางเทคนิค ในทางทฤษฎีอาจเป็นไปได้ที่จะเกิดการสร้างที่เติมทั้งกริดด้วย~{}(หรือ=()หรือ=-~) หรือใช้เลย์เอาต์แบบขรุขระที่เส้นไม่ยาวเท่ากันทั้งหมด อย่างไรก็ตามการเขียนโค้ดแบบนั้นยากอย่างไม่น่าเชื่อเพราะเขาวงกตจะปฏิบัติต่อทุก ๆ เซลล์เป็นทางแยกและคุณจะต้องระมัดระวังอย่างมากเพื่อป้องกันไม่ให้โค้ดแตกแขนงเมื่อคุณไม่ต้องการมัน หากใครสามารถพิสูจน์หรือหักล้างว่าการเว้นพื้นที่เป็นไปได้สำหรับทัวริง - สมบูรณ์ฉันยินดีที่จะให้รางวัลมากมายสำหรับสิ่งนั้น :)


19

Haskell, 5 7 ตัวอักษร

()\->=;

แน่นอนว่า Haskell เป็นภาษาที่ใช้งานได้มีแลมบ์ดาดังนั้นการจำลองแคลคูลัสแลมบ์ดาจึงเป็นเรื่องง่าย ไวยากรณ์สำหรับ lambdas เป็นดังนั้นเราจึงต้องไม่น้อยกว่าตัวละคร นอกจากนี้เราต้องการสัญลักษณ์ตัวแปรไม่ จำกัด จำนวนเพื่อให้สามารถสร้างการแสดงออกแลมบ์ดาโดยพลการ โชคดีที่เราไม่จำเป็นต้องมีตัวละครใหม่ใด ๆ นี้เพราะ, , ... มีทั้งหมดชื่อตัวแปรที่ถูกต้อง ในความเป็นจริงการรวมกันของวงเล็บภายในเป็นชื่อตัวแปรที่ถูกต้องยกเว้นเพียงแค่และซึ่งสงวนไว้สำหรับการแสดงออกแลมบ์ดาและที่จะเริ่มความคิดเห็นบรรทัด(\variable->body)argument()\->
(>)(>>)(>>>)\->\->--

ตัวอย่าง:

  • S = (\(>)(\\)(-)->(>)(-)((\\)(-)))ประเภทถึง(t2 -> t -> t1) -> (t2 -> t) -> t2 -> t1
  • K = (\(>)(-)->(>))ประเภทถึงt -> t1 -> t
  • ฉัน = (\(>)->(>))ประเภทถึงt -> t

แก้ไข:อย่างไรก็ตามตามที่ais523ได้ชี้ให้เห็นในความคิดเห็นการก่อสร้างนี้ได้ทำการพิมพ์แลมบ์ดาแคลคูลัสซึ่งตัวมันเองไม่ได้เป็นทัวริงสมบูรณ์เพราะขาดความสามารถในการป้อนลูปไม่สิ้นสุด ในการแก้ไขปัญหานี้เราต้องการฟังก์ชั่นบางอย่างที่ทำการเรียกซ้ำ จนถึงตอนนี้เราใช้ lambdas ที่ไม่มีชื่อซึ่งไม่สามารถเรียกตัวเองได้เพราะเอ่อพวกเขาไม่มีชื่อ ดังนั้นเราต้องเพิ่มตัวอักษร=และ;เพื่อใช้fixฟังก์ชั่น

(>)=(\(-)->(-)((>)(-)));   -- equivalent to: f =(\ x -> x ( f  x ));

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


จะไม่ถูกลบออกทางเทคนิคในเวลารวบรวมmainหรือไม่?
PyRulez

4
แคลคูลัสของ SKI ที่พิมพ์ง่าย ๆ นั้นไม่ได้เป็นทัวริงสมบูรณ์ คุณต้องการแคลคูลัสแลมบ์ดาที่ไม่ได้พิมพ์เพื่อสิ่งนั้น น่าเสียดายที่การสาธิตของคุณพูดถึง Haskell จะตีความการพิมพ์ลงบนโค้ดตามค่าเริ่มต้น

@PyRulez ตามกฎเริ่มต้นฉันถือว่าฟังก์ชั่นเป็นที่ยอมรับ
Laikoni

@ ais523 combinators SKI เป็นเพียงตัวอย่างการใช้คำศัพท์แลมบ์ดาที่กำหนดสามารถสร้างขึ้นได้เช่นเลขคริสตจักรและฟังก์ชันต่าง ๆ
Laikoni

@ ais523 ต้องมีผู้ทำการคอมบิเนเตอร์จำนวนเท่าใดแลมบ์ดาแคลคูลัสต้องสมบูรณ์? ฉันคิดว่าคุณแค่ต้องการ combinator y ใช่ไหม?
PyRulez

18

CJam, 3 ตัวอักษร

นำออก)ตามคำแนะนำของ Martin Ender

'(~

คล้ายกับงูหลามที่ให้มาเป็นตัวอย่าง

ใช้'~คุณสามารถรับ~ตัวละคร จากนั้นใช้(คุณสามารถลดมันลงเพื่อให้ได้อักขระที่คุณต้องการ ( ~เป็นอักขระ ASCII ที่พิมพ์ได้ครั้งสุดท้าย) ~Evals สตริงใด ๆ ที่เป็นรหัส CJam ปกติ Strings สามารถถูกสร้างขึ้นโดยได้รับตัวละคร[(ผ่าน decrementing ~) eval'ing มันวางลำดับของตัวละครอื่น ๆ บางส่วนแล้ว eval'ing ]ตัวอักษร ผ่านสิ่งนี้คุณสามารถสร้างและดำเนินการโปรแกรม CJam ใด ๆ โดยใช้เพียงสามตัวอักษร

กำลังคำนวณ 2 +2 โดยใช้เพียงอย่างเดียว '(~


สำหรับความท้าทายอื่นมีคนสร้างโปรแกรมที่ใช้โปรแกรม cjam ใด ๆ และรวบรวมมันโดยอัตโนมัติไปยังส่วนย่อย ฉันหวังว่าฉันจะหามันได้
Zwei

1
ฉันจัดการลงโปรแกรม 2 + 2 อย่างมีนัยสำคัญ'~((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((~'~(((((((((((((((((((((((((((((((~'~(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((~
Zwei

@Zwei เยี่ยมมากที่เหมาะกับชื่อของคุณ
Chromium

18

Brain-Flak 6 ตัว

(){}[]

Brain-Flak เป็นภาษามินิมอลลิสต์มีเพียง 8 ตัวอักษร อย่างไรก็ตามมันสามารถพิสูจน์ได้ว่ามีส่วนย่อยของ Brain-Flak ที่ทัวริงสมบูรณ์โดยใช้เพียง 6 ตัวอักษร

สิ่งแรกที่เราจะทำคือการใช้เครื่อง Minsky กับ Brain-Flak เพียงหนึ่งกอง ถ้าเราสามารถพิสูจน์ได้ว่าเครื่องมินสกีเป็นไปได้ที่มีเพียงหนึ่งสแต็คที่เราสามารถแสดงให้เห็นว่าสมอง Flak เป็นทัวริงสมบูรณ์โดยไม่ต้อง<>และ[]nilads สิ่งนี้จะไม่บันทึกอักขระใด ๆ ทันที แต่จะเกิดขึ้นในอนาคตเมื่อเราแสดงว่า<...>ไม่จำเป็น

เครื่อง Minsky เป็นประเภทของหุ่นยนต์ทัวริงที่สมบูรณ์ซึ่งมีจำนวน จำกัด ของการลงทะเบียนที่ไม่ จำกัด และสองคำแนะนำ:

  • เพิ่มการลงทะเบียน

  • หากการลดลงที่ไม่เป็นศูนย์มิฉะนั้นจะเปลี่ยนเป็นคำสั่งที่ระบุ

ในการตั้งค่าโครงสร้าง goto ใน Brain-Flak เราสามารถใช้ตัวอย่างต่อไปนี้:

(({}[()])[(())]()){(([({}{})]{}))}{}{(([({}{}(%s))]{}))}{}

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

เราใช้สิ่งนี้เป็นเครื่องห่อหุ้มสำหรับคำแนะนำของ Minsky Machine ทั้งหมดของเรา

การเพิ่มการลงทะเบียนนั้นง่ายมากโดยไม่ต้องสลับกองซ้อน สามารถทำได้ด้วยสูตรสตริงนี้:

"({}<"*n+"({}())"+">)"*n

ตัวอย่างเช่นการเพิ่มการลงทะเบียนครั้งที่ 3 เราจะเขียนรหัสต่อไปนี้:

({}<({}<({}<({}())>)>)>)

ตอนนี้เราแค่ต้องใช้การดำเนินการที่สอง การตรวจสอบว่าตัวเลขเป็นศูนย์นั้นง่ายใน Brain-Flak หรือไม่:

(({})){(<{}%s>)}{}

จะดำเนินการ%sหาก TOS เป็นศูนย์ ดังนั้นเราสามารถดำเนินการครั้งที่สองของเรา

เนื่องจาก Minsky Machines กำลังทัวริงสมองที่สมบูรณ์แล้วยังทำให้ทัวริงสมบูรณ์โดยไม่ต้องใช้<>และ[]ปฏิบัติการ

อย่างไรก็ตามเรายังไม่ได้ลดจำนวนตัวอักษรเพราะ<...>และ[...]ยังใช้งานอยู่ วิธีนี้สามารถแก้ไขได้ด้วยการทดแทนอย่างง่าย เนื่องจาก<...>เทียบเท่ากับ[(...)]{}ในทุกกรณี ดังนั้น Brain-Flak นั้นทัวริงสมบูรณ์โดยไม่ต้องใช้ตัวอักษร<และ>(รวมถึงตัวเลือกทั้งหมด)


"เพราะ<...>และ[...]ยังใช้อยู่" [...]แต่คุณไม่ได้ลบ กรุณาแก้ไข
CalculatorFeline

คำถาม: [...]จำเป็นจริง ๆ การกด 0 สามารถทำได้ตั้งแต่เริ่มต้นด้วย({})(แต่ขึ้นอยู่กับสแต็กเปล่าดังนั้น 0s จะต้องถูกสับอย่างระมัดระวัง) ปัญหาหลักคือสามารถลงไปในสแต็กได้โดยไม่ต้องเข้าถึง<...>(ซึ่งไม่สามารถจำลองได้อีกต่อไป)
CalculatorFeline

16

> <> , 3 ตัวอักษร

> <> สามารถทำได้ใน 3 ด้วย1p-ซึ่งทำ:

1          Push 1
p          Pop y, x, c and put the char c in cell (x, y) of the codebox
-          Subtraction: pop y, x and push x-y

pจัดเตรียมการสะท้อนการแก้ไขซอร์สโค้ด 2D โดยการใส่อักขระลงในกล่องรหัส ด้วย1-คุณสามารถกดตัวเลขใด ๆ ลงบนสแต็กได้ตั้งแต่1-ลบหนึ่งและ111-1--( x-(1-1-1) = x+1) บวกหนึ่งเข้าไป

เมื่อ1p-คำสั่งทั้งหมดได้ดำเนินการแล้วตัวชี้คำสั่งจะล้อมรอบเพื่อให้สามารถเรียกใช้รหัส "ของจริง"

ตัวอย่างโปรแกรมที่คำนวณตัวเลขฟีโบนักชี (จากคำตอบนี้ ) คือ:

111-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1--11-11-p111-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1--111-p111-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1--111-1--11-p111-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1--111-1-1--11-p111-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1--111-1-1-1--11-p111-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1--111-1-1-1-1--11-p111-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1--11-1p111-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1--11p111-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1--111-1--1p111-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1--111-1-1--1p111-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1--111-1-1-1--1p111-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1--111-1-1-1-1--1p111-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1--111-1-1-1-1-1--1p111-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1--111-1-1-1-1-1-1--1p111-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1--111-1-1-1-1-1-1-1--1p111-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1--111-1-1-1-1-1-1-1-1--1p111-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1--111-1-1-1-1-1-1-1-1-1--1p111-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1--111-1-1-1-1-1-1-1-1-1-1--1p111-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1--111-1-1-1-1-1-1-1-1-1-1-1--1p111-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1--111-1-1-1-1-1-1-1-1-1-1-1-1--1p111-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1--111-1-1-1-1-1-1-1-1-1-1-1-1-1--1p111-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1--111-1-1-1-1-1-1-1-1-1-1-1-1-1-1--1p

ลองออนไลน์! เมื่อ1p-คำสั่งทั้งหมดดำเนินการแล้วกล่องรหัสจะมีลักษณะดังนี้:

01aa+v1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1- ...
@+&1->:?!;&:nao:

ยกเว้นทุกอย่างหลังจากvบรรทัดแรกนี่เป็นโปรแกรมมาตรฐานฟีโบนักชี> <>


13

bash, 9 ตัวอักษร

01456\$ '

Bash มีไวยากรณ์$'\nnn'สำหรับการป้อนอักขระด้วยค่าฐานแปด เราสามารถป้อนคำสั่งในรูปแบบนี้เป็นeval $'\145\166\141\154'ก่อนอื่นเราจะเปลี่ยนผลลัพธ์ที่ต้องการให้เป็นค่าฐานแปด จากนั้นเราจะแปลงค่าฐานแปดใด ๆ โดยใช้ตัวเลขอื่นที่ไม่ใช่ 0, 1, 4, 5, 6 และเข้าสู่การแสดงออกที่จะประเมินว่าค่าใช้ฐานแปด$(())และลบผนวกevalไปด้านหน้า ในขั้นตอนสุดท้ายของเราเราเพิ่มอีกอันevalและแปลงวงเล็บและเครื่องหมายลบเป็นค่าฐานแปด การใช้วิธีนี้เราสามารถรันคำสั่ง bash ใด ๆ ดังนั้นเซ็ตย่อยนี้จึงสมบูรณ์

ตัวอย่าง:

dc กลายเป็น

$'\144\143' ซึ่งกลายเป็น

$'\145\166\141\154' \$\'\\144\\$((144-1))\' ซึ่งกลายเป็น

$'\145\166\141\154' $'\145\166\141\154' $'\$\\\'\\\\144\\\\$\050\050144\0551\051\051\\\''


12

เหตุการณ์ 2 ตัวอักษร

มันไม่สำคัญว่าคุณจะเลือกตัวละครใดสองตัว การรวมกันของสองออคเต็ตใด ๆ ก็คือการทำให้ทัวริงเสร็จสมบูรณ์ในเหตุการณ์

การพิสูจน์ความจริงแล้วเป็นเรื่องยากกว่าที่คุณคาดหวังและในขณะที่เขียนหน้าอภิปรายของ Esolang เกี่ยวกับเหตุการณ์นั้นมุ่งเน้นที่ปัญหา ฉันจะพยายามให้บทสรุปของหลักฐานที่รู้จักง่ายที่สุดด้านล่าง

ก่อนที่จะพิสูจน์พื้นหลังบางส่วน เหตุการณ์จะส่งสัญญาณโทเค็นที่ใช้ในโปรแกรมโดยดูที่ต้นทาง (โทเค็นเป็นสตริงที่ปรากฏขึ้นสามครั้งในแหล่งที่มาไม่ใช่ซับสตริงของโทเค็นอื่นและไม่ทับซ้อนกับโทเค็นอื่น) ดังนั้นโปรแกรมใด ๆ ที่สามารถแปลงให้ใช้อักขระใด ๆ ที่กำหนดโดยการเปลี่ยนโทเค็นคืออะไร; ภาษานั้นทัวริงสมบูรณ์ (และมีความสมบูรณ์สำหรับ I / O เช่นกัน!) แม้จะยากในการเขียนโปรแกรมดังนั้น "ทั้งหมด" ที่คุณต้องการคือวิธีการเข้ารหัสโทเค็นเพื่อให้ทำงานกับอักขระเพียงสองตัว

และตอนนี้ต่อไปนี้เป็นบทสรุปของการพิสูจน์ (ซึ่งถูกค้นพบโดยØrjanนักคณิตศาสตร์ประจำของ Esolang) แนวคิดคือเราเข้ารหัสโทเค็นโดยใช้สำเนาสองตัวของอักขระหนึ่งตัว (พูด1) ในทะเลใหญ่ของตัวละครอื่น (พูด0) ระยะห่างระหว่าง1s แตกต่างกันไปโทเค็น แต่อยู่เสมอหลาย 4 แล้วสำหรับช่องว่างระหว่างราชสกุลเราจะใช้รายการพิเศษของ0s กับ1ที่อยู่ตรงกลาง แต่จำนวนของ 0s ในแต่ละด้านของ1คือไม่ใช่ผลคูณของ 4 แต่เป็นตัวเลขเฉพาะสำหรับอุบัติการณ์เฉพาะของโปรแกรมที่ไม่ปรากฏในส่วนอื่นของโปรแกรม นั่นหมายความว่าแต่ละ1...1ภายในช่องว่างภายในสามารถปรากฏสองครั้งเท่านั้นดังนั้นจะไม่เป็นส่วนหนึ่งของโทเค็น แต่ละโทเค็นตั้งใจมีตรงสอง 1s 1และไม่มีโทเค็นปลอมสามารถมีมากกว่าหนึ่ง จากนั้นเราเพียงเพิ่มการเติมด้านข้างเพื่อลบโทเค็นที่เป็นไปได้ทั้งหมดที่มีหนึ่ง1หรือศูนย์1โดยการเพิ่มอย่างน้อยสี่สำเนา


11

จอประสาทตา 3 ตัว

{`

และขึ้นบรรทัดใหม่

ก่อนอื่นเราต้องขึ้นบรรทัดใหม่เพื่อให้สามารถทดแทน (จำเป็นเว้นแต่ว่าเราต้องการให้โปรแกรมทั้งหมดเป็นหนึ่ง regex ซึ่งจะต้องมีตัวอักษรมากขึ้น); และ`และ{เป็นวิธีที่ตัวละครมากน้อยที่จะทำลูป ปรากฎว่าเราไม่ต้องการอะไรอีกแล้ว

ภาษาเป้าหมายของเราที่จะใช้เป็นตัวแปรที่กำหนดของThue (nondeterminism ไม่จำเป็นสำหรับทัวริง - ครบถ้วน; เป็นไปได้ที่จะเขียนโปรแกรม Thue ให้ทำงานอย่างถูกต้องโดยไม่คำนึงถึงลำดับการประเมินที่ใช้) ความคิดพื้นฐานคือการรวบรวมpattern::=replacementลงใน

`pattern
replacement

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

ของหลักสูตรนี้หมายความว่าเราต้องพิสูจน์ Thue ทัวริงสมบูรณ์มีเพียง{และ`ในรูปแบบและการเปลี่ยน แต่ที่ง่ายพอ; เราแทนที่ตัวอักษรด้วยรหัส ASCII nด้วย`, n 1 และอื่น ๆ{ `เห็นได้ชัดว่าเป็นไปไม่ได้ที่รูปแบบการจับคู่จะอยู่ที่ใดก็ได้ แต่ตามขอบเขตของตัวละครดังนั้นสิ่งนี้จะจบลงด้วยการทำสิ่งเดียวกันกับโปรแกรมดั้งเดิม


1
"โปรแกรมเหล่านี้ยังคงทำงานต่อไปจนกว่าจะไม่มีการทดแทนได้อีกต่อไปและสิ่งนี้ทำให้ Retina ทำงานในลักษณะเดียวกัน" โดยมีข้อยกเว้นเพียงอย่างเดียวที่ว่า Retina จะยุติลงก่อนหากว่าใครผ่านโปรแกรมทั้งหมดไม่สามารถเปลี่ยนสตริงได้ ดังนั้นคุณจะได้รับการตรวจจับแบบไม่ จำกัด วงอย่างง่าย ๆ ได้ฟรี
Martin Ender

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

10

Brachylog 5 ตัว

~×₁↰|

ชุดย่อยของตัวละครนี้ช่วยให้เราสามารถนำFractran ไปใช้ซึ่งตัวเลขที่ปรากฏขึ้นเท่านั้นคือผลผลิตของการชดเชย (เช่นผลิตภัณฑ์ของตัวเลขที่สามารถเขียนเป็นทศนิยมโดยใช้หลัก 1 เท่านั้น) (ที่มีจำนวนเต็มเป็นตัวห้อย) หารค่าปัจจุบันด้วยจำนวนเต็มนั้น แต่เฉพาะในกรณีที่หารอย่างแน่นอน (มิฉะนั้นจะ "ล้มเหลว" และมองหากรณีอื่นที่จะทำงาน; |แยกกรณี) ×ให้เราคูณด้วยจำนวนเต็ม ดังนั้นการใช้~×₁|เราสามารถใช้ขั้นตอนหนึ่งของการประมวลผล Fractran จากนั้นให้เราเรียกคืนโดยเรียกใช้โปรแกรมทั้งหมดอีกครั้งกับค่าปัจจุบันใหม่ นี่คือตัวอย่างของโปรแกรม Fractran ที่ง่ายมาก ( 11111111111111111111111/111) แปลเป็น Brachylog

ทัวริงเสร็จสมบูรณ์หรือไม่ สิ่งที่เราต้องทำให้ Fractran Turing สมบูรณ์นั้นมีจำนวนเฉพาะจำนวนมากเพียงพอ (พอที่จะเขียนล่ามสำหรับภาษา Turing ที่สมบูรณ์ใน Fractran เอง) มีห้าพิสูจน์และสงสัยว่าสี่รวมถึงช่วงเวลาที่ยังไม่ได้ค้นพบ มันมากกว่าที่เราต้องการในกรณีนี้ โปรแกรมตรวจสอบความเป็นไปได้จากซ้ายไปขวาเพื่อให้เราสามารถใช้หนึ่งนายกเป็นตัวชี้คำสั่งและอีกสองเป็นเคาน์เตอร์แสดงให้เห็นถึงทัวริงสมบูรณ์ด้วยสามช่วงเวลาเท่านั้น (สิ่งที่ดีเกินไปเพราะมันช่วยให้เราใช้ค่าตอบแทนด้วย 2, 19 และ 23 หลักโดยไม่ต้องหันไปใช้ค่าตอบแทนที่มีขนาดใหญ่ที่ผ่านการพิสูจน์แล้ว แต่น่ารำคาญด้วย 317 หรือ 1,031 หลักซึ่งจะทำให้ซอร์สโค้ดค่อนข้างยากที่จะเขียน) ที่ทำให้สามารถใช้เครื่อง Minsky ที่มีสองตัวนับ (เพียงพอสำหรับทัวริง - ความสมบูรณ์)

นี่เป็นวิธีรวบรวมเฉพาะงาน เราจะใช้สองคำสั่งต่อไปนี้สำหรับการใช้งานเครื่อง Minsky ของเรา (ซึ่งรู้จักกันในชื่อทัวริงสมบูรณ์) และแต่ละคำสั่งจะมีจำนวนเต็มเป็นป้ายกำกับ:

  • เลเบล L: หากตัวนับ {A หรือ B} เป็นศูนย์ให้ข้ามไป X มิฉะนั้นลดลงและกลับไปที่ Y
  • ป้าย L: ตัวนับเพิ่ม {A หรือ B} จากนั้นกลับไปที่ Z

เราเลือกคำสั่งที่จะเรียกใช้ผ่านการวางกำลังของ 11 ในตัวส่วนพลังสูงสุดก่อน เลขชี้กำลัง 11 คือป้ายกำกับของคำสั่ง ด้วยวิธีนี้เศษส่วนแรกที่ตรงกันจะเป็นคำสั่งในการดำเนินการในปัจจุบัน (เพราะส่วนก่อนหน้านี้ไม่สามารถหารด้วย 11s เหล่านั้นทั้งหมด) ในกรณีของคำสั่งลดค่าเรายังวางปัจจัย 1111111111111111111 หรือ 1111111111111111111111111 ในตัวหารสำหรับตัวนับ A หรือ B ตามลำดับและติดตามด้วยคำสั่งอื่นโดยไม่มีปัจจัยนั้น กรณี "การลดลง" จะถูกนำมาใช้โดยคำสั่งแรก, กรณีที่ "ศูนย์" โดยที่สอง ในขณะเดียวกัน "goto" จะได้รับการจัดการโดยกำลังที่เหมาะสมที่ 11 ในตัวเศษและ "การเพิ่ม" ผ่านปัจจัย 111111111111111111111 หรือ 1111111111111111111111111 ในตัวเศษ


มีเหตุผลใดที่ทำให้คุณไม่สามารถใช้ค่าตอบแทนแบบคู่ตามลำดับได้?
CalculatorFeline

@CalculatorFeline: ไม่ แต่ฉันไม่ได้คิดถึงพวกเขาจนกระทั่งหลังจากฉันพบการก่อสร้างที่ไม่ต้องการพวกเขาแล้ว แน่นอนว่ามันจะช่วยในการเล่นกอล์ฟที่เขียนด้วยชุดตัวละครนี้

นอกจากนี้ค่าตอบแทนทั้งหมด> 1 คือ coprime ตามเข็มนาฬิกา (คิดดู)
CalculatorFeline

@CalculatorFeline: ไม่มีเลย 111 และ 111111 นั้นหารด้วย 3 ได้อย่างชัดเจน

* ไม่มี repunit แบ่ง repunit อีก
CalculatorFeline

10

Befunge-98, 3 ตัวละคร

เท่าที่ฉันรู้ Befunge-98 ควรจะได้รับการทำให้สมบูรณ์ดังนั้นเราแค่ต้องแสดงให้เห็นว่าโปรแกรม Befunge-98 ใด ๆ สามารถสร้างขึ้นได้โดยใช้ตัวละครเพียงสามตัว โซลูชันเริ่มต้นของฉันอาศัยอักขระสี่ตัวต่อไปนี้:

01+p

เราจะได้รับจำนวนเต็มบวกใด ๆ ลงบนสแต็คโดยมีการเพิ่ม1ค่าร่วมกับคำสั่งและศูนย์เราก็ใช้+ 0เมื่อเรามีความสามารถในการกดหมายเลขที่เราต้องการแล้วเราสามารถใช้pคำสั่ง (put) เพื่อเขียนค่า ASCII ใด ๆ ไปยังตำแหน่งใด ๆ ในสนามเด็กเล่น Befunge

อย่างไรก็ตามตามที่Sp3000ชี้ให้เห็นคุณสามารถใช้อักขระสามตัวจริง:

1-p

จำนวนลบใด ๆ สามารถคำนวณได้โดยเริ่มต้นด้วย1จากนั้นลบซ้ำ ๆ1(เช่น -3 จะเป็น11-1-1-1-) จากนั้นจำนวนบวกใด ๆ สามารถแทนได้ด้วยการลบ 1-n จาก 1 โดยที่ 1-n เป็นจำนวนลบซึ่งเรารู้วิธีจัดการ (เช่น 4 = 1 - (- 3) ซึ่งจะเป็น111-1-1-1--)

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

ตัวอย่างเช่นนี่คือ bootloader ที่สร้างรหัส Befunge ที่จำเป็นสำหรับผลรวม 2 + 2 และผลลัพธ์: 22+.@

และสำหรับตัวอย่างที่ซับซ้อนกว่านี้เล็กน้อยคือ "Hello World": "!dlroW olleH"bk,@


นี่คือรูปหลายเหลี่ยมสามารถใช้อักขระเดียวกันสำหรับ> <> และอนุพันธ์ของมัน เยี่ยมมาก!
Sok

2
Befunge-98 ทำได้ใน 3 ด้วย1p-เช่นกัน
Sp3000

@ Sp3000 แน่นอนใช่! ฉันแน่ใจว่าต้องมีวิธีที่จะทำให้มันลงไปถึง 3 ตัวอักษร ขอบคุณ
James Holderness

9

ทับทิม 8 ตัวอักษร

eval"<1+

แรงบันดาลใจจากคำตอบของ Python

มันทำงานอย่างไร

  • สามารถใช้ eval เพื่อรันสตริงโดยพลการ
  • "<1+ เป็นชุดอักขระขั้นต่ำที่ต้องใช้ในการสร้างสตริงใด ๆ

สตริงในทับทิมสามารถสร้างได้โดยใช้สตริงว่างเป็นจุดเริ่มต้นและผนวกอักขระ ASCII เข้าด้วยกันตัวอย่างเช่น:

eval ""<<111+1<<11+11+11+1<<111<<11+11+11+1

เทียบเท่ากับ

eval ""<<112<<34<<111<<34

ซึ่งประเมินสตริง

p"o"

8

OCaml, 9 ตัวอักษร

fun->()`X

อักขระเหล่านี้เพียงพอที่จะใช้แคลคูลัส SKI Combinator ใน OCaml สะดุดตาเราสามารถหลีกเลี่ยงการใช้พื้นที่ที่มีวงเล็บที่เพียงพอ น่าเสียดายที่การแสดงออกแลมบ์ดาใน OCaml ต้องการfunคำหลักดังนั้นจึงไม่มีทางแก้ปัญหาที่สั้นกว่านี้อีก ตัวอักษรเดียวกันสามารถใช้ในการสร้างชื่อตัวแปรโดยพลการหากต้องการแสดงออกแลมบ์ดาที่ซับซ้อนยิ่งขึ้น

S Combinator:

fun(f)(u)(n)->f(n)(u(n)) กับประเภท ('a -> 'b -> 'c) -> ('a -> 'b) -> 'a -> 'c

K Combinator:

fun(f)(u)->u กับประเภท 'a -> 'b -> 'b

ฉัน Combinator:

fun(f)->f กับประเภท 'a -> 'a

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

Combinator Z:

fun(f)->(fun(`X(x))->(x)(`X(x)))(`X(fun(`X(x))y->f(x(`X(x)))y))

กับประเภท (('a -> 'b) -> 'a -> 'b) -> 'a -> 'b


2
แคลคูลัสของ SKI ที่พิมพ์ง่าย ๆ นั้นไม่ได้เป็นทัวริงสมบูรณ์ คุณต้องการแคลคูลัสแลมบ์ดาที่ไม่ได้พิมพ์เพื่อสิ่งนั้น น่าเสียดายที่การสาธิตของคุณได้กล่าวถึงแล้ว OCaml จะทำการตีความการพิมพ์บนโค้ดตามค่าเริ่มต้น

1
จากนั้นฉันก็ต้องการตัวอักษรเพิ่มอีกสองสามตัวเพื่อให้สามารถใช้ตัวแปรหลากหลายซึ่งจะช่วยให้การเข้ารหัส y-combinator (และ z-combinator ในทำนองเดียวกัน)
Devin Lehmacher

Combinator Z คืออะไร
CalculatorFeline

@CalculatorFeline มันเป็นตัวแปรที่เข้มงวดของ y-combinator มีความจำเป็นใน OCaml เพราะ OCaml ไม่ได้ขี้เกียจ นี่คือลิงค์ไปยังหน้าวิกิพีเดีย: en.wikipedia.org/wiki/…
Devin Lehmacher

8

ภาษาที่เรียงซ้อนตามสแต็ก 4 ตัวอักษร

underload

():^

GolfScript

{}.~

CJam

{}_~

GS2

  • backspace, แท็บ, @เว้นวรรค (ฉันรู้ว่า GS2 ใช้ unprintables ได้เยอะ แต่นี่มันไร้สาระ ... )

dc (แนะนำโดย @seshoumara)

[]dx

Underload ได้รับการพิสูจน์แล้วว่าทัวริงสมบูรณ์ด้วยการใช้งานเท่านั้น():^(ขอบคุณนักคณิตศาสตร์ถิ่นอาศัยของ Esolang Ørjan) หลักฐานอยู่นานเกินไปที่จะอธิบายที่นี่ แต่ถ้าหากคุณสนใจคุณสามารถอ่านเกี่ยวกับเรื่องนี้ที่นี่

คำสั่งที่เป็นปัญหาคือ()(วางรหัสตามตัวอักษรบนสแต็ก), :(องค์ประกอบด้านบนสุดของสแต็กที่ซ้ำกัน) และ^(ประเมินด้านบนของสแต็ก) คำสั่งเหล่านี้ค่อนข้างพบได้ทั่วไปในภาษาที่ใช้สแต็ก (โดยเฉพาะภาษาที่ต่อกัน) และดังนั้นฉันจึงให้บางอย่างของคอลเลกชันข้างต้น ภาษาเหล่านี้เป็นภาษาทัวริงครบทั้ง 4 ตัวด้วยเหตุผลเดียวกับ Underload


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

1
@seshoumara: ตัวเลข (และสวยมากทุกการจัดเก็บข้อมูลอื่น ๆ ) จะดำเนินการมากทางอ้อมเมื่อใช้วิธีการนี้ มีบางอย่างที่เหมือนกับสองหรือสามระดับบางทีอาจเป็นสี่เท่าของระดับนามธรรมก่อนที่คุณจะได้สิ่งที่เป็นเลขคณิต สิ่งนี้เป็นเรื่องปกติในการพิสูจน์ทัวริงสมบูรณ์ของระบบที่ จำกัด มากเช่นนี้

ฉันกำลังคิดที่จะส่งคำตอบเป็น dc ด้วยตัวเองเช่นเดียวกับภาษาที่ใช้สแต็ก แต่ใช้วิธีอื่นที่เกี่ยวข้องกับตัวอักษรมากกว่า 4 ตัว dc ไม่มีตัวดำเนินการเรียงต่อกัน แต่มันมีค่าเทียบเท่า สามารถใส่ในรายการของคุณได้หรือไม่?
seshoumara

@seshoumara: ใช่ดูเหมือนว่าจะมีฟังก์ชั่นทั้งหมดที่จำเป็น ฉันได้เพิ่มและให้เครดิตคุณ

บางทีคุณอาจค้นหา FlogScript
mbomb007

7

ช่องว่าง 3 ตัวอักษร

STL

Sคือช่องว่างTคือแท็บและขึ้นLบรรทัดใหม่


นี่เป็นภาษาเต็มหรือเป็นส่วนย่อยหรือไม่ ข้อพิสูจน์ของทัวริงครบถ้วนที่ไหน
Brian Minton

2
@BrianMinton มันเป็นภาษาแบบเต็ม, The esolang wiki นั้นสว่างมากesolangs.org/wiki/Whitespaceแต่ afaik, มันกำลังจะเสร็จสมบูรณ์
Cruncher

7

แร็กเก็ต (Scheme) 4 ตัวอักษร

(λ)

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

ตัวอย่างเช่นที่นี่คือ combinator โอเมก้าคลาสสิกซึ่งวนซ้ำ

((λ (λλ) (λλ λλ)) (λ (λλ) (λλ λλ)))

6

Python 3, 9 ตัวอักษร

exc('%1+)

ดูคำตอบ Python 2ของฉันสำหรับคำอธิบายพื้นฐาน คำตอบนี้ต่อยอดจากสิ่งนั้น

แทนที่จะใช้ตัวอักษรเดียวกับ Python สองอย่างง่าย ๆ ด้วยการเพิ่ม()เราสามารถวางอักขระได้เนื่องจากตอนนี้เรามีการใช้วงเล็บ โปรแกรมจะยังคงมีรูปร่างพื้นฐานของ

exec('%c'%stuff)

แต่เราย่อโปรแกรมให้สั้นลงโดยใช้+แทน-และจากนั้นเราสามารถลบ~โดยใช้1แทน0ได้ จากนั้นเราจะสามารถเพิ่ม1, 11และ111จะได้รับค่า ASCII ที่จำเป็น

โปรแกรมprint()ดังต่อไปนี้จะสั้นที่สุด:

exec('%c%%c%%%%c%%%%%%%%c%%%%%%%%%%%%%%%%c%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%c%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%c'%(111+1)%(111+1+1+1)%(11+11+11+11+11+11+11+11+11+1+1+1+1+1+1)%(11+11+11+11+11+11+11+11+11+11)%(111+1+1+1+1+1)%'('%')')

ลองออนไลน์

คุณอาจคิดกับตัวเองว่าใครจะสร้าง NUL ไบต์โดยไม่ต้องได้0อย่างไร อย่ากลัวตั๊กแตนตัวน้อย! เพราะเรามีความสามารถในการใช้คณิตศาสตร์เป็นอย่างดีในการสร้างศูนย์%1%1


ทำไมคุณถึงต้องการ NUL ไบต์ในโปรแกรมของคุณ?
NieDzejkob

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

คุณไม่จำเป็นต้องมี NUL byte สำหรับทัวริงครบถ้วน ล่าม BF สามารถเขียนได้โดยไม่ต้องใช้หนึ่ง
MilkyWay90

@ MilkyWay90 จริง แต่ทำไมไม่ลองคิดดูถ้าคุณทำได้?
mbomb007

6

PHP 7, 6 ตัวอักษร

'().;^

แนวคิดก็คือมันเป็นไปได้ที่จะรันโค้ดโดยอำเภอใจโดยใช้โครงสร้างต่อไปนี้:

('create_function')('','<code>')();

eval จะไม่ทำงานที่นี่เพราะมันเป็นภาษาที่สร้างขึ้นและไม่สามารถเรียกได้ว่าใช้ฟังก์ชั่นตัวแปร

create_function และรหัสสามารถเขียนเป็นการเชื่อมต่อของ XORs ระดับบิตของอักขระที่มีอยู่:

(<char1_1>^<char1_2>^...).(<char2_1>^<char2_2>^...)...

ใช้().;^สำหรับ<charX_Y>เราจะได้รับ

()./:;<=JKLMXY^_bcdepqvw

และอักขระที่ไม่สามารถพิมพ์ได้บางส่วน ยังไม่พอ แต่ตอนนี้เราสามารถโทร'eXp'()และรับตัวอักษรตัวเลขได้เช่นกัน:

''.'eXp'('eXp'('')) -> 1
''.'eXp'('eXp'('eXp'(''))) -> 2.718281828459
''.'eXp'('eXp'('eXp'('eXp'('eXp'(''))))) -> 3814279.1047602

มันทำให้เรา1, 2และ3(ตัวละครอื่น ๆ จะได้รับการปฏิเสธโดยแฮคเกอร์ถ้าสตริงอื่น ๆ ที่เป็นตัวละครตัวหนึ่งยาว) จาก().;^123ตอนนี้เราสามารถสร้างชุดอักขระ ASCII ทั้งหมด

ลองออนไลน์


5

Pyke 5 ตัวอักษร

0h.CE

นี่คือความสามารถในการผลิตจำนวนมากอย่างไม่ จำกัด เปลี่ยนเป็นสตริงแล้วประเมินว่าเป็นรหัส Pyke

คำอธิบายของรหัส:

0- เพิ่ม 0 เข้ากับสแต็ก สิ่งนี้จำเป็นสำหรับการเริ่มต้นหมายเลข

h- เพิ่มจำนวนก่อน ด้วยการทำซ้ำนี้เป็นจำนวนครั้งโดยพลการคุณสามารถสร้างตัวเลขที่มีขนาดใหญ่มาก Pyke รองรับ bignums ตามที่เขียนไว้ใน Python ซึ่งใช้เป็นค่าเริ่มต้น

.C- เปลี่ยนตัวเลขให้เป็นสตริงโดยใช้อัลกอริทึมต่อไปนี้: ( ลิงก์ Github )

def to_string(num):
    string = ""
    while num > 256:
        num, new = divmod(num, 256)
        string = chr(new) + string
    string = chr(num) + string
    return string

ถึงตอนนี้เราสามารถสร้างจำนวนของสตริงและจำนวนธรรมชาติใน Pyke ได้ตามอำเภอใจ เบอร์ที่สามารถสร้างขึ้นในรูปแบบที่สอดคล้องกับ regex และสตริงสามารถสร้างขึ้นด้วย0(h)* 0(h)*.Cพวกเขาสามารถผสมเข้าด้วยกันเพื่อสร้างส่วนผสมของสตริงและจำนวนเต็มโดยพลการ

E- ประเมินสตริงเป็นรหัส Pyke สิ่งนี้ใช้สภาพแวดล้อมเดียวกันกับรหัส Pyke ที่ทำงานอยู่แล้วซึ่งจะแบ่งปันสิ่งต่างๆเช่นอินพุต

พยายามพิสูจน์ว่า Pyke กำลังทัวริงเสร็จสมบูรณ์

วิธีที่ง่ายที่สุดวิธีหนึ่งในการแสดงภาษาคือการทำให้ภาษาสมบูรณ์โดยใช้ Brainf * ck นี้อาจจะเป็นเรื่องยากใน Pyke กว่าภาษาอื่น ๆ อีกมากมายเพราะมันเป็นรายการและการดำเนินงานพจนานุกรมจะสวยมากไม่ได้มีอยู่เนื่องจากการขาดการต้องให้พวกเขาในพื้นที่ Pyke ถูกออกแบบมาเพื่อทำงานใน: รหัสกอล์ฟ

ประการแรกเราสร้างล่าม brainf * CK และเข้ารหัสโดยใช้อัลกอริทึมของเราด้านบนเพื่อสร้างตัวเลขแล้วแสดงตัวเลขที่มีและ0 hจากนั้นเราจะสร้างสตริงที่มีรหัสเพื่อให้ทำงานในลักษณะเดียวกัน ถ้าเราปล่อยมันไว้อย่างนั้นเราก็จะได้สแต็คเป็น

string containing brainf*ck code
string containing brainf*ck interpreter

ซึ่งหมายความว่ารหัสจะต้องอยู่ในรูปแบบตรงข้ามเนื่องจาก Pyke stack เป็นลำดับสุดท้ายก่อน

ตอนนี้เพื่อความสนุกสนาน: ล่ามสมอง * ck ที่มีขนาดใหญ่ถึง 216 ไบต์!

Q~B"><ht.,".:=B;Z]1=L;W~Bo@D=c"ht"{I~c~LZ@EZ]1~LR3:=L)~c\,qIz.oZ]1~LR3:=L)~c\.qI~LZ@.CpK)~c"<>"{I~c"<>""th".:ZE=ZZ1_qI0=Z~L0"":0]10:=L)Z~LlqI~L~Ll"":1_]10:=L))~c\[qI~LZ@0qI\]~B~o>@~o+h=o))~c\]qI~o\[~B~o<_@-t=o)~o~BlN

ลองที่นี่!

หากคุณต้องการลองใช้รหัสในรูปแบบกึ่งสมบูรณ์ แต่สามารถแก้ไขได้ลองที่นี่!

ในการแปลงจากสตริงเป็นตัวเลขคุณสามารถใช้รหัส Python ต่อไปนี้:

def conv(string, t=0):
    t *= 256
    t += ord(string[0])
    if len(string) != 1:
        return conv(string[1:], t)
    return t

วิธีแก้ปัญหาขั้นสุดท้าย (เกือบ) สามารถลองได้ที่นี่!

คำอธิบายของล่าม Brainf * ck

ก่อนอื่นให้แยกโปรแกรมออกเป็นส่วน ๆ :

  • การเริ่มต้น:

Q~B"><ht.,".:=B;Z]1=L; - The initialisation part
Q~B"><ht.,".:          - input.replace("><+-.,[]", "><ht.,")
                       - replace the characters in brainf*ck with some modified ones. 
                       - this means we can `eval` the add and subtract bits easily.
             =B;       - set `B` to this.
                       - The `B` variable contains the instructions
                Z]1=L; - set `L` to [0]
                       - `L` contains the stack, initialised with 0
  • วงหลัก:

​​ ​ ​

W~Bo@D=c !code! ~o~BlN - The main loop
W                      - do
 ~Bo@D=c               -  c=B[o++]
                       -  the c variable is used to store the current character.
                ~o~BlN - while
                ~o     -   o 
                     N -  ^ != V 
                  ~Bl  -   len(B)
                       -  this stops the program running once it's finished.
  • คำแนะนำ
    • เพิ่ม / ลด:+-

​​ ​ ​

"ht"{I~c~LZ@EZ]1~LR3:=L) - The bit that does incrementing and decrementing
"ht"{I                 ) - if c in "ht"
        ~LZ@             -  L[Z]
                         -  `Z` contains the current stack pointer
      ~c    E            -  eval current character with ^ as an argument
                         -  returns the contents of `Z` either incremented or decremented
             Z]1~LR3:=L  - L[Z] = ^
  • อินพุต,::

​​ ​ ​

~c\,qIz.oZ]1~LR3:=L) - The code for output 
~c\,qI             ) -  if character == ",":
      z.o            -    ord(input)
         Z]1~LR3:=L  -   L[Z] = ^
  • เอาท์พุท.::

​​ ​ ​

~c\.qI~LZ@.CpK) - The code for input 
~c\.qI        ) - if c == ".":
      ~LZ@      -    L[Z]
          .C    -   chr(^)
            pK  -  print(^)
  • เลื่อนซ้าย / ขวา<>::

​​ ​ ​

~c"<>"{I~c"<>""th".:ZE=Z - main part 
~c"<>"{I                 - if "<>" in c:
        ~c"<>""th".:     -  c.replace("<>", "th")
                    ZE=Z -  Z = eval(char, Z)

Z1_qI0=Z~L0"":0]10:=L) - lower bound check
Z1_qI                ) - if Z == -1:
     0=Z               -  Z = 0
        ~L0"":         -  L.insert("", 0)
              0]10:=L  -  L[0] = 0

Z~LlqI~L~Ll"":1_]10:=L) - upper bound check
Z~LlqI                ) - if Z == len(L):
        ~Ll"":          -  L.insert("", len(L))
      ~L      1_]10:=L  -  L[-1] = 0
  • เงื่อนไข[::

​​ ​ ​

~c\[qI~LZ@0qI\]~B~o>@~o+h=o)) - Code for `[`
~c\[qI                      ) - if c == "[":
      ~LZ@0qI              )  -  if L[Z] == 0:
               ~B~o>          -     B[o:]
             \]     @         -    ^.find("]")
                     ~o+h=o   -   o = o + ^ + 1

- และ]:

​​ ​ ​

~c\]qI~o\[~B~o<_@-t=o) - Code for `]`
~c\]qI               ) - if c == "]":
          ~B~o<_       -    reversed(B[:o])
        \[      @      -   ^.find("[")
      ~o         -t=o  -  o = o - ^ -1

5

ซ้อนกัน 5 ตัวอักษร

{!n:}

มันสั้นอย่างน่าประหลาดใจ หาก Stacked สามารถนำชุดค่าผสม SKI แต่ละชุดมารวมกันได้จะเป็นการทำให้เสร็จสมบูรณ์ สรุป:

  • I combinator - ฟังก์ชันเอกลักษณ์ x -> x
  • K combinator - ฟังก์ชั่นคงที่ x -> y -> x
  • S combinator - ฟังก์ชันการแทนที่ (x, y, z) -> x(z)(y(z))

ฉัน combinator: {!n}

ตอนนี้สำหรับสแต็คเฉพาะ {! ... }คือ n-lambda nมันเป็นฟังก์ชั่นที่มีเอกอาร์กิวเมนต์เป็นโดยปริยาย จากนั้นนิพจน์สุดท้ายจะถูกส่งคืนจากฟังก์ชัน ดังนั้นจึง{!n}เป็นฟังก์ชันที่ใช้เวลาอาร์กิวเมนต์และอัตราผลตอบแทนnn

K combinator: {!{:n}}

ตอนนี้เป็นฟังก์ชั่นที่ใช้เวลาการขัดแย้งใดและผลตอบแทน{:...} ...เมื่อรวมสิ่งนี้เข้ากับการสร้าง n-lambda ของเราเราจะได้รับ (เพิ่มช่องว่างเพื่อความชัดเจน):

{! { : n } }
{!         }   n-lambda. arguments: (n)
   { : n }     lambda.   arguments: ()
       n       yields n.

S Combinator: {n!nn!nnn:nnn{!n}!nn!nnn{!n}!n!!}

ตกลงนี่ดูซับซ้อนกว่าเล็กน้อย ดังนั้นแลมบ์ดารับอาร์กิวเมนต์คั่นด้วยอักขระที่ไม่ใช่ตัวระบุ ดังนั้นแลมบ์ดาในส่วนหัวจึงเท่ากับ:

{n nn nnn:nnn{!n}!nn!nnn{!n}!n!!}

นี่คือแลมบ์ดาที่ต้องใช้เวลาสามข้อโต้แย้ง, n, และnn nnnลองเปลี่ยนเหล่านี้ด้วยx, yและzเพื่อความชัดเจน:

{x y z:z{!n}!y!z{!n}!x!!}

ทั้งสอง{!n}!เป็นเพียงฟังก์ชั่นเอกลักษณ์เพื่อหลีกเลี่ยงช่องว่างอีกครั้งซึ่ง!หมายความว่า "รัน" ดังนั้นลดอีกครั้ง:

{x y z:z y!z x!!}

ด้วยคำอธิบาย:

{x y z:z y!z x!!}
{x y z:         }  three arguments
       z y!        apply `y` to `z` -- `y(z)`
           z x!    apply `x` to `z` -- `x(z)`
               !   apply `x(z)` to `y(z)` -- `x(z)(y(z))`

และนี่คือ combinator S


{n nn nnn:nnn{!n}!nn!nnn{!n}!n!!}มีช่องว่าง
CalculatorFeline

@CalculatorFeline คุณอ่านประโยคก่อนหน้านี้หรือไม่? ตกลงนี่ดูซับซ้อนกว่าเล็กน้อย ดังนั้นแลมบ์ดารับอาร์กิวเมนต์คั่นด้วยอักขระที่ไม่ใช่ตัวระบุ ดังนั้นแลมบ์ดาในส่วนหัวจึงเท่ากับ:
Conor O'Brien

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