Perl, 1116 1124 ไบต์, n = 3, คะแนน = 1124 ^ (2/3) หรือประมาณ 108.1
อัปเดต : ตอนนี้ฉันตรวจสอบแล้วว่าสิ่งนี้ใช้ได้กับ n = 3 โดยใช้กำลังดุร้าย (ซึ่งใช้เวลาสองสามวัน); ด้วยโปรแกรมที่ซับซ้อนนี้มันยากที่จะตรวจสอบความต้านทานการแผ่รังสีด้วยมือ (และฉันทำพลาดหนึ่งครั้งในเวอร์ชันก่อนหน้าซึ่งเป็นสาเหตุที่จำนวนไบต์เพิ่มขึ้น) จบการอัพเดท
ฉันขอแนะนำให้เปลี่ยนเส้นทาง stderr บางแห่งที่คุณจะไม่เห็น โปรแกรมนี้สร้างคำเตือนมากมายเกี่ยวกับไวยากรณ์ที่น่าสงสัยแม้ว่าคุณจะไม่ได้ลบอักขระออกไปก็ตาม
เป็นไปได้ว่าโปรแกรมสามารถย่อให้สั้นลงได้ การทำงานในลักษณะนี้ค่อนข้างเจ็บปวดทำให้ง่ายต่อการพลาดในการเพิ่มประสิทธิภาพของไมโคร ฉันส่วนใหญ่มีเป้าหมายเพื่อให้ได้จำนวนตัวอักษรที่สามารถลบได้สูงที่สุดเท่าที่จะเป็นไปได้ (เพราะนั่นเป็นส่วนที่ท้าทายอย่างยิ่งของโปรแกรม) และปฏิบัติต่อtie -golf tiebreak เป็นสิ่งที่ดีที่จะตั้งเป้าหมายไว้ ความพยายามที่ไร้สาระในการเพิ่มประสิทธิภาพ (บนพื้นฐานที่ว่ามันง่ายมากที่จะทำลายความต้านทานรังสีโดยไม่ได้ตั้งใจ)
โปรแกรม
หมายเหตุ: มีการควบคุมตัวอักษร_
ตัวอักษร (ASCII 31) -+
ทันทีก่อนที่แต่ละแห่งที่สี่การเกิดขึ้นของ ฉันไม่คิดว่ามันจะคัดลอกและวางลงใน StackOverflow อย่างถูกต้องดังนั้นคุณจะต้องเพิ่มอีกครั้งก่อนที่จะเรียกใช้โปรแกรม
eval+<eval+<eval+<eval+(q(FoPqOlengthFoBBPP181XXVVVVJJJKKKNdoWchopJFtPDevalMODx4KNFrPIPA-MN-TUV-ZPINFsPIFoPqOI.Fo.IQNevalFoINevalIFsPZyI.Fr.IT-UPINsayDFtJqJFsKPZyPT-UFWrYrKD.DEEEEQDx6NsayDNDforB1..4YforB1..4NexitQNevalFo)=~y=A-Z=-+;-AZz-~=r)####>####>####>####>####>####>
;
;
;
;
eval+<eval+<eval+<eval+(q(FoPqOlengthFoBBPP181XXVVVVJJJKKKNdoWchopJFtPDevalMODx4KNFrPIPA-MN-TUV-ZPINFsPIFoPqOI.Fo.IQNevalFoINevalIFsPZyI.Fr.IT-UPINsayDFtJqJFsKPZyPT-UFWrYrKD.DEEEEQDx6NsayDNDforB1..4YforB1..4NexitQNevalFo)=~y=A-Z=-+;-AZz-~=r)####>####>####>####>####>####>
;
;
;
;
eval+<eval+<eval+<eval+(q(FoPqOlengthFoBBPP181XXVVVVJJJKKKNdoWchopJFtPDevalMODx4KNFrPIPA-MN-TUV-ZPINFsPIFoPqOI.Fo.IQNevalFoINevalIFsPZyI.Fr.IT-UPINsayDFtJqJFsKPZyPT-UFWrYrKD.DEEEEQDx6NsayDNDforB1..4YforB1..4NexitQNevalFo)=~y=A-Z=-+;-AZz-~=r)####>####>####>####>####>####>
;
;
;
;
eval+<eval+<eval+<eval+(q(FoPqOlengthFoBBPP181XXVVVVJJJKKKNdoWchopJFtPDevalMODx4KNFrPIPA-MN-TUV-ZPINFsPIFoPqOI.Fo.IQNevalFoINevalIFsPZyI.Fr.IT-UPINsayDFtJqJFsKPZyPT-UFWrYrKD.DEEEEQDx6NsayDNDforB1..4YforB1..4NexitQNevalFo)=~y=A-Z=-+;-AZz-~=r)####>####>####>####>####>####>
;
;
;
;
คำอธิบาย
โปรแกรมนี้ค่อนข้างชัดเจนทำจากโปรแกรมขนาดเล็กที่เหมือนกันสี่รายการที่ต่อกันเข้าด้วยกัน แนวคิดพื้นฐานคือแต่ละสำเนาของโปรแกรมจะตรวจสอบว่ามีความเสียหายมากเกินไปที่จะเรียกใช้หรือไม่ ถ้าเป็นเช่นนั้นมันจะไม่ทำอะไรเลย (นอกเหนือจากการเตือนคาย) และปล่อยให้การคัดลอกครั้งต่อไปทำงานได้ หากยังไม่ได้รับ (เช่นไม่มีการลบหรือตัวละครที่ถูกลบเป็นสิ่งที่สร้างความแตกต่างให้กับการทำงานของโปรแกรม) มันจะทำสิ่งที่น่าสงสัย (พิมพ์รหัสต้นฉบับของโปรแกรมเต็มนี่คือ quine ที่เหมาะสม ด้วยแต่ละส่วนที่มีการเข้ารหัสของรหัสที่มาทั้งหมด) แล้วออก (ป้องกันไม่ให้สำเนาที่ไม่เสียหายอื่น ๆ จากการพิมพ์รหัสต้นฉบับออกมาอีกครั้งและทำให้การทำลายควินินโดยการพิมพ์ข้อความมากเกินไป)
แต่ละส่วนทำจากสองส่วนซึ่งเป็นอิสระต่อการใช้งานอย่างมีประสิทธิภาพ wrapper ภายนอกและรหัสภายในบางอย่าง ด้วยเหตุนี้เราสามารถพิจารณาแยกต่างหาก
เสื้อคลุมด้านนอก
โดยทั่วไปแล้ว wrapper ด้านนอกeval<+eval<+eval< ... >####>####...>###
(รวมอัฒภาคและบรรทัดใหม่ที่มีจุดประสงค์ที่ชัดเจนควรให้แน่ใจว่าส่วนของโปรแกรมจะแยกออกจากกันไม่ว่าเซมิโคลอนบางอันหรือบรรทัดใหม่ก่อนหน้าจะถูกลบทิ้ง ) นี่อาจดูเรียบง่ายพอสมควร แต่ก็มีหลายวิธีและเหตุผลที่ฉันเลือก Perl สำหรับความท้าทายนี้
อันดับแรกให้ดูที่วิธีการทำงานของ wrapper ในสำเนาของโปรแกรมที่ไม่เสียหาย eval
แยกวิเคราะห์เป็นฟังก์ชั่นในตัวซึ่งใช้เวลาหนึ่งอาร์กิวเมนต์ เนื่องจากข้อโต้แย้งคาดว่า+
นี่คือ unary +
(ซึ่งจะคุ้นเคยกับนักกอล์ฟ Perl โดยขณะนี้พวกเขามามีประโยชน์บ่อยครั้งอย่างแปลกใจ) เรายังคงคาดหวังข้อโต้แย้ง (เราเพิ่งเห็นโอเปอเรเตอร์ unary) ดังนั้นสิ่ง<
ที่ตามมาจะถูกตีความว่าเป็นจุดเริ่มต้นของ<>
โอเปอเรเตอร์ (ซึ่งไม่มีคำนำหน้าหรืออาร์กิวเมนต์ของคำนำหน้าหลังและสามารถใช้ในตำแหน่งตัวถูกดำเนินการ)
<>
เป็นผู้ประกอบการที่ค่อนข้างแปลก วัตถุประสงค์ปกติของมันคือการอ่าน filehandles และคุณวางชื่อ filehandle ไว้ในวงเล็บเหลี่ยม อีกทางเลือกหนึ่งถ้านิพจน์ไม่ถูกต้องเป็นชื่อ filehandle มันจะทำให้เกิดความกลมกลืน (โดยทั่วไปกระบวนการเดียวกับที่เชลล์ UNIX ใช้ในการแปลข้อความที่ผู้ใช้ป้อนไปยังลำดับของอาร์กิวเมนต์บรรทัดคำสั่ง; Perl รุ่นเก่าที่ใช้จริงมาก เชลล์สำหรับสิ่งนี้ แต่ทุกวันนี้ Perl จัดการกับสิ่งที่อยู่ภายใน) วัตถุประสงค์การใช้งานจึงเป็นตามสายของซึ่งโดยทั่วไปแล้วจะกลับรายการเช่น<*.c>
("foo.c", "bar.c")
ในบริบทเซนต์คิตส์และเนวิส (เช่นอาร์กิวเมนต์ไปeval
) เพียงแค่ส่งคืนรายการแรกที่พบในครั้งแรกที่เรียกใช้ (เทียบเท่ากับอาร์กิวเมนต์แรก) และจะส่งคืนรายการอื่น ๆ ในการรันในอนาคตตามสมมติฐานที่ไม่เคยเกิดขึ้น
ตอนนี้เชลล์มักจัดการกับอาร์กิวเมนต์บรรทัดคำสั่ง ถ้าคุณให้อะไรที่-r
ไม่มีข้อโต้แย้งมันก็จะถูกส่งไปยังคำต่อคำของโปรแกรมโดยไม่คำนึงว่ามีชื่อไฟล์นั้นหรือไม่ Perl ทำหน้าที่ในลักษณะเดียวกันตราบใดที่เรามั่นใจว่าไม่มีตัวอักษรที่พิเศษสำหรับเชลล์หรือ Perl ระหว่าง<
และการจับคู่>
เราสามารถใช้มันได้อย่างมีประสิทธิภาพเช่นสตริงตัวอักษรที่น่าอึดอัดใจจริงๆ ยิ่งไปกว่านั้น parser ของ Perl สำหรับตัวดำเนินการที่มีเครื่องหมายคำพูดมีแนวโน้มที่จะบังคับให้จับคู่วงเล็บในบริบทเช่นนี้ซึ่งมันไม่มีเหตุผลดังนั้นเราจึงสามารถซ้อน<>
อย่างปลอดภัย (ซึ่งเป็นการค้นพบที่จำเป็นสำหรับโปรแกรมนี้เพื่อให้เป็นไปได้) ข้อเสียที่สำคัญของซ้อนกันทั้งหมดเหล่านี้<>
คือการหลบหนีเนื้อหาของ<>
เป็นไปไม่ได้เกือบ ดูเหมือนว่าจะมีสองเลเยอร์ของการหลบหลีกกับแต่ละ<>
ดังนั้นเพื่อหนีบางสิ่งบางอย่างที่อยู่ภายในทั้งสามมันจะต้องนำหน้าด้วยแบ็กสแลช 63 ฉันตัดสินใจว่าแม้ว่าขนาดรหัสเป็นเพียงข้อพิจารณาที่สองในปัญหานี้ แต่ก็แทบจะไม่คุ้มที่จะจ่ายค่าปรับนี้กับคะแนนของฉันดังนั้นฉันจึงตัดสินใจเขียนโปรแกรมส่วนที่เหลือโดยไม่ใช้อักขระที่ละเมิด
แล้วจะเกิดอะไรขึ้นถ้าส่วนต่าง ๆ ของเสื้อคลุมถูกลบ?
- การลบคำว่า
eval
ทำให้มันกลายเป็นbarewordสตริงที่ไม่มีความหมาย Perl ไม่ชอบสิ่งเหล่านี้ แต่มันปฏิบัติต่อพวกเขาราวกับว่าพวกเขาถูกล้อมรอบด้วยคำพูด; จึงeal<+eval<+...
ถูกตีความว่าเป็น"eal" < +eval<+...
. สิ่งนี้ไม่มีผลกระทบต่อการทำงานของโปรแกรมเพราะโดยทั่วไปแล้วจะได้ผลลัพธ์จาก evals ที่ซ้อนกันอย่างมาก (ซึ่งเราไม่ได้ใช้อยู่แล้ว) ส่งไปที่จำนวนเต็มและทำการเปรียบเทียบแบบไม่มีจุดหมาย (สิ่งนี้ทำให้เกิดการเตือนสแปมจำนวนมากเนื่องจากไม่ใช่สิ่งที่มีประโยชน์ที่จะทำภายใต้สถานการณ์ปกติเราแค่ใช้เพื่อดูดซับการลบ) การเปลี่ยนแปลงจำนวนวงเล็บเหลี่ยมมุมที่เราต้องการ (เพราะวงเล็บเปิด ขณะนี้กำลังถูกตีความว่าเป็นตัวดำเนินการเปรียบเทียบแทน) แต่ห่วงโซ่ความคิดเห็นในตอนท้ายทำให้มั่นใจได้ว่าสตริงจะสิ้นสุดอย่างปลอดภัยไม่ว่าจะซ้อนกันกี่ครั้งก็ตาม (มี#
สัญญาณมากกว่าที่จำเป็นอย่างยิ่งที่นี่ฉันเขียนมันเหมือนที่ฉันทำเพื่อให้โปรแกรมบีบอัดได้มากขึ้นทำให้ฉันใช้ข้อมูลน้อยลงเพื่อเก็บควินิน)
- หากได้รับการลบรหัสตอนนี้จะแยกวิเคราะห์เป็น
<
eval(eval<...>)
รองนอกeval
ไม่มีผลกระทบเนื่องจากโปรแกรมที่เราประเมินไม่ส่งคืนสิ่งใดที่มีผลกระทบที่แท้จริงในฐานะโปรแกรม (ถ้าพวกเขากลับมาตามปกติเลยปกติแล้วมันจะเป็นสตริง null หรือ bareword โดยทั่วไปแล้วพวกเขากลับผ่าน ข้อยกเว้นซึ่งทำให้eval
คืนสตริงว่างหรือใช้exit
เพื่อหลีกเลี่ยงการส่งคืน)
- หาก
+
ได้รับการลบนี่จะไม่มีผลทันทีหากรหัสที่อยู่ติดกันไม่เป็นอันตราย เอก+
จะไม่มีผลกับโปรแกรม (เหตุผลที่ต้นฉบับ+
มีไว้เพื่อช่วยซ่อมแซมความเสียหายพวกเขาเพิ่มจำนวนสถานการณ์ที่<
ตีความว่าเป็นเอกภาพ<>
แทนที่จะเป็นผู้ดำเนินการเชิงสัมพันธ์หมายความว่าคุณต้องการการลบมากกว่าเพื่อสร้างโปรแกรมที่ไม่ถูกต้อง)
เสื้อคลุมอาจเสียหายได้ด้วยการลบที่เพียงพอ แต่คุณจำเป็นต้องทำชุดการลบเพื่อสร้างสิ่งที่ไม่แยกวิเคราะห์ ด้วยการลบสี่รายการคุณสามารถทำสิ่งนี้:
eal<evl<eval+<...
และใน Perl ตัวดำเนินการเชิงสัมพันธ์<
นั้นไม่เกี่ยวข้องและทำให้คุณได้รับข้อผิดพลาดทางไวยากรณ์ (อันเดียวกับที่คุณจะได้รับ1<2<3
) ดังนั้น cap สำหรับโปรแกรมตามที่เขียนคือ n = 3 การเพิ่ม unary มากขึ้น+
ดูเหมือนเป็นวิธีที่มีแนวโน้มในการเพิ่ม แต่ก็ทำให้มีโอกาสมากขึ้นที่ด้านในของ wrapper อาจแตกได้เช่นกันการตรวจสอบว่าโปรแกรมเวอร์ชันใหม่ทำงานได้ยากมาก
เหตุผลที่ wrapper มีค่ามากคือeval
ใน Perl จับข้อยกเว้นเช่น (ตัวอย่าง) ข้อยกเว้นที่คุณได้รับเมื่อคุณพยายามรวบรวมข้อผิดพลาดทางไวยากรณ์ เนื่องจากสิ่งนี้eval
เป็นของตัวอักษรสตริงการรวบรวมของสตริงเกิดขึ้นที่รันไทม์และหากตัวอักษรไม่สามารถรวบรวมข้อยกเว้นที่เกิดขึ้นได้รับการติด นี่เป็นสาเหตุeval
ให้ส่งคืนสตริง null และตั้งค่าตัวบ่งชี้ข้อผิดพลาด$@
แต่เราไม่เคยตรวจสอบอย่างใดอย่างหนึ่ง (ยกเว้นบางครั้งเรียกใช้งานสตริง null ที่ส่งคืนในโปรแกรมกลายพันธุ์บางรุ่น) ซึ่งหมายความว่าหากสิ่งที่ควรเกิดขึ้นกับรหัสภายในwrapper ทำให้เกิดข้อผิดพลาดทางไวยากรณ์จากนั้น wrapper จะทำให้โค้ดไม่ทำอะไรแทน (และโปรแกรมจะดำเนินการต่อไปเพื่อพยายามค้นหาสำเนาที่ไม่เสียหายของตัวเอง) ดังนั้นรหัสด้านในไม่จำเป็นต้องมีความต้านทานการแผ่รังสีเหมือนกับแผ่นห่อ สิ่งที่เราใส่ใจคือถ้าเกิดความเสียหายมันอาจจะทำหน้าที่เหมือนกับรุ่นที่ไม่เสียหายของโปรแกรมหรือมิฉะนั้นมันก็จะพัง (อนุญาตให้eval
จับยกเว้นและดำเนินการต่อ) หรือออกตามปกติโดยไม่ต้องพิมพ์อะไร
ด้านในเสื้อคลุม
รหัสภายใน wrapper โดยพื้นฐานแล้วจะมีลักษณะเช่นนี้ (อีกครั้งมีการควบคุม - _
ที่ Exchange Exchange จะไม่แสดงทันทีก่อน-+
):
eval+(q(...)=~y=A-Z=-+;-AZz-~=r)
รหัสนี้เขียนด้วยตัวอักษรแบบกลมปลอดภัยและมีจุดประสงค์เพื่อเพิ่มตัวอักษรใหม่ของเครื่องหมายวรรคตอนที่ทำให้สามารถเขียนโปรแกรมจริงผ่านการถอดเสียงและประเมินสตริงตัวอักษร (เราไม่สามารถใช้'
หรือ"
เป็นคำพูดของเรา เครื่องหมาย แต่q(
... )
ยังเป็นวิธีที่ถูกต้องในการสร้างสตริงใน Perl) (เหตุผลสำหรับตัวละครที่ไม่สามารถพิมพ์ได้คือเราต้องถอดทอนบางสิ่งบางอย่างลงในช่องว่างโดยไม่ต้องใช้ตัวอักษรช่องว่างในโปรแกรมดังนั้นเราจึงสร้างช่วงที่เริ่มต้นที่ ASCII 31 และจับพื้นที่เป็นองค์ประกอบที่สองของช่วง) เห็นได้ชัดว่าถ้าเราผลิตตัวละครบางตัวผ่านการทับศัพท์เราต้องเสียสละตัวละครเพื่อถอดเสียงจากแต่ตัวอักษรตัวพิมพ์ใหญ่ไม่ได้มีประโยชน์มากและง่ายต่อการเขียนโดยไม่ต้องเข้าถึงตัวอักษรเหล่านั้นมากกว่าการเข้าถึงเครื่องหมายวรรคตอน
นี่คือตัวอักษรของเครื่องหมายวรรคตอนที่สามารถใช้งานได้เนื่องจาก glob (บรรทัดบนแสดงการเข้ารหัสบรรทัดล่างของอักขระที่เข้ารหัส):
BCDEFGHIJKLMNOPQRSTUVWXYZ
! "# $% & '() + *? <=> @ Azz {|} ~
ที่โดดเด่นที่สุดคือเรามีเครื่องหมายวรรคตอนมากมายที่ไม่ปลอดภัย แต่มีประโยชน์ในการเขียนโปรแกรม Perl พร้อมกับอักขระเว้นวรรค ฉันยังบันทึกตัวอักษรตัวพิมพ์ใหญ่สองตัวตัวอักษรA
และZ
(ซึ่งเข้ารหัสไม่ให้ตัวเอง แต่ถึงT
และU
เพราะA
จำเป็นสำหรับทั้งบนและล่างช่วงปลายทาง); สิ่งนี้ช่วยให้เราสามารถเขียนคำสั่งการถอดเสียงได้เองโดยใช้ชุดอักขระที่เข้ารหัสใหม่ (แม้ว่าตัวอักษรตัวพิมพ์ใหญ่จะไม่เป็นประโยชน์ แต่ก็มีประโยชน์ในการระบุการเปลี่ยนแปลงตัวอักษรตัวพิมพ์ใหญ่) ตัวละครที่โดดเด่นที่สุดที่เราไม่สามารถหาได้คือ[
, \
และ]
, แต่ไม่มีสิ่งจำเป็น (เมื่อฉันต้องการขึ้นบรรทัดใหม่ในผลลัพธ์, ฉันสร้างมันขึ้นมาโดยใช้บรรทัดใหม่โดยนัยจากsay
มากกว่าที่จะต้องเขียน\n
; chr 10
ก็จะได้ผลเช่นกัน
ตามปกติเราจำเป็นต้องกังวลเกี่ยวกับสิ่งที่เกิดขึ้นหากภายในของเสื้อคลุมได้รับความเสียหายนอกตัวอักษรสตริง ความเสียหายeval
จะป้องกันไม่ให้สิ่งใดทำงาน เราไม่เป็นไร หากเครื่องหมายคำพูดได้รับความเสียหายภายในของสตริงจะไม่ถูกต้อง Perl และดังนั้นเสื้อคลุมจะจับมัน (และการลบจำนวนมากบนสตริงหมายความว่าแม้ว่าคุณสามารถทำให้มันถูกต้อง Perl ก็จะไม่ทำอะไรซึ่ง เป็นผลลัพธ์ที่ยอมรับได้) ความเสียหายให้กับการทับศัพท์ถ้ามันไม่ได้เป็นข้อผิดพลาดทางไวยากรณ์จะฉีกสตริงถูกประเมินมักจะก่อให้เกิดมันจะกลายเป็นข้อผิดพลาดทางไวยากรณ์; ฉันไม่แน่ใจ 100% ว่าไม่มีกรณีที่การหยุดพักนี้ แต่ฉันกำลังบังคับให้ทำอย่างนั้นในขณะนี้เพื่อให้แน่ใจและควรง่ายพอที่จะแก้ไขหากมี
โปรแกรมที่เข้ารหัส
เมื่อมองเข้าไปในสตริงตัวอักษรการย้อนกลับของการเข้ารหัสที่ฉันใช้และเพิ่มช่องว่างเพื่อให้อ่านได้ง่ายขึ้นเราจะได้รับสิ่งนี้ (อีกครั้งให้จินตนาการถึงขีดล่างควบคุมก่อนหน้า-+
ซึ่งเข้ารหัสเป็นA
)
$o=q<
length$o ==181 || zzzz((()));
do {
chop ($t = "eval+<"x4);
$r = '=-+;-AZz-~=';
$s = '$o=q<' . $o . '>;eval$o';
eval '$s=~y' . $r . 'A-Z=';
say "$t(q($s)=~y=A-Z${r}r)" . "####>"x6;
say ";" for 1..4
} for 1..4;
exit>;
eval $o
ผู้ที่เคยใช้ในการทดสอบจะรับรู้โครงสร้างทั่วไปนี้ ส่วนที่สำคัญที่สุดคือการเริ่มต้นที่เราตรวจสอบว่า $ o ไม่เสียหาย ถ้าตัวละครที่ได้รับการลบความยาวของมันจะไม่ตรงกับ181
ดังนั้นเราจึงทำงานzzzz((()))
ซึ่งถ้ามันไม่ได้เป็นข้อผิดพลาดทางไวยากรณ์เนื่องจากวงเล็บตรงกันจะเป็นข้อผิดพลาด runtime แม้ว่าคุณจะลบใด ๆ ที่ตัวละครทั้งสามเพราะไม่มีzzzz
, zzz
, zz
, และz
เป็นฟังก์ชั่นและไม่มีวิธีที่จะป้องกันไม่ให้มันแยกเป็นฟังก์ชั่นอื่นนอกเหนือจากการลบ(((
และทำให้เกิดข้อผิดพลาดทางไวยากรณ์ที่น่ารังเกียจ การตรวจสอบตัวเองยังมีความเสียหาย ||
ได้รับความเสียหายไป|
แต่ที่จะทำให้เกิดการzzzz((()))
เรียกร้องให้ทำงานโดยไม่มีเงื่อนไข ตัวแปรหรือค่าคงที่จะทำให้เกิดความเสียหายที่ไม่ตรงกันเพราะคุณกำลังเปรียบเทียบหนึ่ง0
,180
, 179
, 178
เพื่อความเท่าเทียมกันในการเซตบางส่วนของตัวเลขของ181
; และการลบออก=
จะทำให้เกิดความล้มเหลวในการแยกวิเคราะห์และอีกสองรายการที่=
จะทำให้ LHS ต้องประเมินค่าเป็นจำนวนเต็ม 0 หรือสตริง null ซึ่งทั้งคู่เป็นเท็จ
อัปเดต : การตรวจสอบนี้ผิดเล็กน้อยในโปรแกรมรุ่นก่อนหน้าดังนั้นฉันต้องแก้ไขเพื่อแก้ไขปัญหา รุ่นก่อนหน้ามีลักษณะเช่นนี้หลังจากถอดรหัส:
length$o==179||zzzz((()))
และเป็นไปได้ที่จะลบเครื่องหมายวรรคตอนสามตัวแรกเพื่อให้ได้สิ่งนี้:
lengtho179||zzz((()))
lengtho179
เป็น bareword เป็นความจริงและทำให้แบ่งการตรวจสอบ ฉันแก้ไขสิ่งนี้โดยการเพิ่มB
อักขระพิเศษสองตัว (ซึ่งเข้ารหัสอักขระช่องว่าง) ซึ่งหมายถึงควินินเวอร์ชันล่าสุดทำสิ่งนี้
length$o ==181||zzzz((()))
ตอนนี้มันเป็นไปไม่ได้ที่จะซ่อนทั้ง=
เครื่องหมายและ$
สัญญาณโดยไม่สร้างข้อผิดพลาดทางไวยากรณ์ (ฉันต้องเพิ่มช่องว่างสองช่องแทนที่จะเป็นช่องว่างหนึ่งอันเนื่องจากความยาวของ180
จะใส่0
อักขระตามตัวอักษรลงในแหล่งที่มาซึ่งอาจถูกใช้ในบริบทนี้เป็นศูนย์เปรียบเทียบจำนวนเต็มกับ bareword ซึ่งประสบความสำเร็จ) อัปเดตสุดท้าย
เมื่อการตรวจสอบความยาวผ่านไปแล้วเรารู้ว่าสำเนานั้นไม่เสียหายอย่างน้อยก็ในแง่ของการลบตัวอักษรออกไปดังนั้นมันจึงเป็นเพียงแค่การคว้านออกมาจากตรงนั้น (การแทนที่เครื่องหมายวรรคตอนเนื่องจากตารางถอดรหัสที่เสียหายจะไม่ถูกตรวจจับ แต่ฉันได้ตรวจสอบแล้วผ่านการเดรัจฉานบังคับว่าไม่มีการลบสามจากเฉพาะตารางถอดรหัสแบ่งควินนั้นน่าจะส่วนใหญ่ทำให้เกิดข้อผิดพลาดทางไวยากรณ์) เรามี$o
ตัวแปรอยู่แล้วดังนั้นสิ่งที่เราต้องทำก็คือ hardcode ตัวห่อหุ้มภายนอก (ด้วยการบีบอัดเล็กน้อยบางอันฉันไม่ได้ข้ามส่วนของcode-golfของคำถามทั้งหมด ) เคล็ดลับอย่างหนึ่งคือเราจัดเก็บตารางการเข้ารหัสไว้จำนวนมาก$r
; เราสามารถพิมพ์มันอย่างแท้จริงเพื่อสร้างส่วนตารางการเข้ารหัสของ wrapper ภายในหรือเชื่อมต่อโค้ดบางส่วนรอบ ๆ มันและeval
เพื่อรันกระบวนการถอดรหัสในสิ่งที่ตรงกันข้าม (ช่วยให้เราทราบว่ารุ่นที่เข้ารหัสของ $ o คืออะไร มีเฉพาะรุ่นถอดรหัสที่มีอยู่ในตอนนี้)
ในที่สุดหากเราเป็นสำเนาที่สมบูรณ์และสามารถส่งออกโปรแกรมต้นฉบับทั้งหมดได้เราจะโทรติดต่อexit
เพื่อป้องกันไม่ให้สำเนาอื่นพยายามพิมพ์โปรแกรมออกมา
สคริปต์ยืนยัน
ไม่สวยมาก แต่โพสต์เพราะมีคนถาม ฉันวิ่งไปหลายครั้งด้วยการตั้งค่าที่หลากหลาย (โดยทั่วไปจะเปลี่ยน$min
และ$max
ตรวจสอบพื้นที่ที่น่าสนใจ); มันไม่ใช่กระบวนการอัตโนมัติอย่างสมบูรณ์ มันมีแนวโน้มที่จะหยุดทำงานเนื่องจากภาระของ CPU ที่หนักอื่น; เมื่อสิ่งนี้เกิดขึ้นฉันเพิ่งเปลี่ยน$min
เป็นค่าแรกของ$x
ที่ไม่ได้รับการตรวจสอบอย่างสมบูรณ์และรันสคริปต์ต่อไป ฉันตรวจสอบการลบจากสำเนาแรกของโปรแกรมเท่านั้นเนื่องจากเห็นได้ชัดว่าการลบจากสำเนาอื่นไม่สามารถทำได้มากกว่า
use 5.010;
use IPC::Run qw/run/;
undef $/;
my $program = <>;
my $min = 1;
my $max = (length $program) / 4 - 3;
for my $x ($min .. $max) {
for my $y ($x .. $max) {
for my $z ($y .. $max) {
print "$x, $y, $z\n";
my $p = $program;
substr $p, $x, 1, "";
substr $p, $y, 1, "";
substr $p, $z, 1, "";
alarm 4;
run [$^X, '-M5.010'], '<', \$p, '>', \my $out, '2>', \my $err;
if ($out ne $program) {
print "Failed deleting at $x, $y, $z\n";
print "Output: {{{\n$out}}}\n";
exit;
}
}
}
}
say "All OK!";
Subleq
มา ฉันคิดว่ามันจะเหมาะสำหรับความท้าทายแบบนี้!