การเขียนโปรแกรมโลกที่เก่าแก่


87

ลองกำหนดโปรแกรมที่เก่าแก่เป็นโปรแกรมที่ไม่มีข้อผิดพลาดใด ๆ ของตัวเอง แต่จะผิดพลาดถ้าคุณแก้ไขได้โดยการเอาย่อยที่ต่อเนื่องกันใด ๆ ของตัวอักษร N, 1 <= N < program lengthที่

ตัวอย่างเช่นโปรแกรมสามตัวอักษร Python 2

`8`

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

8`
``
`8

และโปรแกรมทั้งหมดที่เป็นผลมาจากการลบสตริงย่อยของความยาว 2 ทำให้เกิดข้อผิดพลาด:

`
`

ตัวอย่างเช่นหาก`8เป็นโปรแกรมที่`8`ไม่มีข้อผิดพลาดก็จะไม่ได้รับความบริสุทธิ์เนื่องจากผลลัพธ์ทั้งหมดของการลบสตริงย่อยจะต้องเกิดข้อผิดพลาด

งานของคุณในการท้าทายนี้คือการเขียนโปรแกรมที่สั้นที่สุดที่เป็นไปได้โดยไม่ต้องป้อนข้อมูล แต่ให้ผลลัพธ์หนึ่งในห้าคำต่อไปนี้:

world
earth
globe
planet
sphere

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

หมายเหตุ:

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

ต่อไปนี้เป็นตัวอย่างสแต็กที่จะแสดงรายการสิ่งที่โปรแกรมที่จำเป็นต้องมีข้อผิดพลาดเนื่องจากโปรแกรมที่เก่าแก่:

<script src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js'></script><script>function go() { var s = $('#i').val(), e = []; for (var i = 1; i < s.length; i++) { for (var j = 0; j <= s.length - i; j++) { e.push(s.substring(0, j) + s.substring(j + i)); } } $('#o').val(e.join('\n---\n')); }</script>Program:<br><textarea id='i' rows='16' cols='80'>`8`</textarea><br><button onclick='go()' type='button'>Go</button><br><br>Programs that should error: (--- separated)<br><textarea id='o' rows='16' cols='80'></textarea><br>


1
@geokavel ใช่ การตรวจจับข้อยกเว้นหมายความว่าไม่มีข้อผิดพลาดอีกต่อไป
งานอดิเรกของ Calvin

33
คำตอบที่ถูกลบสองครั้งมากที่สุดเท่าที่ไม่ถูกลบ นั่นคือความสำเร็จ!
DLosc

1
โปรแกรมสามารถอ่านซอร์สโค้ดของตัวเองได้หรือไม่?
Shelvacu

2
จะดูหลุมฝังศพของคำตอบ "ปิด แต่ไม่มีซิการ์" และความคิดเห็นของพวกเขาได้ที่ไหน?
วิ

1
@Vi ได้รับ 2,000 ตัวแทนเพื่อให้คุณสามารถดูกระทู้ที่ถูกลบ
ThisSuitIsBlackNot

คำตอบ:


46

Railขนาด 24 ไบต์

$'main'    #
 -[world]o/

ฉันคิดว่ามันใช้งานได้ และทั้งสั้นและอ่านได้ (เท่าที่รถไฟวิ่ง)

  • หากซับสตริงที่ลบออกรวมส่วนใดส่วนหนึ่งของ$'main'เราInternal Error: Crash: No 'main' function foundด้วย
  • หากสตริงย่อยที่ถูกลบออกรวมถึง#จะไม่มีทางที่โปรแกรมจะออกอย่างหมดจดดังนั้นมันจะจบลงด้วยCrash: No valid moveเสมอ ฉันเชื่อว่ามันเป็นไปไม่ได้ที่จะลบซับสตริงเช่นนี้ทำให้แทร็กเป็นลูปที่ถูกต้อง (ไม่ จำกัด )
  • หากซับสตริงที่ลบออกอยู่ด้านหน้า#จะถูกตัดการเชื่อมต่อจากจุดสิ้นสุดของแทร็กดังนั้นรถไฟจะหยุดทำงาน (โดยมีข้อผิดพลาดเดียวกับด้านบน)
  • หากซับสตริงที่ถูกลบออกหลังจาก#นั้นมันจะตัดการเชื่อมต่อ#จากจุดสิ้นสุดของแทร็ก (และอาจเป็นจุดเริ่มต้นของแทร็กจากจุดเข้าใช้งาน$) ดังนั้นข้อผิดพลาดเดียวกันอีกครั้ง

สำหรับโปรแกรมที่เกิดขึ้นจริง: โปรแกรมรถไฟทุกโปรแกรมจำเป็นต้องมี$'main'(หรือตัวแปรที่ยาวกว่า แต่เรากำลังเล่นกอล์ฟอยู่ที่นี่) เป็นจุดเริ่มต้นเข้าสู่ฟังก์ชั่นและรถไฟเริ่มขึ้นใน$ทิศตะวันออกเฉียงใต้ ทุกอย่างในบรรทัดแรกนั้นสามารถเป็นส่วนหนึ่งของแทร็กได้ดังนั้นการลบ'main'แทร็กคือ:

$          #
 -[world]o/

-และ/เป็นเพียงชิ้นส่วนของรถไฟที่เราต้องปล่อยให้รถไฟใช้เวลาเหล่านั้น 45 °ผลัด

[world]ดันสตริงworldและoพิมพ์ #ทำเครื่องหมายจุดสิ้นสุดของแทร็ก - วิธีเดียวในการยกเลิกโปรแกรม Rail อย่างปลอดภัย

น่าสนใจโซลูชันนี้มีความเป็นไปได้เพียงเพราะ Rail อนุญาตให้แทร็กวิ่งผ่านmainเส้น - หากไม่สามารถทำได้#หลังจาก newline แรกและรหัสอาจสั้นลง

$'main'
 #

ซึ่งเป็นโปรแกรมที่ถูกต้องที่ไม่ทำอะไรเลย (อักขระที่ไม่ใช่ช่องว่างระหว่าง'และ#จะไม่มีผลกับสิ่งนั้น)

นอกจากนี้ยังค่อนข้างน่าสนใจ: ถ้าฉันได้เพียงแค่แข็งแรงเล่นกอล์ฟงานพิมพ์worldก็จะไม่ได้รับมากน้อยหรือง่าย:

$'main'
 -[world]o#

4
ถ้าฉันลบอักขระใด ๆ ระหว่าง [และ]
Martin Lütke

@ MartinLütkeมันจะตัดการเชื่อมต่อจาก/ #
Martin Ender

2
@ MartinLütkeคุณไม่สามารถลบวงเล็บได้เนื่องจากไม่ได้ต่อเนื่องกัน
งานอดิเรกของ Calvin

เกิดอะไรขึ้นถ้าลบบรรทัดใหม่ระหว่างสองบรรทัด
วิ

1
@Vi ซึ่งจะตัดการเชื่อมต่อ$จากจุดเริ่มต้นของแทร็กดังนั้นรถไฟจึงล้มเหลวทันที (รถไฟคาดว่าแทร็กจะดำเนินการต่อไปทางตะวันออกเฉียงใต้ของ$)
Martin Ender

43

Funciton ( 186 136 ไบต์ใน UTF-16)

╔══════════════╗
║19342823075080╟
║88037380718711║
╚══════════════╝

โปรแกรมนี้พิมพ์ "โลก"

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

 ╔══════════════╗
|║19342823075080╟  (remove this whole line)
|║88037380718711║
 ╚══════════════╝
 ╔══════════════╗
 ║|19342823075080╟   ← substring starts at | here
 ║|88037380718711║   ← substring ends at | here
 ╚══════════════╝
... ↕ or anything in between these that removes a whole line’s worth ↕ ...
 ╔══════════════╗
 ║19342823075080|╟   ← substring starts at | here
 ║88037380718711|║   ← substring ends at | here
 ╚══════════════╝
 ╔══════════════╗
|║19342823075080╟
 ║88037380718711║  (both lines entirely)
|╚══════════════╝
 ╔══════════════╗
 ║19342823075080╟
|║88037380718711║  (remove this whole line)
|╚══════════════╝

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

╔══════════════╗
║88037380718711║
╚══════════════╝

นี่ไม่ใช่โปรแกรมที่ถูกต้องอีกต่อไปเพราะ parser ต้องการโปรแกรมที่มีเอาต์พุตเดียว:

ข้อผิดพลาด: ไฟล์ต้นฉบับไม่มีโปรแกรม (โปรแกรมต้องมีเอาต์พุต)

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

╔══════════════╗
║19342823075080╟
╚══════════════╝

อย่างไรก็ตามหมายเลขนี้ไม่ได้เข้ารหัสสตริง Unicode ที่ถูกต้องในความลึกลับของ Funciton UTF-21 ลองเรียกใช้สิ่งนี้คุณจะได้รับ:

ข้อยกเว้น Unhandled: System.ArgumentOutOfRangeException: ค่า UTF32 ที่ถูกต้องอยู่ระหว่าง 0x000000 ถึง 0x10ffff รวมและไม่ควรรวมค่า codepoint ตัวแทน (0x00d800 ~ 0x00dfff)

ดังนั้นโปรแกรมนี้จึงบริสุทธิ์


3
ฉันรู้สึกว่าคุณโชคดีในกรณีสุดท้าย (ไม่ใช่ว่ามันเป็นเรื่องง่ายที่จะบังเอิญได้รับลำดับ Unicode ที่ถูกต้อง แต่ก็ยัง ... )
ผลไม้ Esolanging Fruit

34

Visual C ++ - 96 95 ไบต์

#include<iostream>
#define I(a,b)a<<b
int main()I({std::cout,I('w',I('o',I('r',I('l','d';)))))}

คุณสมบัติ:

  1. คุณไม่สามารถลบส่วนใดส่วนหนึ่งint main()โดยไม่มีข้อผิดพลาดในการรวบรวม
  2. คุณไม่สามารถลบแก้ไขการขยายตัวแมโครที่ทุกคนเอาaที่ทั้งหมดหมายความว่าmain()ไม่เคยได้รับ{การลบbที่ทุกคนหมายถึงสายของเราไม่ได้จบใน;การลบ<หมายถึงการstd::cout<'w'ทำให้เกิดข้อผิดพลาดและการลบ<<สาเหตุstd::cout'w', 'w''o'ฯลฯ
  3. คุณไม่สามารถลบพารามิเตอร์จากคำนิยามแมโครหรือภาวนาเพียงชื่อที่ถูกต้องสำหรับความหมายจะเป็นI(a), I(b)ซึ่งไม่ตรงกับและIที่ขยายไปก่อน(; ในทางกลับกันโดยใช้I(,สาเหตุ<<<<และ,)ลดเซมิโคลอน (ยกเว้นข้อผิดพลาดอื่น ๆ )
  4. คุณไม่สามารถลบบางส่วนของทั้งหมดstd::coutโดยไม่เรียกใช้งานในส่วนนำ<<ดังนั้นจึงไม่สามารถลบส่วนใดส่วนหนึ่ง#include<iostream>ในตอนเริ่มต้นได้โดยไม่มีข้อผิดพลาดในการคอมไพล์
  5. คุณไม่สามารถลบส่วนใดส่วนหนึ่งของอักขระเดียว''มีข้อผิดพลาดของอักขระที่ว่างเปล่าและ'w,ฯลฯ ... พยายามทำให้ทุกอย่างเป็นอักขระเดียว
  6. คุณไม่สามารถลบด้านซ้าย / ขวาของมาโครได้โดยไม่ต้องออกมากเกินไป)หรือ(อยู่อีกด้านหนึ่งเช่นคุณไม่สามารถทำสิ่งต่าง ๆI('w',I('r'ได้

รวบรวมออนไลน์โดยใช้Visual C ++

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

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


ยืนยัน:

โปรแกรมต่อไปนี้ได้รับการยืนยันว่ารุ่นนี้เก่าแก่โดยใช้clคอมไพเลอร์จาก Visual C ++ 2010 ฉันหวังว่าฉันจะใส่ใจที่จะเขียนสิ่งนี้ในไม่ช้า:

#include <fstream>
#include <iostream>
char *S = "#include<iostream>\n#define I(a,b)a<<b\nint main()I({std::cout,I('w',I('o',I('r',I('l','d';)))))}";
//uncomment to print source code before compile
// #define prints
int main(){
   for(int i=0; i<95; i++)
      for(int j=i; j<95; j++){
         std::fstream fs;
         fs.open ("tmptst.cpp",std::fstream::out);
         for(int k=0; k<95; k++)
         if(k<i || k>j){
            fs << S[k];
            #ifdef prints
               std::cout<<S[k];
            #endif
         }
         fs.close();
         #ifdef prints
            std::cout<<'\n';
         #endif
         //Compile and surpress/pipe all output
         //if it doesn't compile we get a nonzero errorlevel (i.e.true) from system.
         if(!system("cl -nologo tmptst.cpp >x"))
            return 0;
      }
      std::cout<<"PRISTINE!";
}

1
เราทราบว่าในขณะที่นี่เป็นที่เก่าแก่ที่สุดในคอมไพเลอร์นี้ไม่ได้อยู่ในคอมไพเลอร์ทั้งหมด
Joshua

1
โปรดยกตัวอย่าง ....
Linus

3
ในคอมไพเลอร์บางโปรแกรม C ++ เปล่าจะให้โปรแกรมที่ไม่ทำอะไรเลย #include <iostream> อาจรวบรวมขึ้นอยู่กับการใช้งานของ iostream
Joshua

5
@Joshua โปรแกรมย่อยที่มีความยาวตั้งแต่ 1 เรื่องขึ้นไปดังนั้นโปรแกรมจึงไม่เกี่ยวข้อง
ThisSuitIsBlackNot

2
@Comintern ไม่ได้จริงๆ หากคุณไม่ทำเครื่องหมายในช่องเพื่อเรียกใช้งาน/cตัวเลือกนี้จะมีตัวเลือกนี้รวมอยู่โดยอัตโนมัติและจะรวบรวม (เช่นถ้าสร้างไลบรารีไม่ใช่โปรแกรม) หากคุณทำเครื่องหมายในช่องเรียกใช้ที่ไซต์ไม่รวม/cคุณจะไม่ได้รับข้อความแสดงความสำเร็จและค้นหา "LINK: ร้ายแรงข้อผิดพลาดร้ายแรง LNK1561: ต้องระบุจุดเข้าใช้งาน"
Linus

32

Python 3, 79 33

if 5-open(1,'w').write('world'):a

open(1,'w')เปิดเอาต์พุตมาตรฐานจากนั้นเราพิมพ์สตริง writeส่งคืนจำนวนอักขระที่เขียน สิ่งนี้ถูกใช้เพื่อทำให้แข็งกับการลบซับสตริง: การลบส่วนหนึ่งของสตริงทำให้สิ่งอื่นที่ไม่ใช่ 5 ถูกส่งคืนและ 5 ลบค่านั้นจะประเมินเป็นจริง แต่นั่นทำให้if-body ถูกเรียกใช้งานและaไม่ได้กำหนดไว้

นี้จะขึ้นอยู่กับควินแอนเดอเก่าแก่ Kaseorg ฉลาดที่นี่

เนื่องจากต้องมีการตรวจสอบเพียงข้อความเดียวจึงสั้นกว่าโซลูชันเดิม แต่ก็มีความกว้างน้อยกว่า

โซลูชันเก่า:

try:
 q="print('world');r=None"
 if exec('e=q')==eval(q[17:]):exec(e)
finally:r

ในการตรวจสอบว่าเป็นโปรแกรมที่เก่าแก่จริงๆ:

w=r'''try:
 q="print('world');r=None"
 if exec('e=q')==eval(q[17:]):exec(e)
finally:r'''
exec(w)
for j in range(1,len(w)):
 for i in range(len(w)+1-j):
  e=w[:i]+w[i+j:]
  try:exec(e,{});print('WORKED',e)
  except:pass

ประเด็นสำคัญบางประการ:

  • ทุกคำสั่งที่ดำเนินการสามารถลบได้ การตรวจสอบว่าได้รับการดำเนินการต้องมีคำสั่งด้านนอกของq qการtryแก้ปัญหาที่ดีโดยต้องมีอย่างน้อยสองประโยคซึ่งไม่สามารถลบได้อย่างสมบูรณ์
  • การตรวจสอบว่าqมีการดำเนินการเกิดขึ้นโดยการประเมินrในตอนท้าย
  • การตรวจสอบว่าqได้รับการแก้ไขไม่ได้จะทำได้โดยการeval(q[17:])ซึ่งมีการประเมินผลNoneสำหรับqที่จะดำเนินการ
  • ifสภาพเป็นบิตยากที่จะได้รับสิทธิ เพื่อให้แน่ใจว่ามันถูกประเมินก็มีผลข้างเคียงที่ดีของการตั้งค่าซึ่งเป็นสิ่งจำเป็นในการตั้งค่าe r(นี่คือเหตุผลที่ฉันใช้ Python 3 exprเนื่องจากฟังก์ชั่นนี้สร้างความมหัศจรรย์สำหรับผลข้างเคียงในระดับนิพจน์)

ไม่ใช่ความท้าทายที่การลบจะไม่ทำให้เกิดข้อผิดพลาดทางไวยากรณ์หรือไม่ คุณดูเหมือนจะก่อให้เกิดข้อผิดพลาด runtime
Martin Lütke

5
@ MartinLütkeข้อผิดพลาดประเภทใดก็ได้
งานอดิเรกของ Calvin

1
อืม 79 ไบต์นี้ใช่มั้ย
Matt

@TheMatt ใช่มั้ย ฉันแค่นับพวกเขาอีกครั้งและคุณดูเหมือนจะถูกต้อง บางทีฉันที่ผ่านมานับบรรทัดใหม่ CRLF ... น่าอายแค่ไหน ขอบคุณ!
ฟิลิปป์

25

Haskell, 61

x=uncurry(:)
main=putStr$x('w',x('o',x('r',x('l',x('d',[])))))

ข้อผิดพลาดใด ๆ ก็โอเค? ในกรณีนั้น:

Haskell, 39

main=putStr$take 5$(++)"world"undefined

ใช้งานได้ไหมถ้าคุณลบตัวอักษรตัวใดตัวหนึ่งออก?
lirtosiast

มันจะพังระหว่างการทำงาน เพราะมันจะพยายามประเมินไม่ได้กำหนด
Martin Lütke

มันยอดเยี่ยมมาก การประเมินผลขี้เกียจ FTW มันปรากฏขึ้น!
DLosc

1
ฉันหวังว่า 'inits' อยู่ในบทโหมโรง :( จากนั้น: main = putStr $ inits "โลก" !! 5 (27 bytes)
Martin Lütke

16

JavaScript, 74 73 35 ไบต์

if((alert(a="world")?x:a)[4]!="d")x

ปรากฎว่าคำตอบนั้นง่ายกว่าที่ฉันคิดไว้มาก ...

คำอธิบาย

if(
  (
    alert(a="world") // throws a is not defined if '="world"' is removed
        ?x           // throws x is not defined if 'alert' or '(a="world")' is removed
        :a           // throws a is not defined if 'a="world"' or 'a=' is removed
  )
  [4]!="d"           // if "world" is altered fifth character will not be "d"
                     // if 'd' is removed it will compare "world"[4] ("d") with ""
                     // if '[4]' is removed it will compare "world" with "d"
                     // if '(alert(a="world")?x:a)' is removed it will compare [4] with "d"
                     // if '?x:a' is removed [4] on alert result (undefined[4]) will error
                     // if '[4]!="d"' is removed the if will evaluate "world" (true)
                     // if '!', '!="d"' or '(alert...[4]!=' is removed the if will
                     //     evaluate "d" (true)
)x                   // throws x is not defined if reached

// any other combination of removing substrings results in a syntax error

ลบทุกอย่างยกเว้นa="world"ไม่มีข้อผิดพลาด
anOKsquirrel

3
@anOKsquirrel สามารถลบสตริงย่อยเดียวได้
เดนนิส

4
ฉันผ่านสิ่งนี้เช่น "ฉันจะลบสิ่งนี้ได้หรือไม่ไม่ข้อผิดพลาดนี้จะเกิดขึ้นสามารถถูกลบได้หรือไม่ดีฉันเดาว่ามันจะทำให้เกิดข้อผิดพลาดอื่น ๆ อ๊ะ! ตัวอักษรเหล่านั้นสามารถลบออกได้!
ETHproductions

if(a="world")["bol"+a[4]]ไม่ผิดพลาด
anOKsquirrel

4
วัวศักดิ์สิทธิ์ตอนนี้น่าประทับใจเป็นสองเท่า! หวังว่าฉันจะสามารถ +1 อีกครั้ง ...
ผลิตภัณฑ์ ETH

15

Java 8, 301 bytes

เพราะคำถามทุกข้อต้องการคำตอบ Java

class C{static{System.out.print(((((w='w')))));System.out.print((((o='o'))));System.out.print(((r='r')));System.out.print((l='l'));System.out.print(d='d');e=(char)((f=1)/((g=8)-C.class.getDeclaredFields()[h=0].getModifiers()));}public static void main(String[]a){}static final char w,o,r,l,d,e,f,g,h;}

ขยาย

class C {
    static {
        System.out.print(((((w = 'w')))));
        System.out.print((((o = 'o'))));
        System.out.print(((r = 'r')));
        System.out.print((l = 'l'));
        System.out.print(d = 'd');
        e = (char) ((f = 1) / ((g = 8) - C.class.getDeclaredFields()[h = 0].getModifiers()));
    }

    public static void main(String[] a) { }

    static final char w, o, r, l, d, e, f, g, h;
}

คำอธิบาย

  • public static main(String[]a){} จำเป็น.
  • หากการประกาศเขตข้อมูลถูกลบ (หรือทำให้ไม่คงที่) บล็อกแบบคงที่แรกไม่สามารถหาได้
  • หากบล็อกแบบคงที่จะถูกลบ (หรือทำแบบไม่คงที่) ฟิลด์จะไม่เริ่มต้น

ส่วนที่ยากที่สุด:

  • หากfinalคำหลักถูกลบบรรทัดที่สองจะประเมิน1/(8-8)ว่าเป็นสาเหตุทำให้เกิด/ by zeroข้อยกเว้น

ทำไมคุณไม่สามารถลบส่วนในของคำสั่งการพิมพ์ใด ๆ
Nic Hartley

2
@QPaysTaxes ไม่มีSystem.out.print()วิธีที่ว่างเปล่า นอกจากนี้สำหรับการแต่ไม่ได้สำหรับprintln() print()ดังนั้นถ้าคุณจะลบd='d'มันจะให้The method print(boolean) in the type PrintStream is not applicable for the arguments ()เป็นข้อผิดพลาด (และถ้าคุณจะลบd=มันก็จะให้The blank final field d may not have been initializedเป็นข้อผิดพลาด)
Kevin Cruijssen

15

Funciton , 143 142 136 ไบต์

คะแนนเป็น UTF-8 ตามปกติเนื่องจาก UTF-16 จะใหญ่กว่าสองไบต์ (เนื่องจาก BOM)

╔══════════╗
║1934282307║╔╗
║5080880373╟╚╝
║80718711  ║
╚══════════╝

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

แต่ตัวอักษรในบรรทัดเดียวนั้นมีราคาแพงฉาวโฉ่ทั้งเนื่องจากจำนวนอักขระที่มากขึ้นและเนื่องจากอักขระที่ไม่ใช่ ASCII จำนวนมากขึ้น และเขาพูดถึงบล็อก "ความคิดเห็นที่ว่างเปล่า" ทำให้ฉันคิดว่า ...

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

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

ที่เหลือสองตัวเลือก (ขอบคุณSteve ที่ชี้ให้เห็น):

  • ลบบรรทัดที่สี่ นั่นทำให้ทั้งสองกล่องมีไหวพริบ แต่เมื่อจำนวนเต็มส่งผลให้19342823075080880373มีการถอดรหัสสตริงที่สอดคล้องกันจะมีจุดรหัส0x18D53Bซึ่งไม่ได้เป็นอักขระ Unicode ที่ถูกต้องเกิดปัญหากับSystem.Char.ConvertFromUtf32ArgumentOutOfRangeException
  • ลบบรรทัดทั้งหมดโดยเริ่มจากมุมบนขวา อีกครั้งทั้งสองกล่องจะอยู่ในชั้นเชิง แต่จำนวนเต็มที่เกิดขึ้น508088037380718711จะมีจุดรหัสที่ไม่ถูกต้องสองจุด0x1B0635และ0x140077นำไปสู่ข้อยกเว้นเดียวกัน

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


จะเกิดอะไรขึ้นถ้าคุณลบสตริงย่อยที่เริ่มต้นด้วยตัวอักษรหลังจากตัวเชื่อมต่อเอาท์พุทและจบบรรทัดที่ 1 ในภายหลัง เช่นลบบรรทัดกลางของบล็อกความคิดเห็นและบรรทัดที่มี "80718711" ในบล็อกหลัก แต่ทิ้งมุมของกล่องทั้งสองไว้เหมือนเดิม
Steve

@ Steve ฉันได้แก้ไขคำตอบเพื่อให้ครอบคลุมกรณีนั้น หลังจากดูมันอีกเล็กน้อยสิ่งนี้ทำให้ฉันสามารถบันทึกอักขระสองตัว / หกไบต์ได้จริง
Martin Ender

10

ทับทิม, 36

eval(*[(s="planet")[$>.write(s)^6]])

เรากำหนดs="planet"แล้วเขียนสตริงนั้นไปที่ STDOUT ส่งคืนจำนวนอักขระที่เขียน เรา xor นั่นกับ 6 ดังนั้นถ้ามีสิ่งใดนอกเหนือจาก 6 ตัวอักษรที่ถูกเขียนขึ้นเราจะได้จำนวนเต็มที่ไม่ใช่ศูนย์ จากนั้นเราก็เจาะเข้าไปsกับดัชนีนั้น เฉพาะอักขระที่ 0 ของs"p" เท่านั้นที่เป็นสตริงรหัสที่ถูกต้อง (ไม่มีตัวเลือก) เราส่งผ่านไปยังevalโดยใช้(*[argument])ไวยากรณ์ที่เทียบเท่าเพียง(argument)ยกเว้นว่ามันไม่ถูกต้องนอกการเรียกวิธีการ

การตรวจสอบความถูกต้องอย่างละเอียดโดยทางโปรแกรมใน Ruby 1.9.3 และ 2.2


อึศักดิ์สิทธิ์ มันอัศจรรย์มาก.
ตบมือ

เกิดอะไรขึ้นถ้าคุณลบ*?
LegionMammal978

จากนั้นคุณก็ผ่านอาร์เรย์เพื่อหาค่าแทนที่จะเป็นสตริงซึ่งก็คือ ArgumentError
ฮิสโทแคต

9

C #, 128 118 101 ไบต์

คิดว่าจะใช้กฎสตริงย่อยที่ต่อเนื่องกัน

รหัส

class h{static void Main()=>System.Console.Write(new char[1
#if!i
*5]{'w','o','r','l','d'
#endif
});}

ทำไมมันถึงได้ผล

  1. class hและstatic void Main()มีความจำเป็น
  2. การลบใด ๆ ของตัวอักษรในสาเหตุข้อผิดพลาดเนื่องจากแถวถ่านจะเริ่มต้นที่มีความยาว'w','o','r','l','d'1*5
  3. คุณไม่สามารถลบเนื้อหาใน Main () โดยไม่ละเมิดกฎของตัวอักษรที่ต่อเนื่องกันเนื่องจากชิ้นส่วนถูกคั่นด้วย preprocs (ดูด้านล่าง)

ก่อนเล่นกอล์ฟและแยกตัว

class h
{
    static void Main() =>
        System.Console.Write(new char[1 * 5]{'w','o','r','l','d'});
}

ยืนยันด้วย

https://ideone.com/wEdB54

แก้ไข:

  • ที่บันทึกไว้ไบต์บางอย่างโดยใช้แทน#if !x#if x #else
  • =>ไวยากรณ์ func ใช้แล้ว แทน#if!x #if !xเครดิตไปที่ @JohnBot
  • เนื่องจาก=>ไวยากรณ์ของ func ทำให้สามารถลบเงื่อนไขล่วงหน้าได้

สวัสดีเกลียว! คุณคิดว่าคุณสามารถอธิบายได้อย่างไรและทำไมคำตอบของคุณจึงใช้งานได้มากกว่าเดิม?
isaacg

@isaacg แก้ไขแล้ว พิสูจน์ให้เห็นตาม
Helix Quar

ฉันไม่สามารถได้รับมันจะทำงานได้โดยไม่เกี่ยวกับstatic Main
Johnbot

@Johnbot ใช่ ต้องผิดพลาด แก้ไขแล้ว.
Helix Quar

คุณสามารถบันทึกตัวอักษรโดยการสมาชิกฟังก์ชั่นการแสดงออกฉกรรจ์และ 2 มากขึ้นโดยการลบช่องว่างก่อนสภาพ preprocessor นี้: นั่นคือ 115 จากการนับของฉัน Mainclass h{static void Main()=>System.Console.Write(new char[1\n#if!l\n*5]{'w','o','r','l','d'\n#if!o\n});\n#endif\n}\n#endif
Johnbot

9

MATLAB, 37 36 33 ไบต์

feval(@disp,reshape('world',1,5))

เนื่องจากฉันไม่แน่ใจว่าเราได้รับอนุญาตให้ส่งออกans =ด้วยหรือไม่ดังนั้นฉันต้องหาวิธีแก้ไขบางอย่างเพื่อส่งออกด้วยวิธีที่เหมาะสม การใช้fprintfด้วยตัวเองไม่ได้ผลเพราะไม่ว่าฉันจะพยายามทำอะไร การใช้dispด้วยตัวมันเองนั้นไม่ใช่ตัวเลือกเนื่องจากมันจะใช้เวลาเพียงแค่ 1 ข้อโต้แย้งเท่านั้นและการโต้แย้งนั้นเองก็จะดำเนินการโดยไม่มีข้อผิดพลาด

หากไม่มีปัญหาในการรวมans =ในเอาต์พุตด้วย MATLAB สามารถทำได้ด้วย20 ไบต์ :

reshape('world',1,5)

ฉันต้องเรียนรู้เพิ่มเติมเกี่ยวกับฟังก์ชั่นในตัว (+1) // btw โปรแกรมของคุณได้คะแนน 20
Abr001am

2
ขึ้นอยู่กับว่ากฎนั้นเข้มงวดแค่ไหน พวกเขาระบุว่าควรพิมพ์เฉพาะ 'world' (+ ขึ้นบรรทัดใหม่ท้าย) เท่านั้นดังนั้นจึงมีขนาด 33 ไบต์
slvrbld

ใช่เราจะนับเป็น 33 ขอบคุณสำหรับความเข้าใจ :)
งานอดิเรกของ Calvin

9

> <> , 17 ไบต์

e"ooooo7-c0pBhtra

ลองออนไลน์!

พิมพ์ "earth"

วิธีเดียวที่><>โปรแกรมออกโดยไม่มีข้อผิดพลาดคือการเรียกใช้;อักขระซึ่งเป็นปัญหาเนื่องจากคุณสามารถลบอักขระทั้งหมดก่อนหน้านั้นได้ดังนั้นจึง;เป็นอักขระตัวแรกที่ถูกเรียกใช้ คุณสามารถแก้ไขได้โดยใช้pคำสั่งเพื่อปรับเปลี่ยนโปรแกรมที่จะรวม;ในระหว่างการดำเนินการแทน การถอดส่วนใดส่วนหนึ่งของรหัสที่เป็นสาเหตุที่ทำให้;ไม่เคยมีการผลิตที่ก่อให้เกิดข้อผิดพลาดผ่านคำแนะนำที่ไม่ถูกต้องB, hและtกองอันเดอร์โฟล์และลูปอนันต์ทำให้ในที่สุดก็วิ่งออกมาจากหน่วยความจำ ฉันต้องทำให้แน่ใจว่าลูปที่ไม่มีที่สิ้นสุดทั้งหมดยังคงเต็มไปด้วยสแต็ค

ตัวแปรทั้งหมดได้รับการทดสอบโดยใช้ตัวอย่างงูหลาม:

code = 'e"ooooo7-c0pBhtra'
count = {"invalid":0, "underflow":0, "memory":0}
for l in range(1, len(code)):
    for x in range(0, len(code)-l+1):
        print(code[:x] + code[x+l:], "\t\t", end='')
        try:
            interp = Interpreter(code[:x]+code[x+l:])
            for _ in range(0,1000):
                interp.move()
            print(len(interp._stack), "< ", end='')
            interp2 = Interpreter(code[:x]+code[x+l:])
            for _ in range(0,2000):
                interp2.move()
            print(len(interp2._stack))
            count["memory"] += 1
        except Exception as e:
            print(e)
            if str(e) == "pop from empty list": count["underflow"] += 1
            else: count["invalid"] += 1
print(count) 
#don't judge me

เพิ่มไปยัง (เวอร์ชันดัดแปลงเล็กน้อย) ล่ามfish.pyอย่างเป็นทางการโดยผู้สร้าง> <> ออกจากโปรแกรมย่อย 152 ที่เป็นไปได้ 92 ข้อผิดพลาดจากคำแนะนำที่ไม่ถูกต้อง 18 จากสแตกอันเดอร์โฟลว์และ 42 จากหน่วยความจำไม่เพียงพอ

ข้อเท็จจริงตลกรุ่นแรกนี้e"ooooo6-c0pAhtraมีคู่ของประหลาดย่อยโปรแกรมที่มีการจัดการที่จะใช้คำสั่งใส่เพื่อวางที่ซึ่งจะล้างสแต็คในสถานที่ของการเรียนการสอนที่ไม่ถูกต้อง[ Aนอกจากนี้ "โลก" เป็นเพียงหนึ่งในวลีที่จะทำงานกับวิธีนี้เพราะตัวอักษรตัวแรกeเป็นคำสั่งที่ถูกต้องใน><>เป็นคำแนะนำที่ถูกต้องในมิฉะนั้น"จะต้องวางคำสั่งไว้ที่ด้านหน้าของโปรแกรมและโปรแกรมย่อยที่ถูกต้องอาจเป็นได้"ด้วยตัวเอง


8

ทับทิม, 34

eval(*[($>.write("world")-1).chr])

นี่เป็นส่วนประกอบบางส่วน:

eval(*[ expr ])ยืมมาจากคำตอบของ histocratและล้วนๆเช่นเดียวกับการตรวจสอบค่าส่งคืนของexprเป็นโปรแกรมทับทิมที่ถูกต้องที่ไม่ผิดพลาด method(*arr)เป็นไวยากรณ์ทับทิมที่เรียกว่าmethodมีค่าarrเป็นอาร์กิวเมนต์ เหตุผลที่จำเป็นในที่นี้คือเนื่องจากใช้ได้เฉพาะกับพารามิเตอร์สำหรับวิธีการดังนั้นหากevalถูกลบออก(*[expr])จะเป็นข้อผิดพลาดทางไวยากรณ์ ถ้าexprถูกลบออกไปevalบ่นว่ามีข้อโต้แย้งไม่เพียงพอ

$>.write("world")-1ไม่สามารถ mangled ยกเว้นภายในสตริงและการลบ $>.write("world")เขียน "โลก" เพื่อ STDOUT และส่งกลับจำนวนตัวอักษรที่เขียนแล้วลบ 1. ดังนั้นถ้าโปรแกรมคือยกเลิก mangled ค่าจะตรง4 ถ้ามันเป็นแหลกเหลว (อย่างใดอย่างหนึ่ง-1จะถูกลบออกหรือสตริงสั้นลง) แล้วมันจะกลับมาเป็นหนึ่งใน-1,0,1,2,3 หรือ 5 mangling อื่นใดส่งผลให้เกิดข้อผิดพลาดทางไวยากรณ์

การโทรหาchrหมายเลขจะคืนค่าอักขระที่แทนด้วยหมายเลขนั้น ดังนั้นเมื่อเรียกผลลัพธ์ของตัวอย่างข้างต้นข้อผิดพลาดใน -1 และส่งกลับสตริงอักขระเดี่ยว

ฉันไม่แน่ใจจริงๆว่าทำไมถึงเป็นเช่นนี้ แต่ดูเหมือนว่าการตีความทับทิม\x04เป็นตัวละครช่องว่างซึ่งหมายความว่าการแสดงออกที่ถูกต้อง (โปรแกรมทับทิมที่ว่างเปล่าไม่ทำอะไรเลย) อย่างไรก็ตามใด ๆ ของตัวละครอื่น ๆ ( \x00- \x03และ\x05) Invalid char '\x01' in expressionส่งผลให้เกิด ฉันพบสิ่งนี้โดยทำซ้ำมากกว่าคณิตศาสตร์ที่เป็นไปได้ที่ฉันสามารถทำได้กับจำนวนที่ส่งคืน ก่อนหน้านี้ฉันเคยใช้

$>.write("planet
")*16

โดยที่ "ดาวเคราะห์" บวกกับการขึ้นบรรทัดใหม่คือ 7 ตัวอักษรคูณ 16 เพื่อให้ได้ 112 สำหรับpฟังก์ชันตัวอักษรตัวเดียวเท่านั้นในทับทิมที่กำหนดโดยค่าเริ่มต้น เมื่อไม่ได้รับข้อโต้แย้งมันจะไม่มีประสิทธิภาพ


รางวัลชมเชย: $><<"%c"*5%%w(w o r l d)ใกล้มาก แต่ไม่เก่าแก่ การลบ"%c"*5%ผลลัพธ์โดยไม่มีข้อผิดพลาด Mini-คำอธิบาย:

$>คือ stdout และ<<เป็นฟังก์ชันที่ถูกเรียกใช้ "%c"*5สร้างรูปแบบของสตริง"%c%c%c%c%c"ที่แล้วแล้ว trys การจัดรูปแบบ ( %) โดยอาร์เรย์: ซึ่งเป็นรุ่นที่สั้นลง%w(w o r l d) ['w','o','r','l','d']หากมีองค์ประกอบในอาร์เรย์น้อยเกินไปหรือมากเกินไปซึ่งไม่ตรงกับสตริงรูปแบบจะมีข้อผิดพลาดเกิดขึ้น ส้นเท้าของอาคิลลิสคือสิ่ง"%c"*5นั้นและ%w(w o r l d)ทั้งคู่สามารถดำรงอยู่ได้อย่างอิสระและ$><<ต้องการเพียงข้อโต้แย้งอย่างใดอย่างหนึ่ง ดังนั้นจึงมีวิธีที่แตกต่างกันเล็กน้อยในการจัดการโปรแกรมนี้ให้เป็นลูกพี่ลูกน้องที่ไม่มีข้อผิดพลาด


ตรวจสอบโดยใช้สิ่งนี้:

s = 'eval(*[($>.write("world")-1).chr])'
puts s.size
(1...s.length).each do |len| #how much to remove
  (0...len).each do |i| #where to remove from
    to_test = s.dup
    to_test.slice!(i,len)
    begin #Feels so backwards; I want it to error and I'm sad when it works.
      eval(to_test)
      puts to_test
      puts "WORKED :("
      exit
    rescue SyntaxError
      #Have to have a separate rescue since syntax errors
      #are not in the same category as most other errors
      #in ruby, and so are not caught by default with 
      #a plain rescue
    rescue
      #this is good
    end
  end
end

คำอธิบายตามคำตอบของฮิสโทแคตจะดีมาก ดูเหมือนว่าคุณกำลังใช้วิธีการพื้นฐานแบบเดียวกัน แต่เนื่องจากฉันไม่รู้ว่า Ruby ฉันจึงไม่เข้าใจรายละเอียด
ThisSuitIsBlackNot

@ ThisSuitIsBlack ไม่ดีที่สุดของฉันอะไรที่คุณไม่เข้าใจ?
Shelvacu

คำอธิบายที่ยอดเยี่ยมขอบคุณ!
ThisSuitIsBlackNot

6

Python 3 , 43 ไบต์

for[]in{5:[]}[open(1,"w").write("world")]:a

ลองออนไลน์!

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

เพื่อป้องกันการลบ substring เราจะใช้แทนopen(1,"w").write printใน Python 3 writeส่งคืนจำนวนอักขระที่เขียนซึ่งเราจะตรวจสอบคือ5ให้แน่ใจว่าไม่มีการลบส่วนใดส่วนหนึ่งของสตริง เราทำสิ่งนี้โดยค้นหาค่าส่งคืนในพจนานุกรม{5:[]}และวนซ้ำผลลัพธ์ด้วยfor[]in…:aซึ่งจะล้มเหลวหากเราไม่ได้รับ iterable ที่ว่างเปล่าหรือถ้าforคำสั่งนั้นถูกลบ


4

Javascript (Node.js), 93 95 ไบต์

if(l=arguments.callee.toString().length,l!=158)throw l;console.log("world");if(g=l!=158)throw g

ตรวจสอบขนาดของตัวเองสองครั้งดังนั้นหากตัวอักษรใด ๆ หายไปข้อผิดพลาดจะถูกโยน ความยาวคือ 156 เนื่องจาก Node.js function (exports, require, module, __filename, __dirname) {นำเสนอโค้ดในรันไทม์

ขอบคุณ Martin Büttnerที่ชี้ข้อผิดพลาด แก้ไขแล้ว


4

Perl 5.10+, 71 63 ไบต์

(${open 0;@{\(read(0,$a,63)!=63?die:@_)};say"world"});{$a//die}

พิมพ์worldด้วยบรรทัดใหม่ต่อท้าย ทำงานแบบนี้:

perl -M5.010 file

สิ่งนี้ขึ้นอยู่กับจำนวนไบต์ของซอร์สโค้ดดังนั้นจึงfileต้องมีโค้ดด้านบนและไม่มีสิ่งอื่นใด (ไม่มี shebang ไม่มีการขึ้นบรรทัดใหม่ตามมา) Perl 5.10+ เป็นสิ่งจำเป็นสำหรับการที่กำหนดไว้หรือผู้ประกอบการsay//


มันยากอย่างเหลือเชื่อที่จะสร้างโปรแกรมที่เก่าแก่ด้วย Perl เพราะ:

  • ใด ๆ ที่ระบุ bareword (เช่นfoo, a, _) เป็นคำสั่งที่ถูกต้องด้วยno strict 'subs';(เริ่มต้น) ซึ่งหมายความว่าโปรแกรมไม่สามารถเริ่มหรือจบด้วยตัวอักษรตัวเลขหรือขีดล่าง

  • ตามที่tchrist อธิบายว่า "ตัวระบุที่ระบุผ่านการลงทะเบียนแบบสัญลักษณ์ไม่มีข้อ จำกัด ใด ๆกับชื่อของพวกเขา" ซึ่งหมายความว่าโปรแกรมไม่สามารถเริ่มต้นด้วยการใด ๆ ของ sigils $, @, %หรือ*ตั้งแต่การลบทั้งหมด แต่ตัวอักษรตัวแรกและครั้งสุดท้ายมักจะปล่อยให้ชื่อตัวแปรที่ถูกต้อง

  • ฟังก์ชันในตัวหลายตัว (รวมถึงฟังก์ชั่นส่วนใหญ่ที่สามารถสร้างเอาต์พุต) ทำงาน$_ตามค่าเริ่มต้นดังนั้นการโทรมักจะใช้งานได้แม้ว่าคุณจะลบอาร์กิวเมนต์ (เช่นsay"world"vs. say)

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

โซลูชันนี้ได้รับแรงบันดาลใจจากคำตอบ Node.js ของ Naouakซึ่งจะตรวจสอบความยาวของตัวเองเพื่อให้แน่ใจว่าตัวละครยังไม่ถูกลบ

โปรแกรมมีสองส่วนส่วนหนึ่งอยู่ในวงเล็บและอีกส่วนหนึ่งอยู่ในบล็อก:

(...);{...}

ส่วนแรกอ่านไฟล์ต้นฉบับและตายหากไฟล์มีความยาวน้อยกว่า 63 อักขระ ส่วนที่สองตรวจสอบว่าการreadดำเนินการเรียบร้อยแล้ว หากส่วนใดส่วนหนึ่งถูกลบออก (มีหรือไม่มีวงเล็บปิดล้อมหรือวงเล็บปีกกา) ส่วนอื่น ๆ จะโยนข้อยกเว้น

การลบตรงกลางหรือด้านซ้ายหรือด้านขวาของโปรแกรมจะทำให้ไม่สมดุลของวงเล็บและ / หรือวงเล็บปีกกาทำให้เกิดข้อผิดพลาดทางไวยากรณ์

หากครั้งแรกที่dieมีการเปลี่ยนแปลง (เพื่อd, e, di, deหรือieที่มีทั้งหมดตัวบ่งชี้ที่ถูกต้อง) ตรวจสอบความยาวกลายเป็น:

@{\(read(0,$a,63)!=63?di:@_)};

ซึ่งประเมินว่า:

@{\'di'};

สิ่งนี้ใช้การอ้างอิงไปยังสตริงและพยายามอ้างถึงมันเป็นอาร์เรย์ทำให้เกิดข้อผิดพลาด:

Not an ARRAY reference

หากมีการเปลี่ยนแปลงข้อความอื่น ๆ การตรวจสอบความยาวจะล้มเหลวและโปรแกรมจะตาย


ตรวจสอบความบริสุทธิ์ด้วยโปรแกรมต่อไปนี้:

#!/usr/bin/perl

use strict;
use warnings;
use 5.010;

use File::Temp;
use List::MoreUtils qw(uniq);

sub delete_substr {
    my ($str, $offset, $len) = @_;

    my $tmp = $str;
    substr($tmp, $offset, $len) = '';

    return $tmp;
}

sub generate_subprograms {
    my ($source) = @_;

    my $tot_len = length $source;
    my @subprograms;                                             

    foreach my $len (1 .. $tot_len - 1) { 
        foreach my $offset (0 .. $tot_len - $len) {
            push @subprograms, delete_substr($source, $offset, $len);
        }                                                        
    }                                                            

    return uniq @subprograms;                                    
}                                                                

chomp(my $source = <DATA>);                                                                                                       
my $temp = File::Temp->new;                                                                                        

foreach my $subprogram ( generate_subprograms($source) ) {       
    print $temp $subprogram;

    my $ret = system(qq{/usr/bin/perl -M5.010 $temp > /dev/null 2>&1});
    say($subprogram), last if $ret == 0;

    truncate $temp, 0;
    seek $temp, 0, 0;
}

__DATA__
(${open 0;@{\(read(0,$a,63)!=63?die:@_)};say"world"});{$a//die}

4

Ruby + coreutils, 33 27 26 ไบต์

`base#{$>.write"world
"}4`

ลองออนไลน์!

Backticks ใน ruby ​​รันคำสั่งภายในพวกมันและคืนสิ่งที่โปรแกรมที่ใส่ไว้ใน STDOUT เป็นสตริง #{expr}ไวยากรณ์ช่วยให้การฝังตัวของการแสดงออกในสตริงและ backticks โปรแกรมนี้สามารถเขียนใหม่ (ไม่ใช่ pristinely) เป็น:

system("base" + (STDOUT.write("world\n")).to_s + "4")

IO#writeส่งคืนจำนวนไบต์ที่เขียนดังนั้นหากสตริงสั้นลงจะไม่เป็นจำนวนที่ถูกต้อง #{}การฝังโดยอัตโนมัติทำให้ตัวเลขเป็นสตริง หากมีการลบบางส่วนออกไปและไม่ส่งผลให้เกิดข้อผิดพลาดทางไวยากรณ์คำสั่งที่ผิดจะถูกเรียกใช้ หากส่วนหนึ่งส่วน"world"ใดถูกลบเกินกว่าส่วนใดส่วนหนึ่งbase04ผ่านbase54จะพยายามเรียกใช้

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


exec(*[(s="ec%co earth")%s[10]])

execแทนที่กระบวนการ ruby ​​ปัจจุบันด้วยคำสั่งที่ระบุ ดูคำตอบอื่น ๆ ของฉันสำหรับคำอธิบายของmeth(*[])ไวยากรณ์และความจำเป็นของมัน

(s="ec%co earth")กำหนดสตริง "ec แผ่นดิน% ร่วม" sให้กับตัวแปร การมอบหมายส่งคืนสิ่งที่ได้รับมอบหมายดังนั้นสตริงจะถูกส่งคืนเช่นกัน

"format string %d" % 5เป็นน้ำตาลซินแทคติกสำหรับsprintf("format string %d",5)อย่างไรก็ตามช่องว่างรอบ ๆ%ไม่จำเป็น

s[10]รับตัวละครในสตริงที่ดัชนี 10 เมื่อไม่ได้พันกันอักขระนี้คือ "h" ตัวอักษรตัวสุดท้ายในสตริง อย่างไรก็ตามการลบอักขระใด ๆ ในสตริงหมายถึงสตริงนั้นสั้นกว่าดังนั้นจึงไม่มีอักขระที่ดัชนี 10 ดังนั้นs[10]ส่งคืนnilและ"%c" % nilทำให้เกิดข้อผิดพลาด

หาก%s[10]ถูกลบออกทับทิมจะพยายามเรียกใช้คำสั่งec%co earthที่ไม่ทำงาน

การเปลี่ยน10เป็น1หรือ0ยังส่งผลให้เกิดคำสั่งที่ไม่รู้จัก (อย่างใดอย่างหนึ่งeceoหรือecco) การลบออกทั้งหมดไม่ได้เป็นข้อผิดพลาดทางไวยากรณ์เนื่องจากจะเรียกใช้เมธอด#[]บนสตริง แต่จากนั้นจะบ่นเกี่ยวกับข้อโต้แย้งไม่เพียงพอ


บันทึกเกี่ยวกับการแก้ปัญหานี้โดยทั่วไป: คุณต้องมีเสื้อคลุมบางอย่างที่ตรวจสอบรหัสภายในในแง่นามธรรมขณะที่ตัวเองล้วนๆ ตัวอย่างเช่นโปรแกรมที่มีการแบ่งที่ส่วนท้าย ( blablabla/somevar) จะไม่ทำงานเพราะสามารถลบการหารได้เสมอ ( blablabla) นี่คือบางส่วนที่ฉันเคยใช้:

  • eval(*[รหัสที่])ใช้โดย histocrat และในคำตอบแรกของฉัน ตรวจสอบว่าผลลัพธ์เป็นโปรแกรมทับทิมที่ถูกต้อง
  • exec(*[รหัสที่])ใช้ด้านบนตรวจสอบว่าการตอบสนองเป็นคำสั่งที่ถูกต้อง
  • `#{ รหัส }`

ไวยากรณ์ backtick ยังเรียกใช้คำสั่ง (และเพื่อตรวจสอบว่ามันเป็นหนึ่งที่ถูกต้อง) แต่ STDOUT จะถูกจับเป็นสตริงแทนที่จะเป็นเอาท์พุทเป็นกระบวนการหลัก '(Ruby's) STDOUT ด้วยเหตุนี้ฉันจึงไม่สามารถใช้สำหรับคำตอบนี้ได้แก้ไข: ฉันทำให้มันใช้งานได้ ข้อ จำกัด ที่ระบุไว้ข้างต้น

แก้ไข: ขอบคุณ @histocrat ที่ชี้ให้เห็นข้อบกพร่องบางอย่าง


วิธีการที่ยอดเยี่ยม! คุณสามารถ (และดังนั้นต้อง) ลบช่องว่างระหว่างwriteและจุดเริ่มต้นของสตริง แต่ฉันไม่คิดว่ามีผลกระทบต่อความบริสุทธิ์ นอกจากนี้ในเครื่องของฉันbase64จะรอการป้อนข้อมูลซึ่งอาจผิดกฎ
ชำนาญวิชาประวัติศาสตร์

@ ขุนนางว้าวฉันประหลาดใจที่ได้$>.write"world"ผลขอบคุณ! สำหรับ base64 กำลังรออินพุตดูเหมือนว่าจะแตกต่างกันไปตามระบบ TIO ทำงานได้ดี นั่นทำให้มันคลุมเครือมากขึ้นว่าจะเป็นไปตามกฎ
Shelvacu

3

PowerShell, (97 ไบต์ + 5 สำหรับชื่อโปรแกรม) = 102 ไบต์

"$(try{if(($a=(gc .\c.ps1).Length)-eq97){"world";a}}catch{if($a-ne97){a}$error.clear();exit}a)";a

ตรวจสอบตัวเองก่อนที่มันจะทำลายตัวเอง ... สองครั้ง

คาดว่าจะได้รับการบันทึกc.ps1และดำเนินการจากไดเรกทอรีภายในเครื่องเช่น:
PS C:\Tools\Scripts\Golfing\> .\c.ps1.

นามแฝงgcนั้นสั้นGet-Contentและคล้ายกันกับการcatอ่านไฟล์ (ในกรณีนี้คือพา ธ การประมวลผลของเรา.\c.ps1) เราได้รับ.Lengthของไฟล์ตั้งค่าให้$aและตรวจสอบว่ามันไม่ได้มีค่าเท่ากับ 97 -eq97ด้วย ถ้ามันจะมีค่าเท่ากับ (เช่นโปรแกรมที่ยังไม่ได้รับการแก้ไข) เราพิมพ์ด้วยและดำเนินการคำสั่งที่ไม่ถูกต้อง"world" aสิ่งนี้บังคับcatchให้มีผลบังคับใช้ซึ่งทำให้เราสามารถตรวจสอบตัวเองอีกครั้ง เวลานี้ถ้ารหัสของเราไม่เท่ากับ 97 เราจะโยนคำสั่งที่ไม่ถูกต้องดังนั้นโปรแกรมของเรามีข้อผิดพลาดและพิมพ์ข้อความผิดพลาดไปยังผลลัพธ์ เรานั้นclear()เกิดข้อผิดพลาดและexitตามปกติ

เห็นได้ชัดว่าหากifข้อความใดข้อความหนึ่งถูกดัดแปลงข้อความอื่นจะมีข้อผิดพลาด หากส่วนใดส่วนหนึ่ง"world";ถูกดัดแปลงส่วนแรกifจะทำให้เกิดข้อผิดพลาด เนื่องจากต้องต่อเนื่องกันเราจึงไม่สามารถลบทั้งสองifคำสั่งได้ สตริงที่อยู่ตรงกลางจะส่งผลให้ในวงเล็บที่ไม่ตรงกันหรือจะส่งผลให้ในครั้งที่สอง{a}ได้รับการดำเนินการ try/ catchคือการจับข้อผิดพลาดจากครั้งแรกifคำสั่งเพื่อให้เราสามารถที่ชัดเจนถูกต้อง ด้านนอก"$( )"ป้องกันสตริงจากปลายทั้งสองได้รับการ snipped ขั้นตอนสุดท้าย;aคือการป้องกันบางส่วนของการดึงกลางที่จะทำให้โปรแกรมที่ถูกต้อง (เช่น"it}a)";aซึ่งจะพิมพ์it}a)และจากนั้นเกิดข้อผิดพลาด)

มีสถานการณ์พิเศษหลายประการ:

  • ถ้าgc, gc<space>หรือgc .\ถูกลบออกโปรแกรมก็จะเกิดข้อผิดพลาดออกมาพร้อมกับรสชาติของออกมาจากข้อผิดพลาดในหน่วยความจำบางส่วน (เนื่องจากซ้ำโทรดำเนินการด้วยตนเอง) และมีแนวโน้มที่ผิดพลาดเปลือก (และอาจจะคอมพิวเตอร์) ไม่ผ่านการทดสอบ
  • หาก<space>.\c.ps1หรือ.\c.ps1ถูกลบออกโปรแกรมจะหยุดและแจ้งให้สำหรับผู้ใช้ป้อน ไม่ว่าผู้ใช้จะเข้าสู่โปรแกรมใดโปรแกรมนั้นจะยังคงมีข้อผิดพลาดเนื่องจากการนับขนาดจะผิด
  • หากสตริงย่อยเริ่มต้นที่$และสิ้นสุดก่อนที่"จะถูก snipped โปรแกรมจะส่งเอาต์พุตสิ่งที่เหลืออยู่และจากนั้นเกิดข้อผิดพลาดเนื่องจากaไม่ถูกต้อง

ตรวจสอบกับสิ่งต่อไปนี้:

$x='"$(try{if(($a=(gc .\c.ps1).Length)-eq97){"world";a}}catch{if($a-ne97){a}$error.clear();exit}a)";a'
$yy='"$(try{if(($a=( .\c.ps1).Length)-eq97){"world";a}}catch{if($a-ne97){a}$error.clear();exit}a)";a'
$yyy='"$(try{if(($a=(.\c.ps1).Length)-eq97){"world";a}}catch{if($a-ne97){a}$error.clear();exit}a)";a'
$yyyy='"$(try{if(($a=(c.ps1).Length)-eq97){"world";a}}catch{if($a-ne97){a}$error.clear();exit}a)";a'

for($i=1;$i-lt$x.Length;$i++){
  for($j=0;$j-lt($x.Length-$i);$j++){
    $y=($x[0..$j]+$x[($i+$j+1)..$x.Length])-join''
    $y>.\c.ps1
    $error.clear()
    if(!($y-in($yy,$yyy,$yyyy))){try{.\c.ps1}catch{};if(!($error)){exit}}
    $q++;
    write-host -n "."
    if(!($q%150)){""}
  }
}
"No success."

(ขอบคุณ Martin สำหรับความช่วยเหลือที่กว้างขวางของเขา!)


3

C (gcc) (Linux, -Werror=undef), 66 ไบต์

main(a){a
=
1
/
(puts("world")/
6);
#if(7^__LINE__)
#else
}
#endif

ลองออนไลน์!

ท้าทายมาก! นี่เป็นเรื่องหลอกลวงอย่างหนัก แต่ฉันค่อนข้างมั่นใจว่าฉันมีโปรแกรมที่ถูกต้องแล้ว!

ใช้คำสั่ง preprocessor เพื่อให้ไม่มีการขึ้นบรรทัดใหม่ที่สามารถถอดออกตั้งแต่วงเล็บปิดเพื่อจะรวมเฉพาะในกรณีที่main __LINE__==6นอกจากนี้ยังช่วยให้คุณไม่ต้องล้างออกmainทั้งหมดเนื่องจากปล่อยให้#endifลอย (ดังนั้นจึงเป็นสิ่งสำคัญที่#endifอยู่นอกmain)

ฉันใช้#elseเพราะฉันเชื่อมั่นอย่างเป็นธรรมไม่มีรุ่นของ__LINE__==6ที่ไม่สามารถลบซับสตริงและยังคงเป็นจริงเนื่องจากทั้งสอง6และ__LINE__โดยตัวเองเป็นจริง นอกจากนี้ยังใช้-Werror=undefเพื่อให้บางสิ่งบางอย่างเช่น#ifdef(LINE__)ไม่ได้ประเมินว่าเป็นเท็จ แต่เป็นข้อผิดพลาด

ด้วย gcc (บน Linux อย่างน้อย) putsส่งคืนจำนวนอักขระที่พิมพ์ (รวมถึงบรรทัดใหม่ที่ต่อท้าย) ดังนั้นการลบส่วนใด ๆ ของสตริงจะputs("...")/6ส่งคืน0ดังนั้นจึง1/0ทำให้เกิดข้อยกเว้นจุดลอยตัว โปรดทราบว่าข้อยกเว้นนี้ไม่ได้เกิดขึ้นยกเว้นว่า1/0มีการกำหนดให้กับบางสิ่งดังนั้นจึงa=จำเป็นต้องใช้

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

เป็นโบนัสนี้จะช่วยให้การแก้ปัญหา 86 ไบต์สำหรับ C ++ สวยนิดเพียงแค่เพิ่ม#include <cstdio>และประกาศเป็นa ลองออนไลน์! (C ++)int


คุณสามารถลบออกได้1/ในขณะที่ออกจากบรรทัดใหม่และมันจะยังคงทำงานอยู่
Gastropner

@gastropner ใช่มั้ย 1ควรจะอยู่ในบรรทัดก่อนหน้านี้ฉันเชื่อว่า
คริส

น่าเศร้าที่สิ่งเดียวกันถือ =1จากนั้นคุณสามารถลบ ฉันคิดว่าคุณต้องใส่ 1 ลงบนเส้นของมันเอง
Gastropner

@gastropner ฉันคิดว่าคุณพูดถูก ฉันจะดูเพิ่มเติมในภายหลัง ขอบคุณ!
คริส

2

PHP, 73 ไบต์

<?=call_user_func(($p='ns')|(($f="u{$p}erialize"))?$f:'','s:5:"world"');

explination

ฉันถือว่าการกำหนดค่า php.ini เริ่มต้น ดังนั้น short_tags ถูกปิดใช้งาน ซึ่งหมายความว่าคุณไม่สามารถลบออก=จากแท็กเปิด

<?=unserialize('s:5:"world"');นี้เป็นพื้น

หากคุณลบส่วนใดส่วนหนึ่งของสตริงที่ทำให้เป็นอนุกรมคุณจะได้รับข้อผิดพลาด

คุณสามารถลบออกได้unserializeและสคริปต์ก็จะแสดงผลสตริงที่ต่อเนื่องกัน call_user_funcที่จะเอาชนะฉันใช้นี้ การลบหนึ่งใน params จะทำให้เกิดข้อผิดพลาด

'<?=call_user_func('unserialize','s:5:"world"');

อย่างไรก็ตามคุณสามารถลบออกunได้เพื่อเรียกใช้serializeฟังก์ชัน ดังนั้นเราจึงนำ 'ns' ออกมา การลบอักขระใด ๆ จะไม่ส่งผลให้ชื่อฟังก์ชันไม่ถูกต้อง

<?=call_user_func(($p='ns')&&($f="u{$p}erialize")?$f:'','s:5:"world"');

เราจะใช้อินไลน์หากจะใช้การกำหนดตัวแปรกับแท็กเอาท์พุท แทนที่จะใช้&&เราใช้ '|' เพื่อป้องกันการลบรายการเดียว&หรือลบการ$fมอบหมาย

คุณสามารถลบและจบลงด้วย='ns')&&($f="u{$p}erialize" ดังนั้นฉันจะเพิ่มวงเล็บเพิ่มรอบ($p)?$f:''$f="u{$p}erialize"

บันทึก

ในทางเทคนิคคุณสามารถลบแท็กเปิดโดยไม่เกิดข้อผิดพลาด อย่างไรก็ตามนี่ไม่ใช่สคริปต์ PHP อีกต่อไป แต่เป็นไฟล์ข้อความธรรมดา


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

มันไม่ PHP แต่เท็กซ์ / html จึงไม่ถูกต้อง PHP โปรแกรมอีกต่อไป
Martijn

1

Matlab (77)

bsxfun(@(c,b)arrayfun(@(x)getfield(c,{x}),conv(b,ismember(4,b))),'world',1:5)

ลองมัน

บันทึก:

ต่อไปนี้ @ คำแนะนำในการเพิ่มประสิทธิภาพของการออกแบบการทำ CPR หรือสิ่งที่ผมต้องเจอในการย่อยที่ไม่คาดฝันที่ไม่ได้นำไปสู่การรวบรวมข้อผิดพลาดใด ๆ เมื่อออกตัวอย่าง: การลบarrayfun(@(x)a(x),prod(b,ismember(4,1:5))),จากการแก้ไขก่อนหน้านี้ feval(@(a)arrayfun(@(x)a(x),prod(b,ismember(4,1:5))),'world')ไม่ได้สร้างข้อผิดพลาดใด! สำหรับรุ่นเดียวกันเมื่อเร็ว ๆ นี้มีbsxfun(@(a,b)arrayfun(@(x)(x),prod(b,ismember(4,b))),'world',1:5)และbsxfun(@(a,b)a,'world',1:5)ถ้าคุณถามว่าฉันเป็นอย่างไรเมื่อค้นหาพวกเขาออกในคอนโซลเอาท์พุทของฉันฉันร้องไห้เหมือนเด็กดังนั้นนี่คือโปรแกรม:

b=0;string='bsxfun(@(c,b)arrayfun(@(x)getfield(c,{x}),conv(b,ismember(4,b))),''world'',1:5)'
for u=1:numel(string),for j=u:numel(string)-2,try a=eval([string(1:u) string(j+2:end)]);catch(b); a=0;end; if a~=0, ['here is it : ' string(1:u) string(j+2:end)],end;end;end

ตัวอย่างของโปรแกรมที่ไม่ได้รับการรับรอง

แก้ไข:

ขอบคุณทุกคนที่อยู่ข้างๆ @Martin สำหรับการชี้รหัสก่อนหน้าของฉัน (ไม่ใช่ข้อผิดพลาด) ออก



1

ลูกแพร์ต้นไม้ 17 ไบต์

โปรแกรมนี้มีจำนวนไบต์พร้อมชุดบิตสูง (ที่ไม่ถูกต้อง UTF-8 ดังนั้นจึงไม่สามารถโพสต์บน TIO) ดังนั้นนี่คือxxdhexdump ที่ย้อนกลับได้:

00000000: 7072 696e 7427 776f 726c 6427 23cd 4290  print'world'#.B.
00000010: bf                                       .

คำอธิบาย

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

น่าเบื่อจริง ๆ แต่ผูกกับผู้นำคนปัจจุบันดังนั้นฉันรู้สึกว่ามันคุ้มค่าที่จะโพสต์

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