TeX, 216 ไบต์ (4 บรรทัด, 54 ตัวอักษร)
เพราะมันไม่เกี่ยวกับจำนวนไบต์มันเกี่ยวกับคุณภาพของการเรียงพิมพ์ :-)
{\let~\catcode~`A13 \defA#1{~`#113\gdef}AGG#1{~`#1 13%
\global\let}GFF\elseGHH\fiAQQ{Q}AII{\ifxQ}AEE#1#2#3|{%
I#3#2#1FE{#1#2}#3|H}ADD#1#2|{I#1FE{}#1#2|H}ACC#1#2|{D%
#2Q|#1 }ABBH#1 {HI#1FC#1|BH}\gdef\S#1{\iftrueBH#1 Q }}
ลองออนไลน์! (Overleaf ไม่แน่ใจว่ามันทำงานอย่างไร)
ไฟล์ทดสอบเต็มรูปแบบ:
{\let~\catcode~`A13 \defA#1{~`#113\gdef}AGG#1{~`#1 13%
\global\let}GFF\elseGHH\fiAQQ{Q}AII{\ifxQ}AEE#1#2#3|{%
I#3#2#1FE{#1#2}#3|H}ADD#1#2|{I#1FE{}#1#2|H}ACC#1#2|{D%
#2Q|#1 }ABBH#1 {HI#1FC#1|BH}\gdef\S#1{\iftrueBH#1 Q }}
\S{swap the a first and last letters of each word}
pwas eht a tirsf dna tasl setterl fo hace dorw
\S{SWAP THE A FIRST AND LAST LETTERS OF EACH WORD}
\bye
เอาท์พุท:

สำหรับ LaTeX คุณเพียงแค่ต้องการแผ่นสำเร็จรูป:
\documentclass{article}
\begin{document}
{\let~\catcode~`A13 \defA#1{~`#113\gdef}AGG#1{~`#1 13%
\global\let}GFF\elseGHH\fiAQQ{Q}AII{\ifxQ}AEE#1#2#3|{%
I#3#2#1FE{#1#2}#3|H}ADD#1#2|{I#1FE{}#1#2|H}ACC#1#2|{D%
#2Q|#1 }ABBH#1 {HI#1FC#1|BH}\gdef\S#1{\iftrueBH#1 Q }}
\S{swap the a first and last letters of each word}
pwas eht a tirsf dna tasl setterl fo hace dorw
\S{SWAP THE A FIRST AND LAST LETTERS OF EACH WORD}
\end{document}
คำอธิบาย
TeX เป็นสัตว์ร้าย การอ่านโค้ดปกติและเข้าใจมันเป็นความสำเร็จด้วยตัวเอง การทำความเข้าใจกับรหัส TeX ที่สับสนนั้นไปอีกไม่กี่ก้าว ฉันจะพยายามทำให้สิ่งนี้เข้าใจได้สำหรับผู้ที่ไม่รู้จัก TeX เช่นกันดังนั้นก่อนที่เราจะเริ่มต้นที่นี่มีแนวคิดบางประการเกี่ยวกับ TeX ที่จะทำให้การติดตามเป็นเรื่องง่ายขึ้น:
สำหรับผู้เริ่มต้น TeX แบบสัมบูรณ์
รายการแรกและสำคัญที่สุดในรายการนี้: รหัสไม่จำเป็นต้องอยู่ในรูปสี่เหลี่ยมผืนผ้าแม้ว่า วัฒนธรรมป๊อป อาจทำให้คุณ คิดเช่นนั้น
TeX เป็นภาษาส่วนขยายของแมโคร ยกตัวอย่างเช่นคุณสามารถกำหนด\def\sayhello#1{Hello, #1!}และเขียน\sayhello{Code Golfists}เพื่อให้ TeX พิมพ์Hello, Code Golfists!ได้ สิ่งนี้เรียกว่า“ มาโครที่ไม่ถูก จำกัด ” และเพื่อให้ฟีดพารามิเตอร์แรก (และเฉพาะในกรณีนี้) ที่คุณใส่ไว้ในวงเล็บ TeX ลบวงเล็บปีกกาเหล่านั้นเมื่อแมโครคว้าอาร์กิวเมนต์ คุณสามารถใช้งานได้ถึง 9 พารามิเตอร์แล้ว\def\say#1#2{#1, #2!}\say{Good news}{everyone}
คู่ของแมโคร undelimited จะแปลกใจคนคั่น :) คุณสามารถทำให้คำนิยามก่อนหน้าตาดเพิ่มเติมsemantical\def\say #1 to #2.{#1, #2!} : ในกรณีนี้พารามิเตอร์ที่จะตามมาด้วยสิ่งที่เรียกว่าข้อความพารามิเตอร์ ข้อความพารามิเตอร์ดังกล่าวคั่นอาร์กิวเมนต์ของแมโคร ( #1คั่นด้วย␣to␣, รวมช่องว่างและ#2คั่นด้วย.) หลังจากที่ความหมายที่คุณสามารถเขียนซึ่งจะขยายตัวออกไป\say Good news to everyone. Good news, everyone!ดีใช่มั้ย :) อย่างไรก็ตามอาร์กิวเมนต์ที่มีการคั่นคือ (อ้างถึงTeXbook )“ ลำดับที่สั้นที่สุด (อาจว่างเปล่า) ของโทเค็นที่มี{...}กลุ่มซ้อนกันอย่างเหมาะสมที่ตามมาในการป้อนข้อมูลโดยรายการเฉพาะของโทเค็นที่ไม่ใช่พารามิเตอร์นี้ " ซึ่งหมายความว่าการขยายตัวของ\say Let's go to the mall to Martinจะสร้างประโยคแปลก ๆ ในกรณีนี้คุณจะต้อง“ซ่อน” ครั้งแรก␣to␣กับ:{...}\say {Let's go to the mall} to Martin
จนถึงตอนนี้ดีมาก ตอนนี้ทุกอย่างเริ่มแปลก ๆ เมื่อ TeX อ่านตัวอักษร (ซึ่งถูกกำหนดโดย“ รหัสตัวอักษร”) มันจะกำหนดตัวอักษรนั้นเป็น“ รหัสหมวดหมู่” (catcode สำหรับเพื่อน ๆ :) ซึ่งจะกำหนดความหมายของตัวละครนั้น การรวมกันของตัวละครและรหัสหมวดหมู่นี้ทำให้โทเค็น (ตัวอย่างเพิ่มเติมที่นี่ ) คนที่น่าสนใจสำหรับเราที่นี่เป็นพื้น:
catcode 11ซึ่งกำหนดโทเค็นซึ่งสามารถสร้างลำดับการควบคุม (ชื่อ posh สำหรับแมโคร) โดยค่าเริ่มต้นตัวอักษรทั้งหมด [a-zA-Z] เป็น catcode 11 ดังนั้นฉันสามารถเขียน\helloซึ่งเป็นหนึ่งในลำดับการควบคุมเดียวในขณะ\he11oที่ลำดับการควบคุม\heตามด้วยอักขระสองตัว1ตามด้วยตัวอักษรoเพราะ1ไม่ใช่ catcode 11 ถ้าฉัน ได้\catcode`1=11จากจุด\he11oนั้นไปเป็นลำดับการควบคุมหนึ่ง สิ่งหนึ่งที่สำคัญคือการที่มีการตั้งค่า catcodes เมื่อเท็กซ์แรกที่เห็นตัวละครที่อยู่ในมือและ catcode ดังกล่าวเป็นแช่แข็ง ... ตลอดไป! (ข้อกำหนดและเงื่อนไขอาจนำมาใช้)
catcode 12ซึ่งเป็นอักขระส่วนใหญ่เช่น0"!@*(?,.-+/และอื่น ๆ พวกมันเป็นประเภท catcode พิเศษที่น้อยที่สุดเพราะมันทำหน้าที่สำหรับการเขียนเนื้อหาบนกระดาษเท่านั้น แต่เดี๋ยวก่อนใครใช้ TeX ในการเขียน?!? (อาจมีข้อกำหนดและเงื่อนไขอีกครั้ง)
catcode 13ซึ่งเป็นนรก :) จริง ๆ หยุดอ่านและไปทำอะไรบางอย่างในชีวิตของคุณ คุณไม่ต้องการที่จะรู้ว่า catcode 13 คืออะไร เคยได้ยินวันศุกร์ที่ 13 ไหม ลองเดาดูว่ามันได้ชื่อมาจากไหน! ดำเนินการต่อด้วยความเสี่ยงของคุณเอง! catcode 13 ตัวละครหรือที่เรียกว่าตัวละคร“ แอคทีฟ” ไม่ได้เป็นเพียงตัวละครอีกต่อไปมันเป็นมาโครเอง คุณสามารถกำหนดให้มีพารามิเตอร์และขยายไปยังสิ่งที่เราเห็นด้านบน หลังจากที่คุณทำ\catcode`e=13คุณคิดว่าคุณสามารถทำได้\def e{I am the letter e!}แต่ คุณ. ไม่ได้! eไม่ใช่ตัวอักษรอีกต่อไปดังนั้น\defไม่ใช่\defคุณรู้ว่ามันเป็น\d e f! โอ้เลือกจดหมายอีกฉบับที่คุณพูด? เอาล่ะ! \catcode`R=13 \def R{I am an ARRR!}. เยี่ยมมากจิมมี่ลองสิ! ฉันกล้าที่คุณทำและเขียนRในรหัสของคุณ! นั่นคือสิ่งที่ catcode 13 เป็น ฉันใจเย็น! ไปกันเถอะ
โอเคตอนนี้เพื่อจัดกลุ่ม ค่อนข้างตรงไปตรงมา สิ่งที่ได้รับมอบหมาย ( \defเป็นการดำเนินการที่ได้รับมอบหมาย\let(เราจะเข้าสู่มัน) เป็นอีกสิ่งหนึ่ง) ที่ทำในกลุ่มจะถูกเรียกคืนเป็นสิ่งที่พวกเขาเคยทำก่อนที่กลุ่มนั้นจะเริ่มต้นเว้นแต่ว่าการมอบหมายนั้นจะเป็นระดับโลก มีหลายวิธีในการเริ่มกลุ่มโดยหนึ่งในนั้นคือ catcode 1 และ 2 ตัวอักษร (โอ้ catcodes อีกครั้ง) โดยค่าเริ่มต้น{คือ catcode 1 หรือกลุ่มเริ่มต้นและ}เป็น catcode 2 หรือกลุ่มปลาย ตัวอย่าง: \def\a{1} \a{\def\a{2} \a} \aพิมพ์1 2 1นี้ นอกกลุ่ม\aเป็น1แล้วภายในนั้นถูกนิยามใหม่ไปและเมื่อกลุ่มสิ้นสุดวันที่มันจะถูกเรียกคืนไป21
การ\letดำเนินการเป็นการดำเนินการที่ได้รับมอบหมายอื่น\defแต่แตกต่างกันมาก เมื่อ\defคุณกำหนดมาโครที่จะขยายไปยังสิ่งของ\letคุณจะสร้างสำเนาของสิ่งที่มีอยู่แล้ว หลังจาก\let\blub=\def( =เป็นตัวเลือก) คุณสามารถเปลี่ยนการเริ่มต้นeตัวอย่างจากรายการ catcode 13 ด้านบนเป็น\blub e{...และสนุกกับสิ่งนั้น หรือดีกว่าแทนการทำลายสิ่งที่คุณสามารถแก้ไข (คุณจะดูที่!) ด้วยเช่น:R \let\newr=R \catcode`R=13 \def R{I am an A\newr\newr\newr!}คำถามด่วน: คุณสามารถเปลี่ยนชื่อเป็น\newR?
ในที่สุดสิ่งที่เรียกว่า "ช่องว่างปลอม" นี่เป็นหัวข้อที่ต้องห้ามเพราะมีคนที่อ้างว่าชื่อเสียงที่ได้รับจากTeX - LaTeX Stack Exchangeโดยการตอบคำถาม "ช่องว่างปลอม" ไม่ควรได้รับการพิจารณาในขณะที่คนอื่นไม่เห็นด้วยอย่างสุดใจ คุณเห็นด้วยกับใคร วางเดิมพันของคุณ! ในขณะเดียวกัน: TeX เข้าใจการแตกบรรทัดเป็นพื้นที่ ลองเขียนหลาย ๆ คำโดยใช้ตัวแบ่งบรรทัด (ไม่ใช่บรรทัดว่าง ) ระหว่างคำเหล่านั้น ตอนนี้เพิ่ม a %ท้ายบรรทัดเหล่านี้ มันเหมือนกับว่าคุณกำลัง“ คอมเม้นท์” จุดสิ้นสุดของบรรทัดเหล่านี้ แค่นั้นแหละ :)
(เรียงจาก) ถอดรหัสออก
ให้สี่เหลี่ยมผืนผ้านั้นเป็นสิ่งที่ง่ายขึ้น (ตามเนื้อหา):
{
\let~\catcode
~`A13
\defA#1{~`#113\gdef}
AGG#1{~`#113\global\let}
GFF\else
GHH\fi
AQQ{Q}
AII{\ifxQ}
AEE#1#2#3|{I#3#2#1FE{#1#2}#3|H}
ADD#1#2#3|{I#2FE{#1}#2#3|H}
ACC#1#2|{D{}#2Q|#1 }
ABBH#1 {HI#1FC#1|BH}
\gdef\S#1{\iftrueBH#1 Q }
}
คำอธิบายของแต่ละขั้นตอน
แต่ละบรรทัดมีหนึ่งคำสั่งเดียว ไปทีละคนแล้วผ่าพวกเขา:
{
ก่อนอื่นเราเริ่มกลุ่มเพื่อให้การเปลี่ยนแปลงบางอย่าง (เช่นการเปลี่ยนแปลง catcode) อยู่ในเครื่องเพื่อไม่ให้สับสนกับข้อความที่ป้อนเข้า
\let~\catcode
โดยทั่วไปทุกรหัสเท็กซ์ obfuscation เริ่มต้นด้วยการเรียนการสอนนี้ โดยค่าเริ่มต้นทั้งใน TeX ธรรมดาและ LaTeX ~ตัวละครเป็นตัวละครที่ใช้งานหนึ่งตัวซึ่งสามารถทำเป็นแมโครเพื่อใช้งานต่อไป และเครื่องมือที่ดีที่สุดสำหรับ weirdifying รหัส TeX คือการเปลี่ยนแปลง catcode ดังนั้นโดยทั่วไปนี่เป็นตัวเลือกที่ดีที่สุด ตอนนี้แทนที่จะ\catcode`A=13เราสามารถเขียน~`A13( =เป็นตัวเลือก):
~`A13
ตอนนี้ตัวอักษรAเป็นตัวละครที่ใช้งานอยู่และเราสามารถกำหนดให้ทำอะไรบางอย่าง:
\defA#1{~`#113\gdef}
Aเป็นแมโครที่รับอาร์กิวเมนต์หนึ่งตัว (ซึ่งควรเป็นอักขระอื่น) แรก catcode ของการโต้แย้งที่มีการเปลี่ยนแปลงถึง 13 ที่จะทำให้มันใช้งาน: ~`#113(แทนที่~โดย\catcodeและเพิ่ม=และคุณมี: \catcode`#1=13) ในที่สุดก็ปล่อยให้\gdef(โกลบอล\def) ในอินพุตสตรีม ในระยะสั้นAทำให้ตัวละครอื่นที่ใช้งานและเริ่มต้นการกำหนด มาลองดูกัน:
AGG#1{~`#113\global\let}
AGเริ่มแรก "เปิดใช้งาน" Gและทำ\gdefซึ่งตามด้วยถัดไปGเริ่มต้นคำจำกัดความ คำจำกัดความของGคล้ายกับของAยกเว้นว่าแทนที่จะ\gdefเป็น\global\let(ไม่มีไม่\gletเหมือน\gdef) ในระยะสั้นGเปิดใช้งานตัวละครและทำให้มันเป็นอย่างอื่น ลองทำทางลัดสำหรับสองคำสั่งที่เราจะใช้ในภายหลัง:
GFF\else
GHH\fi
ตอนนี้แทน\elseและ\fiเราก็สามารถใช้และF Hสั้นกว่ามาก :)
AQQ{Q}
ตอนนี้เราใช้Aอีกครั้งเพื่อกำหนดแมโครอื่น, Q. ข้อความข้างต้นโดยทั่วไปจะ \def\Q{\Q}(ในภาษาที่เข้าใจยากน้อยกว่า) นี่ไม่ใช่คำจำกัดความที่น่าสนใจอย่างยิ่ง แต่มันมีคุณสมบัติที่น่าสนใจ ยกเว้นว่าคุณต้องการทำลายรหัสบางส่วนแมโครเดียวที่ขยายQเป็นของQตัวเองดังนั้นมันจึงทำหน้าที่เหมือนเครื่องหมายที่ไม่ซ้ำกัน (เรียกว่าควาร์ก ) คุณสามารถใช้\ifxเงื่อนไขเพื่อทดสอบว่าอาร์กิวเมนต์ของแมโครนั้นเป็นควาร์กดังกล่าวด้วย\ifx Q#1:
AII{\ifxQ}
เพื่อให้คุณมั่นใจได้ว่าคุณพบเครื่องหมายดังกล่าว ขอให้สังเกตว่าในความหมายนี้ฉันลบช่องว่างระหว่างและ\ifx Qโดยปกติสิ่งนี้จะนำไปสู่ข้อผิดพลาด (โปรดทราบว่าการเน้นไวยากรณ์คิดว่า\ifxQเป็นเรื่องหนึ่ง) แต่เนื่องจากขณะนี้Qcatcode 13 ไม่สามารถสร้างลำดับการควบคุมได้ ระวัง แต่ไม่ได้ที่จะขยายควาร์กนี้หรือคุณจะได้รับการติดอยู่ในวง จำกัด เพราะQการขยายตัวในการQที่จะขยายQซึ่ง ...
ตอนนี้การแข่งขันรอบแรกเสร็จสิ้นแล้วเราสามารถไปยังอัลกอริทึมที่เหมาะสมกับ pwas eht setterl เนื่องจากโทเค็นของ TeX จะต้องเขียนอัลกอริทึมไปข้างหลัง นี่เป็นเพราะในเวลาที่คุณทำการกำหนด TeX จะทำเครื่องหมาย (กำหนด catcodes) ให้กับตัวละครในการกำหนดโดยใช้การตั้งค่าปัจจุบันดังนั้นตัวอย่างเช่นถ้าฉันทำ:
\def\one{E}
\catcode`E=13\def E{1}
\one E
ผลลัพธ์คือE1ในขณะที่ถ้าฉันเปลี่ยนลำดับของคำจำกัดความ:
\catcode`E=13\def E{1}
\def\one{E}
\one E
11ผลลัพธ์คือ นี่เป็นเพราะในตัวอย่างแรกEคำนิยามในโทเค็นเป็นตัวอักษร (catcode 11) ก่อนที่ catcode จะเปลี่ยนดังนั้นมันจะเป็นตัวอักษรEเสมอ ในตัวอย่างที่สอง แต่Eเป็นครั้งแรกที่ใช้งานและเพียงแล้ว\oneถูกกำหนดและตอนนี้ความหมายมี catcode 13 ซึ่งจะขยายE1
อย่างไรก็ตามฉันจะมองข้ามข้อเท็จจริงนี้และจัดลำดับคำจำกัดความใหม่เพื่อให้ได้คำสั่งแบบตรรกะ (แต่ไม่ทำงาน) ในย่อหน้าต่อไปนี้คุณสามารถสมมติว่าตัวอักษรB, C, DและEมีการใช้งาน
\gdef\S#1{\iftrueBH#1 Q }
(สังเกตว่ามีข้อผิดพลาดเล็ก ๆ ในรุ่นก่อนหน้านี้มันไม่ได้มีช่องว่างสุดท้ายในคำนิยามข้างต้นฉันสังเกตเห็นเพียงในขณะที่เขียนนี้อ่านต่อไปและคุณจะเห็นว่าทำไมเราต้องการที่จะยุติแมโครอย่างถูกต้อง ) ครั้งแรกที่เรากำหนดแมโครระดับผู้ใช้
\Sหนึ่งนี้ไม่ควรจะเป็นตัวละครที่ใช้งานให้มีความเป็นมิตร (?) ไวยากรณ์ดังนั้นแมโครสำหรับ gwappins EHT setterl \Sมี แมโครเริ่มต้นด้วยเงื่อนไขที่เป็นจริงเสมอ\iftrue(ในไม่ช้ามันก็จะชัดเจนว่าทำไม) แล้วเรียกBแมโครตามด้วยH(ซึ่งเรากำหนดไว้ก่อนหน้านี้เพื่อ\fiให้ตรงกับ\iftrue) จากนั้นเราจะออกจากข้อโต้แย้งของแมโครตามด้วยช่องว่างและควาร์ก#1 Qสมมติว่าเราใช้\S{hello world}แล้วสตรีมอินพุตควรมีลักษณะดังนี้: \iftrue BHhello world Q␣(ฉันแทนที่พื้นที่สุดท้ายด้วย␣เพื่อให้การแสดงผลของไซต์ไม่กินมันเหมือนที่ฉันทำในรหัสรุ่นก่อนหน้า) เป็นความจริงดังนั้นจึงขยายตัวและเราจะเหลือ\iftrue BHhello world Q␣TeX จะไม่ลบ\fi( H) หลังจากเงื่อนไขถูกประเมิน แต่จะปล่อยไว้ที่นั่นจนกว่า\fiจะขยายออกจริง ตอนนี้Bแมโครถูกขยาย:
ABBH#1 {HI#1FC#1|BH}
Bเป็นแมโครที่คั่นด้วยข้อความพารามิเตอร์H#1␣ดังนั้นอาร์กิวเมนต์จึงเป็นสิ่งที่อยู่ระหว่างHและเว้นวรรค อย่างต่อเนื่องตัวอย่างข้างต้นสตรีมใส่ก่อนที่จะมีการขยายตัวของมีB ตามด้วยตามที่ควร (มิฉะนั้นเท็กซ์จะยกข้อผิดพลาด) แล้วพื้นที่ต่อไปคือระหว่างและเพื่อให้เป็นคำว่า และที่นี่เราต้องแยกข้อความอินพุตที่ช่องว่าง ยาย: D การขยายตัวของเอาทุกอย่างขึ้นอยู่กับพื้นที่เป็นครั้งแรกจากสตรีมใส่และแทนที่โดยมีเป็น: โปรดสังเกตว่ามีใหม่ในสตรีมอินพุตในภายหลังเพื่อทำการวนรอบแบบซ้ำBHhello world Q␣BHhelloworld#1helloBHI#1FC#1|BH#1helloHIhelloFChello|BHworld Q␣BHBและประมวลผลคำภายหลัง หลังจากคำนี้มีการประมวลผลกระบวนการคำถัดไปจนกว่าจะมีคำพูดเพื่อจะประมวลผลเป็นควาร์กB Qต้องการพื้นที่สุดท้ายหลังQเนื่องจากแมโครที่B มีการคั่นต้องการหนึ่งที่ท้ายอาร์กิวเมนต์ ด้วยเวอร์ชันก่อนหน้า (ดูประวัติการแก้ไข) รหัสจะทำงานผิดปกติหากคุณใช้\S{hello world}abc abc(ช่องว่างระหว่างabcs จะหายไป)
HIhelloFChello|BHworld Q␣ตกลงกลับไปยังสตรีมใส่: ครั้งแรกที่มีเป็นH( \fi) \iftrueที่เสร็จสิ้นการเริ่มต้น ตอนนี้เรามีสิ่งนี้ (ปลอม):
I
hello
F
Chello|B
H
world Q␣
การI...F...Hคิดเป็น\ifx Q...\else...\fiโครงสร้างจริงๆ การ\ifxทดสอบจะตรวจสอบว่าคำศัพท์ (โทเค็นแรกของคำศัพท์) นั้นถูกจับQหรือไม่ หากไม่มีสิ่งใดที่ต้องทำและการดำเนินการสิ้นสุดลงมิฉะนั้นสิ่งที่เหลืออยู่คือ: Chello|BHworld Q␣. ตอนนี้Cถูกขยาย:
ACC#1#2|{D#2Q|#1 }
อาร์กิวเมนต์แรกของการCเป็น undelimited ดังนั้นถ้ายันมันจะเป็นโทเค็นเดียวอาร์กิวเมนต์ที่สองจะถูกคั่นด้วย|ดังนั้นหลังจากการขยายตัวของC(ที่มี#1=hและ#2=ello) DelloQ|h BHworld Q␣สตรีมใส่เป็น: ขอให้สังเกตว่าคนอื่น|ใส่ที่นั่นและhจากhelloนั้นก็ใส่หลังจากนั้น การสลับเปลี่ยนครึ่งหนึ่งเสร็จสิ้น ตัวอักษรตัวแรกอยู่ท้าย ใน TeX นั้นง่ายต่อการคว้าโทเค็นแรกของรายการโทเค็น แมโครง่ายได้รับตัวอักษรตัวแรกเมื่อคุณใช้\def\first#1#2|{#1} \first hello|อันสุดท้ายเป็นปัญหาเพราะ TeX คว้ารายการโทเค็นที่เล็กที่สุดและว่างเปล่าว่าเป็นอาร์กิวเมนต์ดังนั้นเราจึงต้องแก้ไขปัญหาบางอย่าง รายการถัดไปในรายการโทเค็นคือD:
ADD#1#2|{I#1FE{}#1#2|H}
Dมาโคร
นี้เป็นหนึ่งในการแก้ไขและมีประโยชน์ในกรณีเดียวที่คำนั้นมีตัวอักษรเดียว สมมติว่าแทนการที่เรามีhello xในกรณีนี้กระแสอินพุทจะเป็นDQ|xแล้วDจะขยายตัว (ที่มี#1=Qและ#2ที่ว่างเปล่า) IQFE{}Q|Hxไปที่: นี้คล้ายกับบล็อกI...F...H( \ifx Q...\else...\fi) ในBซึ่งจะเห็นว่าอาร์กิวเมนต์เป็นควาร์กและจะขัดจังหวะการดำเนินการออกจากxการเรียงพิมพ์เท่านั้น ในกรณีอื่น ๆ (กลับไปhelloเป็นต้น) Dจะขยายตัว (ที่มี#1=eและ#2=lloQ) IeFE{}elloQ|Hh BHworld Q␣เพื่อ: อีกครั้งI...F...HจะตรวจสอบQแต่จะล้มเหลวและใช้สาขา:\else E{}elloQ|Hh BHworld Q␣ตอนนี้ชิ้นสุดท้ายของสิ่งนี้,E มาโครจะขยาย:
AEE#1#2#3|{I#3#2#1FE{#1#2}#3|H}
ข้อความพารามิเตอร์ที่นี่ค่อนข้างคล้ายกับCและD; การขัดแย้งครั้งแรกและครั้งที่สองจะ undelimited |และคนสุดท้ายที่ถูกคั่นด้วย กระแสการป้อนข้อมูลลักษณะเช่นนี้E{}elloQ|Hh BHworld Q␣แล้วEการขยายตัว (มี#1ที่ว่างเปล่า#2=eและ):#3=lloQ IlloQeFE{e}lloQ|HHh BHworld Q␣อีกประการหนึ่งI...F...Hการตรวจสอบบล็อกควาร์ก (ซึ่งเห็นlและผลตอบแทน):false E{e}lloQ|HHh BHworld Q␣ตอนนี้Eขยายตัวอีกครั้ง (ด้วยความ#1=eว่างเปล่า#2=lและ):#3=loQ และอีกครั้งIloQleFE{el}loQ|HHHh BHworld Q␣ I...F...Hแมโครไม่ซ้ำอีกไม่กี่จนกว่าQจะพบในที่สุดและtrueสาขาจะได้รับการ: E{el}loQ|HHHh BHworld Q␣-> IoQlelFE{ell}oQ|HHHHh BHworld Q␣-> ->E{ell}oQ|HHHHh BHworld Q␣ ตอนนี้ควาร์กพบและขยายตัวตามเงื่อนไขเพื่อ:IQoellFE{ello}Q|HHHHHh BHworld Q␣ oellHHHHh BHworld Q␣วุ้ย.
โอ้เดี๋ยวก่อนพวกนี้คืออะไร? ตัวอักษรปกติ? โอ้เด็ก! ตัวอักษรเป็นที่สุดพบและเท็กซ์เขียนลงoellแล้วพวงของH( \fi) ที่พบและการขยายตัว (เพื่ออะไร) oellh BHworld Q␣ออกจากสตรีมใส่ด้วย: ตอนนี้คำแรกมีตัวอักษรตัวแรกและตัวสุดท้ายสลับและสิ่งที่ TeX พบต่อไปคืออีกคำBเพื่อทำซ้ำกระบวนการทั้งหมดสำหรับคำถัดไป
}
ในที่สุดเราก็สิ้นสุดกลุ่มเริ่มต้นที่นั่นเพื่อให้การมอบหมายงานในพื้นที่ทั้งหมดถูกยกเลิก การกำหนดท้องถิ่นคือการเปลี่ยนแปลง catcode ของตัวอักษรA, B, C... ซึ่งได้ทำแมโครเพื่อให้พวกเขากลับไปที่ความหมายตัวอักษรปกติและสามารถใช้ได้อย่างปลอดภัยในข้อความ และนั่นคือมัน ตอนนี้\Sแมโครที่นิยามไว้ด้านหลังจะทำให้เกิดการประมวลผลข้อความดังกล่าว
สิ่งหนึ่งที่น่าสนใจเกี่ยวกับรหัสนี้คือมันสามารถขยายได้อย่างเต็มที่ นั่นคือคุณสามารถใช้มันได้อย่างปลอดภัยในการเคลื่อนย้ายข้อโต้แย้งโดยไม่ต้องกังวลว่ามันจะระเบิด คุณสามารถใช้รหัสเพื่อตรวจสอบว่าตัวอักษรตัวสุดท้ายของคำนั้นเหมือนกับตัวที่สอง (ไม่ว่าด้วยเหตุผลใดก็ตามที่คุณต้องการ) ในการ\ifทดสอบ:
\if\S{here} true\else false\fi % prints true (plus junk, which you would need to handle)
\if\S{test} true\else false\fi % prints false
ขออภัยสำหรับคำอธิบายที่มากเกินไป ฉันพยายามทำให้มันชัดเจนที่สุดสำหรับ TeXies ที่ไม่ใช่ :)
สรุปสำหรับคนใจร้อน
แมโคร\Sprepends การป้อนข้อมูลด้วยตัวใช้งานที่คว้ารายการของสัญญาณที่คั่นด้วยช่องว่างสุดท้ายและผ่านพวกเขาไปB ใช้โทเค็นแรกในรายการนั้นและย้ายไปยังจุดสิ้นสุดของรายการโทเค็นและขยายด้วยสิ่งที่เหลืออยู่ ตรวจสอบว่า“ สิ่งที่เหลืออยู่” นั้นว่างเปล่าหรือไม่ซึ่งในกรณีนี้จะพบคำตัวอักษรเดียวแล้วไม่ทำอะไรเลย มิฉะนั้นการขยายตัว วนรอบรายการโทเค็นจนกระทั่งพบตัวอักษรตัวสุดท้ายในคำเมื่อพบว่าออกจากตัวอักษรตัวสุดท้ายตามด้วยคำกลางซึ่งตามด้วยตัวอักษรตัวแรกที่เหลือในตอนท้ายของกระแสโทเค็นด้วย.CCDDEEC
Hello, world!กลายเป็น,elloH !orldw(การสลับเครื่องหมายวรรคตอนเป็นตัวอักษร) หรือoellH, dorlw!(ใช้เครื่องหมายวรรคตอนแทน) หรือไม่