ทำให้ภาษาของคุณเป็นส่วนใหญ่ไม่สามารถใช้งานได้ (ด้ายของ Robber)


31

แรงบันดาลใจจากความคิดเห็นนี้ ...

ขอขอบคุณผู้ใช้Step Hen , Wheat-WizardและDennis ที่ช่วยฉันสร้างความแข็งแกร่งให้กับสเปคของความท้าทายนี้ก่อนโพสต์มัน!

นี่คือเธรดของ Robber! สำหรับด้ายของตำรวจไปที่นี่


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

  • รับอินพุตและเอาต์พุตตัวเลข

  • เพิ่มตัวเลขสองตัวเข้าด้วยกัน

  • ทดสอบว่าจำนวนหนึ่งเป็นจำนวนเฉพาะหรือไม่

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

ตำรวจจะเขียนโค้ดสองชุด:

  1. ภาษาที่ทำให้ภาษาส่วนใหญ่ใช้ไม่ได้เช่นลบฟังก์ชั่นในตัวเพื่อรับอินพุต / เอาต์พุตและการดำเนินการเชิงตัวเลข รหัสนี้ไม่ได้รับอนุญาตให้ผิดพลาดหรือออก มันควรจะเป็นไปได้ที่จะเพิ่มรหัสการสิ้นสุดของข้อมูลโค้ดนี้และรหัสที่จะได้รับการประเมิน และ

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

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

ตำรวจตอบเสมอจะเปิดเผย

  • แรกข้อมูลโค้ด (ไม่ชัดที่สอง)

  • ภาษา (รวมถึงรุ่นรองเนื่องจากการส่งส่วนใหญ่อาจขึ้นอยู่กับกรณีขอบแปลก ๆ )

  • รูปแบบ IO รวมถึงไม่ว่าจะเป็นฟังก์ชั่นหรือโปรแกรมเต็มรูปแบบ โจรต้องใช้รูปแบบเดียวกันเพื่อเป็นรอยแตกที่ถูกต้อง

  • กรณีขอบแปลก ๆ ที่จำเป็นสำหรับคำตอบในการทำงานของพวกเขา ยกตัวอย่างเช่นทำงานบนลินุกซ์หรือต้องเชื่อมต่ออินเทอร์เน็ต

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

นี่คือตัวอย่าง สำหรับตัวอย่างแรกคุณอาจเห็นโปรแกรม python 3 ต่อไปนี้เป็นคำตอบของตำรวจ:

Python 3

print=None

รับอินพุตจาก STDIN และเอาต์พุตไปยัง STDOUT

ตัวอย่างที่สองที่ถูกต้องอาจเป็นได้

import sys
a,b=int(input()),int(input())
sys.stdout.write(a+b)

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

print=None
import sys
a,b=int(input()),int(input())
sys.stdout.write(a+b)

นี่เป็นการถอดรหัสที่ถูกต้องสำหรับคำตอบของพวกเขา

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

ผู้ชนะของเธรดของ robber คือผู้ใช้ที่ถอดรหัสคำตอบได้มากที่สุดโดย tie-breaker เป็นเวลาที่พวกเขามาถึงรอยแตกN (ดังนั้นหากผู้ใช้สองคนที่แตกต่างกันแต่ละคนมี 5 รอยแตกตัวอย่างเช่นผู้ใช้ที่โพสต์ครั้งที่ 5 ของพวกเขาเป็นผู้ชนะ) หลังจากเวลาผ่านไปพอสมควรแล้วฉันจะยอมรับคำตอบของผู้ชนะด้วยคะแนนมากที่สุด

มีความสุข!

การชี้แจงกฎ

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

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

    import sys
    sys.exit()
    

    ไม่ถูกต้องเพราะมันไม่ทำลายภาษา มันหยุดทำงาน

  • หลังจากเป็นที่ปลอดภัยคะแนนของคุณคือการนับไบต์ทั้งเกร็ดเล็กเกร็ดน้อย

  • นี้ไปกลับไปกรุณาเปิดเผยกรณีขอบแปลก ๆ ที่จำเป็นสำหรับคำตอบของคุณในการทำงาน ... การส่งของคุณจะต้องมีข้อมูลเพียงพอก่อนที่จะถูกเปิดเผยที่จะทำซ้ำหลังจากที่ถูกเปิดเผย ซึ่งหมายความว่าหากคำตอบของคุณปลอดภัยแล้วคุณแก้ไขใน: นี่คือคำตอบของฉัน อ๊ะ BTW ใช้งานได้ก็ต่อเมื่อคุณใช้งานบน Solaris แล้วล้อเล่นกับคุณ! คำตอบของคุณไม่ถูกต้องและจะถูกลบและไม่ถือว่ามีสิทธิ์ได้รับรางวัล

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

ลีดเดอร์บอร์ด

นี่คือรายการของผู้ใช้ทุกคนที่มีรอยแตกอย่างน้อยหนึ่งครั้งเรียงตามคะแนนแล้วชื่อ (เรียงตามตัวอักษร) หากคุณส่งรอยแตกโปรดอัปเดตคะแนนของคุณ

#User                       #Score
Ilmari Karonen              8

Dennis                      5

Olivier Grégoire            4

Sisyphus                    3
Veedrac                     3

Arnold Palmer               2
Bruce Forte                 2
DJMcMayhem                  2
Dom Hastings                2
ppperry                     2

1bluston                    1
2012rcampion                1
Ben                         1
BlackCap                    1
Christian Sievers           1
Cody Gray                   1
HyperNeutrino               1
Joshua                      1
Kaz                         1
Mark                        1
Mayube                      1
Xnor                        1
zbw                         1

คำตอบ:


3

Java 8 โดย Olivier Grégoire

class A {
  public A() {
    String[] args = System.lineSeparator().split(",");
    System.out.print(Integer.parseInt(args[0]) + Integer.parseInt(args[1]));
  }
}

ลองออนไลน์!

เนื่องจากโอลิเวียร์อนุญาตให้ป้อนข้อมูลผ่านชุดคุณสมบัติโดยใช้อาร์กิวเมนต์ VM อย่างชัดเจนฉันจะระบุว่าควรป้อนข้อมูลให้ในอาร์กิวเมนต์ VM -Dline.separator=X,Yโดยที่XและYเป็นหมายเลขที่จะเพิ่ม นั่นคือเพื่อเพิ่มตัวเลข 17 และ 25 โปรแกรมควรจะเรียกใช้เป็น:

java -Dline.separator=17,25 Main

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


ps นี่คือความพยายามในการถอดรหัสก่อนหน้าของฉันซึ่งถือว่าไม่ถูกต้องเนื่องจากใช้คุณลักษณะเฉพาะของ JVM:

class SecurityManager extends sun.awt.AWTSecurityManager {
  static {
    String[] args = System.getProperty("sun.java.command").split(" ");
    int a = Integer.parseInt(args[args.length-2]);
    int b = Integer.parseInt(args[args.length-1]);
    System.out.println(a+b);
  }
}

ลองออนไลน์!

เรื่องนี้กลายเป็น verbose น้อยกว่าก่อนหน้านี้มาก ส่วนที่ยากคือการหาคลาสย่อยSecurityManagerที่ไม่ได้อยู่ในเนมสเปซที่ขึ้นต้นด้วย " java." ฉันสงสัยว่านี่ยังไม่ใช่วิธีแก้ปัญหาที่ตั้งใจ แต่ใช้งานได้ *

*) ใน TIO อย่างน้อยที่สุด sun.awt.AWTSecurityManagerระดับและsun.java.commandคุณสมบัติที่ดูเหมือนจะไม่ได้รับการบันทึกอย่างเป็นทางการและอาจไม่สามารถใช้ได้ใน JVMs ทั้งหมด


งานที่ดี! ฉันลองสิ่งนี้ แต่ไม่พบสิ่งSecurityManagerที่อยู่ในขอบเขต ... คุณสามารถอ่านได้จากSystem.inจุดนี้แม้ว่าจะยังไม่ปิด
zbw

ขออภัยนี้เป็นคำตอบขึ้นอยู่กับแพลตฟอร์มทั้งสองเรื่องที่เกี่ยวกับทั้งสองsun.awt.SecurityManagerและ"sun.awt.command"มีขึ้นอยู่กับแพลตฟอร์มและไม่ได้เป็นส่วนหนึ่งของ Java
Olivier Grégoire

ใช่แตก! :) ทางออกที่ตั้งใจไว้คือต้องผ่านSystem.getProperties().get("blah")(เพราะฉันบล็อกเฉพาะการเข้าถึงSystem.getPropertyไม่ใช่System.getProperties) แต่มันดีพอ! ทำได้ดี!
Olivier Grégoire

22

C (GCC / Linux) โดย Sisyphus

ตัวอย่างนี้ปิดฟังก์ชั่นที่ให้ไว้และเริ่มใหม่ (การฉีดรหัสแบบคลาสสิก) ซึ่งกำหนดตัวเองใหม่closeเพื่อให้แทนที่การปิด fd แทนที่จะเรียกใช้รหัสที่เราต้องการ

}
int close(int x) {
  int a, b;
  scanf("%d %d", &a, &b);
  printf("%d\n", a + b);

  exit(0);

20

Python โซลูชั่นของ Wheat Wizard ที่นี่

import sys
c="".join(open(__file__).read().split('\n')[4:])
if set(c)-set(' &)(,.:[]a`cdfijmonrt~')or"import"in c:sys.setrecursionlimit(1)
f=lambda\
:[]                                                      # my code starts here
sys.setrecursionlimit(1000)
print(int(input())+int(input()))

ฉันหมายถึงคุณสามารถตั้งค่า จำกัด การเรียกซ้ำได้และไม่มีอะไรเลวร้ายเกิดขึ้น ...

ทำงานบน TIO

บันทึก

นี่คือการส่ง CnR ครั้งแรกของฉันดังนั้นหากสิ่งนี้ขัดกับกฎใด ๆ โปรดบอกฉันและฉันจะลบสิ่งนี้


4
ฉันโง่ที่จะพลาดสิ่งนี้
Wheat Wizard

@WheatWizard :)
HyperNeutrino

@wheatwizard ยังไม่เปิดเผยโซลูชันที่คุณตั้งใจไว้ ฉันloooveจะเห็นเป็นตำรวจที่ดีขึ้นกับการแก้ปัญหาเดิมของคุณว่าการแก้ไขปัญหานี้
DJMcMayhem

@Djmcmayhem ฉันอาจจะโพสต์ใหม่ด้วย del sys
ข้าวสาลีตัวช่วยสร้าง

@WheatWizard โปรดจำไว้ว่าos.sysถ้ามันสร้างความแตกต่าง: P
HyperNeutrino

15

Haskell โดย Ben

import Prelude(getLine,print)
a=a
[]++s=s
(a:as)++s=a:(as++s)
r""=""
r(c:s)=(r s)++[c]
t(_:r)=r
ts l=l:ts(t l)
x[_](v:_)=v
x(_:r)(_:s)=x r s
d(a:_:_:_:_:_:_:_:_:_:r)=a:d r
(a:_)!!""=a
l!!(n:m)=d(x['0'..n](ts l))!!m
a+b=[[0..]!!a..]!!b
a-b=let n=[0..]!!a;m=[0..]!!b in
    case [n..m] of
      [] ->   x[m..n][0..]
      l  -> -(x l    [0..])
add('-':x)('-':y)= -(r x+r y)
add('-':x)y=r y-r x
add x('-':y)=r x-r y
add x y=x+y
main=do a<-getLine;b<-getLine;print(add a b)

ฉันยังคงมีตัวเลขตัวอักษรและตัวอักษร (ผมใช้0, '0'และ'-') และ[a..]และ[a..b]ซึ่งจะมีประโยชน์มาก และฉันก็เป็นน้ำหนึ่งใจเดียวกัน-แต่ฉันก็ทำได้โดยไม่ต้องทำ

ฉันสร้างใหม่++เพื่อใช้r( reverse) และกำหนดtและtsสิ่งที่tailและtailsและ x a bส่งคืนnองค์ประกอบที่ th ของbโดยที่nความยาวของaหนึ่งลบ มักจะได้รับการกำหนดให้เป็นx snd.last.zipฟังก์ชั่นdรับรายการและส่งคืนรายการที่มีองค์ประกอบจากตำแหน่งเหล่านั้นที่เป็นทวีคูณของสิบ l!!sส่งกลับnองค์ประกอบของวันlที่เป็นตัวแทนของสตริงตรงกันข้ามs ผลตอบแทนที่ได้เป็นจำนวนเต็มผลรวมของสองจำนวนธรรมชาติให้เป็นสตริงที่กลับรายการเช่นเดียวกันสำหรับความแตกต่าง ผลตอบแทนที่ได้เป็นจำนวนเต็มผลรวมของสองจำนวนเต็มลบที่อาจได้รับเป็นสตริงn+-add

ฉันสงสัยว่านี่จะคล้ายกับสิ่งที่เบ็นมีอยู่ในใจหรือไม่


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

7

C (gcc) โดย Conor O'Brien


void post_main() __attribute__ ((destructor));

void post_main()
{
    int a, b;
    char sum[11];
    void *stdin = fdopen(0, "r");

    fscanf(stdin, "%u %u", &a, &b);
    sprintf(sum, "%u", a + b);
    write(1, sum, strlen(sum));
}

ลองออนไลน์!


ugggg ฉันลืมที่จะแบน fscanf และฟังก์ชั่นอื่น ๆ อีกมากมาย>.> งานที่ดี
Conor O'Brien

7

Python 2 โดย Wheat Wizard (การทำซ้ำครั้งที่สี่)

import sys
if set("".join(open(__file__).read().split('\n')[4:]))-set(' &)(,.:[]a`cdfijmonrt~'):sys.setrecursionlimit(1)
for m in sys.modules:sys.modules[m]=None
del sys;f=lambda\
c,d:(`int([]in[])`[:[]in[]]).join([((c)and`dict([((int([]in[])),(int([]in[])))])`[(int([]in[[]])):][(int([]in[[]]))].join([`dict([((int([]in[])),(int([]in[])))])`[(int([]in[]))],`dict([((int([]in[])),c)])`[(int([]in[[]])):][(int([]in[[]])):][(int([]in[[]])):][(int([]in[[]])):]])or`int([]in[])`[:[]in[]]).format((int([]in[]))),((d)and`dict([((int([]in[])),(int([]in[])))])`[(int([]in[[]])):][(int([]in[[]]))].join([`dict([((int([]in[])),(int([]in[])))])`[(int([]in[]))],`dict([((int([]in[])),d)])`[(int([]in[[]])):][(int([]in[[]])):][(int([]in[[]])):][(int([]in[[]])):]])or`int([]in[])`[:[]in[]]).format((int([]in[]))),`(int([]in[]))`]).rfind(`(int([]in[]))`)

ลองออนไลน์!

ไม่มีการหาประโยชน์เพียงฟังก์ชั่นเพื่อเพิ่มการใช้อักขระเท่านั้น' &)(,.:[]a`cdfijmonrt~'ตามที่ต้องการ (จริง ๆ แล้วเท่านั้น'(),.:[]`acdfijmnort')

ฉันไม่พยายามทำให้สั้น ฉันเพิ่งเขียน subexpressions สำหรับค่ากลางเช่น 0 และสตริงว่างและแทนที่สตริงที่มา

def f(c,d):
	FALSE = []in[]
	TRUE = []in[[]]
	ZERO = int([]in[])
	ONE = int(TRUE)
	EMPTY = `int([]in[])`[:[]in[]]
	ZERO_STR = `ZERO`
	ONE_STR = `ONE`

	ZERO_DICT = dict([(ZERO,ZERO)])
	ZERO_DICT_STR = `ZERO_DICT`

	OPEN_BRACE = ZERO_DICT_STR[ZERO]
	COLON = ZERO_DICT_STR[ONE:][ONE]
	CLOSE_BRACE = ZERO_DICT_STR[ONE:][ONE:][ONE:][ONE:][ONE]

	C_STR = `c`
	D_STR = `d`

	FORMAT_STR_C = ''.join([OPEN_BRACE, ZERO_STR, COLON, C_STR, CLOSE_BRACE])
	FORMAT_STR_D = ''.join([OPEN_BRACE, ZERO_STR, COLON, D_STR, CLOSE_BRACE])

	LENGTH_C_STR = c and FORMAT_STR_C.format(ONE_STR) or EMPTY
	LENGTH_D_STR = d and FORMAT_STR_D.format(ONE_STR) or EMPTY

	TOTAL_STR = EMPTY.join([LENGTH_C_STR, LENGTH_D_STR, ZERO_STR])
	RESULT = TOTAL_STR.find(ZERO_STR)

	return RESULT

ลองออนไลน์!

แนวคิดหลักคือว่ารูปแบบสตริง'{0:5}'.format('1')แผ่นจำนวนศูนย์ความยาวของชอบ5 '1 'โดยการต่อสายสองตัวเข้าด้วยกันโดยใช้''.joinผลรวมของความยาวคือผลรวมของตัวเลขอินพุต จากนั้นเราก็ไปต่อ0จะทำการต่อท้ายและโทร.find()ไปยังตำแหน่งสุดท้ายซึ่งก็คือผลรวม

สตริง'{0:5}'เป็นรูปแบบที่ผลิตโดยแยก{:}ตัวอักษรจาก reprs dictสตริงของพจนานุกรมที่สร้างขึ้นด้วย สตริงที่พิมพ์ซ้ำของการสรุปแต่ละครั้งจะถูกวางไว้โดยที่ 5 จะเป็น ฉันต้องการใช้ dict เช่น{0:5}ตัวของมันเอง แต่การพิมพ์ของมันรวมถึงพื้นที่ที่ทำให้มันยุ่งเหยิง

อินพุต 0 ทำให้กระบวนการยุ่งเหยิงเนื่องจากสตริงย่อยมีความยาวขั้นต่ำ 1 เรามีผู้ที่มีand/orสตริงที่จะให้สตริงว่างในกรณีนี้


1
นี่ค่อนข้างแตกต่างจากที่ฉันตั้งใจไว้ฉันชอบที่จะดูคำอธิบาย
ตัวช่วยสร้างข้าวสาลี

คุณสามารถตีกอล์ฟทั้งหมดของคุณint([]in[])เพียงแค่int()ตามที่ทั้งสองจะออก 0.
หมึกมูลค่า


5

x86 แอสเซมบลีโหมดจริง 16 บิตโดย Joshua

    int  0x3                  ; <---  this is the "robber" portion

    ; -- begin code to print numbers in real-mode asm using ROM BIOS video interrupts --
    add  dx, cx               ; add input values together
    mov  ax, dx               ; move result into AX
    push WORD 0xB800
    pop  ds                   ; DS == starting address of text-mode video buffer
    xor  cx, cx               ; digit counter
    xor  di, di               ; position counter
    mov  bx, 0xA              ; divisor

    test ax, ax               ; is number negative?
    jns  .GetDigits
    neg  ax                   ; convert negative number to positive
    mov  WORD ds:[di], 0x4F2D ; output leading negative sign, in white-on-red
    add  di, 2                ; increment position counter

.GetDigits:
    xor  dx, dx
    div  bx                   ; divide DX:AX by 10 (AX == quotient, DX == remainder)
    push dx                   ; push digit onto stack
    inc  cx                   ; increment digit counter
    test ax, ax
    jnz  .GetDigits           ; keep looping until we've got 'em all

.PrintDigits:
    pop  dx                   ; get digit off of stack
    dec  cx                   ; decrement digit counter
    mov  dh, 0x4F             ; high byte: color attribute (white-on-red)
    add  dl, 0x30             ; low  byte: convert to ASCII
    mov  WORD ds:[di], dx     ; output digit
    add  di, 2                ; increment position counter
    test cx, cx
    jnz  .PrintDigits         ; keep looping until we've printed 'em all

    cli
    hlt

screenshot of Debug dump of code, along with output in upper-left corner

คำอธิบาย:

"การแตก" ที่แนะนำโดยรหัสของ Joshua คือการตั้งค่าธงกับดัก (TF) ซึ่งทำให้ซีพียูเข้าสู่โหมดขั้นตอนเดียว ซึ่งหมายความว่าจะมีการดำเนินการคำสั่งเดียวในแต่ละครั้งก่อนที่ CPU จะหยุด (กับดัก) ที่มีการขัดจังหวะประเภท 1 นี่คือสิ่งที่อนุญาตให้ผู้ใช้ debuggers ใช้โค้ดแบบก้าวเดียวซึ่งค่อนข้างมีประโยชน์ แต่เป็น PITA จริงหากคุณต้องการรันโค้ดนอกบริบทของตัวดีบัก!

เป็นส่วนของรหัสต่อไปนี้ที่เปิดแฟล็ก Trap:

pushf               ; push the FLAGS register onto the top of the stack
mov bp, sp          ; load the pointer to the top of the stack into BP
or word [bp], 256   ; bitwise-OR the WORD at the top of the stack (the copy of FLAGS)
                    ;  with 0x100, which turns on bit 8 (TF)
popf                ; pop the modified flags back off the stack into FLAGS

การติดตั้งแฟล็กแทร็บหมายถึงการที่เราได้รับโอกาสในการดำเนินการหนึ่งคำสั่งก่อนที่จะติดกับดักซีพียู - ซึ่งเป็นสิ่งที่มาทันทีหลังจากที่POPFนี่ ดังนั้นเราต้องนับสิ่งนี้

เคล็ดลับคือINT 3คำสั่งซึ่งจะเรียกใช้หมายเลขขัดจังหวะ 3 มีสองสาเหตุที่ทำให้การ "ถอดรหัส" รหัส:

  1. ค่าสถานะแทร็บถูกล้างในตัวจัดการขัดจังหวะ นี่เป็นเพียงส่วนหนึ่งของการออกแบบของ Intel แต่มันถูกออกแบบมาเพื่อเหตุผลด้านสติปัญญาพื้นฐาน โปรดจำไว้ว่าการติดตั้งแฟล็กกับดักคืออินเทอร์รัปต์ชนิดที่ 1 ถูกเรียกใช้หลังจากการดำเนินการของแต่ละคำสั่งดังนั้นหาก TF ไม่ได้ถูกเคลียร์ตัวมันเองINT 1จะเรียกการขัดจังหวะ - มันจะถูกขัดจังหวะตลอดทาง นอกจากนี้การขัดจังหวะ TF ที่ชัดเจนช่วยให้ทำการดีบักรหัสได้ง่ายขึ้นเช่นเดียวกับ IDE ที่ทำหน้าที่เรียกฟังก์ชั่นห้องสมุดโดยอัตโนมัติ

  2. CALLการทำงานวิธีการขัดจังหวะเป็นหลักเช่นเดียวกับไกล พวกเขาเรียกใช้ตัวจัดการขัดจังหวะที่มีการจัดเก็บที่อยู่ที่ตำแหน่งที่สอดคล้องกันในตารางเวกเตอร์ขัดจังหวะส่วนกลาง เนื่องจากตารางนี้เริ่มต้นที่ที่อยู่0x0000:0000และถูกจัดเก็บในsegment:offsetรูปแบบ4 ไบต์การคำนวณที่อยู่นั้นง่ายเหมือนการคูณ 4 ด้วยเวกเตอร์ / หมายเลขขัดจังหวะ ในกรณีนี้เราเรียกใช้อินเทอร์รัปต์ 3 ดังนั้นจะเท่ากับ 4 × 3 = 12

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

    mov  di, 12
    mov  [di], si
    mov  [di + 2], bp
    

    ซึ่งชุด0x0000:000C(ตัวจัดการขัดจังหวะสำหรับINT 3) BP:SIเพื่อ ซึ่งหมายความว่าเมื่อใดก็ตามที่INT 3มีการเรียกใช้มันจะผลักดันการลงทะเบียน FLAGS ไปยังสแต็กตามด้วยที่อยู่ผู้ส่งและจากนั้นก็แยกไปBP:SIที่ซึ่งช่วยให้เราสามารถเริ่มต้นการเรียกใช้รหัสอีกครั้งในบริบทที่

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

โจชัวอนุญาตให้โจรระบุกลไก I / O ใด ๆ ที่เขาต้องการดังนั้นฉันจึงใช้วิธีการแบบง่าย ๆ โดยสมมติว่าค่าผ่านไปแล้วDXและการCXลงทะเบียน นั่นคือเหตุผลเนื่องจากสิ่งเหล่านี้ไม่ได้อุดตันที่ใดก็ได้โดยรหัส "อารัมภบท" ของเขา

จากนั้นเอาต์พุตจะถูกทำโดยเก็บ ASCII ไบต์ลงในหน่วยความจำวิดีโอโดยตรง บัฟเฟอร์วิดีโอเริ่มต้นที่0xB800:0000โหมดข้อความ CGA, EGA และ / หรือ VGA ดังนั้นเราจึงเริ่มพิมพ์ที่นั่น รูปแบบคือ: อักขระในไบต์ต่ำและแอตทริบิวต์สีในไบต์สูง นั่นหมายความว่าอักขระแต่ละตัวอยู่ในออฟเซ็ต 2 ไบต์ เราแค่วนซ้ำแต่ละหลักในจำนวน (ฐาน -10), แปลงเป็น ASCII และพิมพ์ทีละหน้าจอ ใช่นี่เป็นรหัสจำนวนมาก ไม่มีฟังก์ชั่นห้องสมุดที่จะช่วยเราในภาษาแอสเซมบลี สิ่งนี้สามารถปรับให้เหมาะสมต่อไปได้ แต่ฉันเบื่อที่จะทำงานกับมัน ...

หลังจากแสดงผลลัพธ์แล้วโค้ดจะได้รับอนุญาตให้ทำงานผิดพลาดหรือทำสิ่งใดดังนั้นเราจึงล้างการขัดจังหวะและหยุด CPU


ฉันงงงวย; ฉันไม่สามารถทราบได้ว่านี่จะผ่านคำสั่ง hlt ที่ BP: SP + 1 ได้อย่างไร
โจชัว

@Joshua อืมนั่นเป็นจุดที่ดี ฉันไม่ได้คิดอย่างนั้น เมื่อก้าวผ่านโค้ดใน Debug ฉันจะดำเนินการINT 3และจบลงทันทีที่คำแนะนำที่ตามมาดังนั้นฉันจึงไปกับมัน อาจจะมีบางอย่างเกี่ยวกับสภาพแวดล้อมการทดสอบของฉัน? CLIจะปิดใช้งานการขัดจังหวะฮาร์ดแวร์เท่านั้น แต่แม้ว่าจะผ่านพ้นไปHLTแล้วคุณจะคิดว่ามันจะล้มเหลวและรันโค้ดในlทันทีหลังจากนั้น
Cody Gray

Oh, you were single stepping. Yeah that would do it. I'm going to double check but I think I uploaded whacked code.
Joshua

I also tested without single-stepping. No difference. This is on FreeDOS latest in VM Virtualbox. I have real hardware available, but didn't feel like powering it up. @Joshua
Cody Gray

Well you clearly cracked it then. Maybe you found a way to raise that NMI.
Joshua


4

Python 3, ppperry's 2nd Challenge

Wow, this was fun! I enjoyed solving this.

Edit: OK, I fixed it. It seems like the classes were at a different index in the subclass list on TIO than on my computer, so I made it work for both, and added a TIO.

import sys
for mod in sys.modules.values():mod.__dict__.clear()
1+1

# My code begins here
str = "Hello!".__class__
int = (37).__class__
object = str.__base__

def find_subclass(superclass, name):
	for cls in superclass.__subclasses__():
		if cls.__name__ == name:
			return cls

_io_IOBase      = find_subclass(object, '_IOBase')        # <class '_io._IOBase'>
_io_RawIOBase   = find_subclass(_io_IOBase, '_RawIOBase') # <class '_io._RawIOBase'>
_ioFileIO       = find_subclass(_io_RawIOBase, 'FileIO')  # <class '_io.FileIO'>
stdout = _ioFileIO('stdout', mode='w', opener=lambda name,flags: 1) # FD for stdout is 1
stdin  = _ioFileIO('stdin',  mode='r', opener=lambda name,flags: 0) # FD for stdin is 0
nums = str(stdin.read(), encoding='utf-8').split()
stdout.write(str(int(nums[0]) + int(nums[1])).encode('utf-8') + b'\n')
stdout.flush()

Try it online!


I get an error. sys.excepthook is missing?
Rɪᴋᴇʀ

Hmm... works for me. What's the real error you're getting? (That's happening because ppperry's code destroyed pretty much everything, including knowing how to show exceptions, so that's the sys.excepthook, but there'll be a real cause listed somewhere in there.)
zbw

Nevermind, the real error is IndexError('list index out of range',). It's on the line with the definition of _io_RawIOBase.
Rɪᴋᴇʀ

The problem is that the order of the subclasses isn't fixed. _io_IOBase = [cls for cls in object.__subclasses__() if cls.__name__ == '_IOBase'][0] should work everywhere.
Dennis

@Dennis Yep, I realized that and just fixed it. It works on TIO now!
zbw

4

Haskell by zbw

{-#OPTIONS_GHC -fth -w#-}
module M where

import Language.Haskell.TH.Syntax
import System.IO.Unsafe

a = $( runIO $ TupE[] <$
              do x <- readLn :: IO Integer
                 y <- readLn
                 print $ x + y )

Can't run code at run-time? Run it at compile time!

This was a lot of fun, I did not know template haskell before this challenge.



3

Python 2 by Wheat Wizard

import sys
c="".join(open(__file__).read().split('\n')[4:])
if set(c)-set(' &)(,.:[]a`cdfijmonrt~')or"import"in c:sys.setrecursionlimit(1)
sys.modules['sys'],sys.modules['os']=None,None;del sys;f=lambda\
a,b:a+b
__import__('sysconfig').__dict__['os'].__dict__['sys'].setrecursionlimit(1000)
print(f(1,2))

Try it online!


This is turning out to be more difficult than I thought.
Wheat Wizard

3

Java by LordFarquaad

Blocking the access to the objects at the source level was really smart (and annoying when testing), well done!

public class java {
  public static void main(String[] s) {
    //there is no executable code in snippet one.
    //your code here.
    try {
      ClassLoader cl = ClassLoader.getSystemClassLoader();
      Object in = cl.loadClass("java.lang.System").getDeclaredField("in").get(null);
      Object out = cl.loadClass("java.lang.System").getDeclaredField("out").get(null);
      Object scanner = cl.loadClass("java.util.Scanner").getConstructor(cl.loadClass("java.io.InputStream")).newInstance(in);
      int i = (Integer)cl.loadClass("java.util.Scanner").getMethod("nextInt").invoke(scanner);
      int j = (Integer)cl.loadClass("java.util.Scanner").getMethod("nextInt").invoke(scanner);
      cl.loadClass("java.io.PrintStream").getMethod("println", Object.class).invoke(out, i+j);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  class Class {}
  class Method {}
  class System {}
  class FileDescriptor {}
  class Logger {}
  class Runtime {}
  class Scanner {}
}

Nice! What if ClassLoader had been shadowed?
Jakob

1
@JakobCornell "".getClass().getClassLoader(). Shadowing is usually only a problem you have to think about once and then it's ok. You could even shadow Object, I'd still be able to solve this. Ok, you might force me into the 1kb solution, but it's possible.
Olivier Grégoire


3

Inform 7, by Ilmari Karonen

Blantant abuse of ambiguous nouns ... My code begins with factory is a room. The previous line is the cop's code. Type add 1 and 1 to get 2, for example.

For reading a command: Rule fails

factory is a room.
The adder one is a thing. The adder two is a thing. The adder one is in factory. The adder two is in factory.
Before reading a command: change the text of the player's command to "examine adder"

For printing a parser error: 
    if the player's command includes "add [number] ":
        let N be the number understood;
        if the player's command includes "and [number]":
            say the number understood plus N;

2

Java, Roman Gräf

public class Main {
    public static void main(String... args){
        System.setOut(null);
        System.setErr(null);

        System.setOut(new java.io.PrintStream(new java.io.FileOutputStream(java.io.FileDescriptor.out)));
        System.setErr(new java.io.PrintStream(new java.io.FileOutputStream(java.io.FileDescriptor.err)));
        System.out.println("This");
        System.err.println("works");
    }
}

Sets stdout and stderr back to their initial values.

I believe I am able to use the fully qualified name instead of an import, if I am wrong please correct me (this is my first post here.) This could probably be done using reflection as well.

Edit: here's a reflective solution using only java.lang.reflect.*:

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public class Test {
    public static void main(String... args) {
        System.setOut(null);
        System.setErr(null);

        try {
            Class<?> psClass = Class.forName("java.io.PrintStream");
            Class<?> fsClass = Class.forName("java.io.FileOutputStream");
            Class<?> osClass = Class.forName("java.io.OutputStream");
            Class<?> fdClass = Class.forName("java.io.FileDescriptor");
            Class<System> sClass = System.class;
            Constructor psCtor = psClass.getConstructor(osClass);
            Constructor fsCtor = fsClass.getConstructor(fdClass);

            Field modifiersField = Field.class.getDeclaredField("modifiers");
            modifiersField.setAccessible(true);

            Object sout = psCtor.newInstance(fsCtor.newInstance(fdClass.getDeclaredField("out").get(null)));
            Field outField = sClass.getDeclaredField("out");
            modifiersField.setInt(outField, outField.getModifiers() & ~Modifier.FINAL);
            outField.set(null, sout);

            Object serr = psCtor.newInstance(fsCtor.newInstance(fdClass.getDeclaredField("err").get(null)));
            Field errField = sClass.getDeclaredField("err");
            modifiersField.setInt(errField, outField.getModifiers() & ~Modifier.FINAL);
            errField.set(null, serr);

            System.out.println("This");
            System.err.println("works");
        } catch (Exception ignore) {
        }
    }
}

Yep, stdin, stdout and stderr are stored elsewhere! You don't even need to use setOut and setErr as you can simply use the PrintStream directly.
Olivier Grégoire

Added reflective solution as well as I feel this was what was initially expected
Moira

2

JavaScript by Daniel Franklin

location="data:text/html;base64,PHNjcmlwdD5jb25zb2xlLmxvZygxKnByb21wdCgpKzEqcHJvbXB0KCkpPC9zY3JpcHQ+"

This might be considered a slightly cheaty solution, but it does work for me on Chromium 59 / Linux, even if I do also receive a warning saying:

Upcoming versions will block content-initiated top frame navigations to data: URLs. For more information, see https://­goo.gl/BaZAea.

Ps. Here's another crack, this time without warnings:

Node.prototype.removeChild=function(){}
document.body.innerHTML='<iframe src="data:text/html;base64,PHNjcmlwdD5jb25zb2xlLmxvZygxKnByb21wdCgpKzEqcHJvbXB0KCkpPC9zY3JpcHQ+"/>'

I think prompt()- -prompt() saves two bytes
Marie

2

Java 8 by Olivier Grégoire

A hugely verbose crack for a hugely verbose challenge. :) The pain of working indirectly with classes that you cannot name is palpable.

    try {
      Class loader = Class.class.getMethod("getClassLoader").getReturnType();
      Object sysLoader = loader.getMethod("getSystemClassLoader").invoke(null);
      Class integer = (Class) loader.getMethod("loadClass", String.class).invoke(sysLoader, "java.lang.Integer");
      Class system  = (Class) loader.getMethod("loadClass", String.class).invoke(sysLoader, "java.lang.System");
      Class filein  = (Class) loader.getMethod("loadClass", String.class).invoke(sysLoader, "java.io.FileInputStream");

      InputStream cmd = (InputStream) filein.getConstructor(String.class).newInstance("/proc/self/cmdline");
      byte[] buf = new byte[65536];
      int len = cmd.read(buf);
      String[] args = new String(buf, 0, len).split("\0");
      
      int a = (int) integer.getMethod("parseInt", String.class).invoke(null, args[args.length-2]);
      int b = (int) integer.getMethod("parseInt", String.class).invoke(null, args[args.length-1]);

      Object out = system.getField("out").get(null);
      out.getClass().getMethod("println", String.class).invoke(out, ""+(a+b));
    } catch (Exception e) {
      throw new Error(e);
    }
  }
}
class ClassLoader {
  public static ClassLoader getSystemClassLoader() { return new ClassLoader(); }
  public ClassLoader loadClass(String s) { return this; }
  public ClassLoader getDeclaredField(String s) { return this; }
  public ClassLoader getMethod(String s) { return this; }
  public ClassLoader getMethod(String s, Class c) { return this; }
  public InputStream get (Object o) { return new FakeInputStream(); }
  public void invoke(Object o, SecurityManager sm) {}
}
class FakeInputStream extends InputStream {
  public int read() {
    return -1;

Try it online!

Ps. Here's my earlier attempt, written before Olivier clarified that input was meant to be taken via command line arguments. Unlike the crack above, this one isn't Linux-specific.

    try {
      Class loader = Class.class.getMethod("getClassLoader").getReturnType();
      Object sysLoader = loader.getMethod("getSystemClassLoader").invoke(null);
      Class integer = (Class) loader.getMethod("loadClass", String.class).invoke(sysLoader, "java.lang.Integer");
      Class system  = (Class) loader.getMethod("loadClass", String.class).invoke(sysLoader, "java.lang.System");
      Class scanner = (Class) loader.getMethod("loadClass", String.class).invoke(sysLoader, "java.util.Scanner");

      InputStream in = (InputStream) system.getField("in").get(null);
      Object scanIn = scanner.getConstructor(InputStream.class).newInstance(in);

      int a = (int) scanner.getMethod("nextInt").invoke(scanIn);
      int b = (int) scanner.getMethod("nextInt").invoke(scanIn);

      Object out = system.getField("out").get(null);
      out.getClass().getMethod("println", String.class).invoke(out, ""+(a+b));
    } catch (Exception e) {
      throw new Error(e);
    }
  }
}
class ClassLoader {
  public static ClassLoader getSystemClassLoader() { return new ClassLoader(); }
  public ClassLoader loadClass(String s) { return this; }
  public ClassLoader getDeclaredField(String s) { return this; }
  public ClassLoader getMethod(String s) { return this; }
  public ClassLoader getMethod(String s, Class c) { return this; }
  public InputStream get (Object o) { return new FakeInputStream(); }
  public void invoke(Object o, SecurityManager sm) {}
}
class FakeInputStream extends InputStream {
  public int read() {
    return -1;

Try it online!


If you're up for it, here's my new challenge.
Olivier Grégoire

Just for the sake of writing it here: since I have not the right to say "Gotcha! It works only on one system", this answer doesn't entirely crack the challenge because it works only on Linux.
Olivier Grégoire

@OlivierGrégoire: FWIW, I did come up with an alternative solution using String[] args = ((String) system.getMethod("getProperty", String.class).invoke(null, "sun.java.command")).split(" "); that isn't Linux-specific, but does use what appears to be an undocumented property set by some JVMs.
Ilmari Karonen

That's still not portable. It won't work on IBM Java, for instance. However, it's a nice idea! :)
Olivier Grégoire

2

C# (.NET Core) by raznagul

I assume this wasn't the intended solution.

int a;
int b;

using (var f = new System.IO.FileStream("/dev/stdin", System.IO.FileMode.Open, System.IO.FileAccess.Read))
{
using (var fs = new System.IO.StreamReader(f))
{
a = int.Parse(fs.ReadLine());
b = int.Parse(fs.ReadLine());
}
}
using (var f = new System.IO.FileStream("/dev/stdout", System.IO.FileMode.Open, System.IO.FileAccess.Write))
{
using (var fs = new System.IO.StreamWriter(f))
{
fs.WriteLine((a + b).ToString());
}
}

Nice trick with /dev/std* there. I initially aimed for a similar approach, but couldn't find any easy way to open streams for stdin/out without access to System.Console, so I opted for reflection instead. Of course, your solution presumably only works on Linux and other Unixish systems with the appropriate /dev entries, but raznagul didn't explicitly say it had to work on Windows. And it does work on TIO.
Ilmari Karonen

@IlmariKaronen: Indeed; and my plan for if it were Windows would have failed on TIO.
Joshua

1

Java, by racer290

This was rather a basic overlook that static initializers are called before the main method. It was a nice try: I was dismayed by the throw new Error() at first, but found the way in the end ;)

public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, NoSuchMethodException {

    try {

        System.class.getField("in").set(null, null);
        System.class.getField("out").set(null, null);
        System.class.getField("err").set(null, null);

        System.class.getMethod("getSecurityManager", new Class[0]).setAccessible(false);

        File.class.getField("fs").set(null, null);

        for (Method m : Class.class.getMethods()) {

            m.setAccessible(false);

        }

        SecurityManager mngr = new SecurityManager() {

            @Override
            public void checkPermission(Permission p) {

                throw new Error("Muahaha!");

            }

            @Override
            public void checkLink(String s) {

                throw new Error("Not this way, my friend!");

            }

        };

        System.setSecurityManager(mngr);

    } catch (Throwable t) {

    }
    // My code here, I guess...
} static {
  java.util.Scanner s = new java.util.Scanner(System.in);
  System.out.println(s.nextInt()+s.nextInt());

    // End of my code
}

System.out.println("Hello World!"); Doesn't add two integers?.. "2. A snippet of code that takes two numbers as input, adds them together, and outputs their sum. This snippet must still correctly function even after running the first snippet. When the two snippets are combined together, they must form a full program that adds two numbers, or define a function that adds two numbers. This snippet will probably rely upon obscure behavior, and be hard to find."
Kevin Cruijssen

@KevinCruijssen What can I say? If the cops don't do their job, why should I do theirs? :P
Olivier Grégoire

1
@KevinCruijssen There, I put an addition in there.
Olivier Grégoire

@OlivierGrégoire the whole point is to prevent adding numbers, whether by removing the capability to input, to add, or to output.
Stephen

@StepHen Yep, I understood it a bit more afterwards. Check my 3 other cracks to see that I finally understood that ;)
Olivier Grégoire

1

Java by Kevin Cruijssen

Well constructed. A lot of code to make anyone properly ponder how to solve this challenge. I guess the "put your code afterwards" was a big, big hint.

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileDescriptor;
import java.io.FilePermission;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public class Main {

  // Put everything in a static block so it is run before the static main method 
  // and any trailing (static) initializer-blocks:
  static {
    try {
      initializing();
    } catch (final Exception e) {
    }
  }

  static void initializing() throws Exception {
    // Overwrite System.out, System.err and System.in:
    System.setOut(new PrintStream(new ByteArrayOutputStream()));
    System.setErr(new PrintStream(new ByteArrayOutputStream()));
    System.setIn(new ByteArrayInputStream(new byte[0]));

    // Enable reflection for System.out, System.err and System.in:
    final Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    final Class<?> fdClass = java.io.FileDescriptor.class;
    final Field outField = fdClass.getDeclaredField("out");
    outField.setAccessible(true);
    modifiersField.setInt(outField, outField.getModifiers() & ~Modifier.FINAL);
    final Field errField = fdClass.getDeclaredField("err");
    errField.setAccessible(true);
    modifiersField.setInt(errField, errField.getModifiers() & ~Modifier.FINAL);
    final Field inField = fdClass.getDeclaredField("in");
    inField.setAccessible(true);
    modifiersField.setInt(inField, inField.getModifiers() & ~Modifier.FINAL);

    // Replace existing System.out FileDescriptor with a new (useless) one:
    outField.set(null, new FileDescriptor());
    // Replace existing System.err FileDescriptor with a new (useless) one:
    errField.set(null, new FileDescriptor());
    // Replace existing System.in FileDescriptor with a new (useless) one:
    inField.set(null, new FileDescriptor());

    // Disable reflection for System.out, System.err, System.in again:
    modifiersField.setInt(outField, outField.getModifiers() & ~Modifier.FINAL);
    modifiersField.setInt(errField, errField.getModifiers() & ~Modifier.FINAL);
    modifiersField.setInt(inField, inField.getModifiers() & ~Modifier.FINAL);
    inField.setAccessible(false);
    errField.setAccessible(false);
    outField.setAccessible(false);
    modifiersField.setAccessible(false);

    // Overwrite the SecurityManager:
    System.setSecurityManager(new SecurityManager() {

      private boolean exitAllowed = false;

      @Override
      public void checkExec(final String cmd) {
        throw new SecurityException();
      }

      @Override
      public void checkPermission(final java.security.Permission perm) {
        final String name = perm.getName();
        // You're not allowed to read/write files:
        if (name.equals("setIO") || name.equals("writeFileDescriptor")
            || name.equals("readFileDescriptor")
            || ((perm instanceof FilePermission) && name.startsWith("/proc/self/fd/"))) {
          throw new SecurityException();
        }
        // You're not allowed to overwrite the Security settings:
        if (name.equals("setSecurityManager") || name.equals("suppressAccessChecks")) {
          throw new SecurityException();
        }
        // You're not allowed to use reflection anymore:
        if (name.equals("getModifiers") || name.equals("get") || name.equals("set")
            || name.equals("setBoolean") || name.equals("setByte")
            || name.equals("setChar") || name.equals("setShort") || name.equals("setInt")
            || name.equals("setLong") || name.equals("setFloat") || name.equals("setDouble")
            || name.equals("setFieldAccessor") || name.equals("setFieldAccessor")) {
          throw new SecurityException();
        }
        // When you try to leave the current VM it will stop the program:
        if (name.startsWith("exitVM") && !this.exitAllowed) {
          this.exitAllowed = true;
          System.exit(0);
        }

        // You know what, nothing is allowed!
        throw new SecurityException("Mhuahahahaha!");
      }
    });
  }

  public static void main(String[] args) {
    // Overwritting all given arguments:
    args = new String[0];

    // Exit the program before you can do anything!
    System.exit(0);
  }
}

class System {
  static void exit(int n) {}
  static void setSecurityManager(SecurityManager sm) {
    java.util.Scanner scanner =new java.util.Scanner(java.lang.System.in);
    java.lang.System.out.println(scanner.nextInt() + scanner.nextInt());
  }
  static void setIn(Object o) {}
  static void setOut(Object o) {}
  static void setErr(Object o) {}
}

Try it here.


That was fast.. That was indeed my exact intended solution! Well done. :) EDIT: Took the liberty to add the TIO link if you don't mind.
Kevin Cruijssen

Well, I was actually working on that idea with racer 290's challenge when you posted yours. And, no I don't mind.
Olivier Grégoire


1

cQuents, Step Hen, 3 bytes

+BC

Try it online!

Took a lot of talking to Step Hen to figure out how the hell his weird language works, but in short:

His code was #|1,1:A. #|1,1 is the default input, meaning any input given to the program is appended by 2 1's. (IE if you pass a 47 and a 53, your input is [47, 53, 1, 1].

: simply sets the mode, which will output the nth item in the sequence if n is set, and otherwise output the entire sequence.

Finally A gets the first input.

Because we have 4 inputs [47, 53, 1, 1], adding BC to the end would also fetch the 2nd and 3rd input, and the 4th input implicitly becomes n.

Because our sequence is ABC, it's parsed algebraically, meaning it becomes A*B*C. We don't want that, but if we insert a + between A and B, it becomes A+B*C, where A and B are our inputs, and C is 1.


how the hell his weird language works maybe once I finish it it might make some more sense
Stephen

@StepHen don't get me wrong it's a neat language, but weird as hell
Skidsdev

1

C# (.NET Core) by raznagul

var console = typeof(System.ConsoleCancelEventArgs).Assembly.GetType("System.Console");
var readLine = console.GetMethod("ReadLine");
var writeLine = console.GetMethod("WriteLine", new Type[] { typeof(int) });
int a = Int32.Parse((string) readLine.Invoke(null, null));
int b = Int32.Parse((string) readLine.Invoke(null, null));
writeLine.Invoke(null, new object[] {a+b});

Try it online!

This would probably have taken less time if I actually knew any C#. However, with some browsing of the documentation and a bit of help from Jon Skeet, I managed to cobble together something that works.


1

Vim challenge by @DJMcMayhem

It's been a while since I wasn't able to exit vim, here's my solution (note it's far more than 23 bytes - so it's probably not the intended solution):

i
echo "
12
39
"|awk '{s'$(python -c "print(''.join([chr(43),chr(61)]))")'$1} END {print s}'<Esc>vgg!bash

Try it online!

The idea is simply to pipe the two integers to awk via bash, since = and + were disabled I had to use a small work-around. The awk line expands to:

"|awk '{s'+='} END {print s}

Edit: The original intention was that the input is already in the buffer, but that wouldn't be more difficult - the main difficulty was to get addition working.

Here's the suggested fix by @DJMcMayhem: Try it online!


I think don't think you can do [insert your number here] in insert mode. Instead, it's just already in the buffer. But you could get around that with Oecho "<esc>Go"|awk..., so I think this counts. Nicely done! This isn't the crack I had in mind (I was hoping for a pure vim answer) so I'll probably post a new answer that patches external commands and !.
DJMcMayhem

1
Here's an example that takes input the correct way: Try it online!
DJMcMayhem

Yeah, I wasn't sure about the input. But the workaround would indeed be easy. I'll edit in the official way.
ბიმო

BTW, my patched approach is up here: codegolf.stackexchange.com/a/133441/31716
DJMcMayhem

1

Java 7 by Poke

  }
  public static void main(java.lang.String[]a) throws Exception {
    int x = Integer.parseInt(a[0]);
    int y = Integer.parseInt(a[1]);
    java.lang.System.out.println(x+y);
  }
}
class String {
}
class System {
  public static java.io.InputStream in = new java.io.ByteArrayInputStream(new byte[0]), out = in, err = in;
  public static void setProperties (Object o) {

Try it online!

No Linux-specific tricks needed, just simple masking of the unqualified String and System class names. This is probably not the intended solution, but it works.



1

RProgN2 by @ATaco

"+-/*÷^"{²[[\=};
{"D"=11{‹1D&¬\D›]"D"=}:]1\2\Š1{[\D‹|"D"=};D¬{1"D"=1\2\Š1{[D‹"D"=};}{[}?D}"~"={"d"="g"=g~d&gd~&|}"±"={"H"="I"=11{‹H1&I1&±\H›"H"=I›"I"=H¬¬I¬¬|}:1\2\Š1{[H‹|"H"=};H}"×"={"J"="K"=1{JK&‹JK×"K"=]"J"=}:JK|}"+"=

Try it online!

This is by far not the best answer I could've given, but it allows adding numbers together again. Had I actually went through and did proper stack handling, I could probably golf this quite a bit, but as of now I'm happy with the answer.

In ATaco's original post he effectively just reassigned all of the main arithmetic operators to destroy their inputs. To fix this problem I redefined what addition was in terms of its binary operations, which was a pain because RProgN2 doesn't have a binary negation operator or xor.

Note: If you want to test the input, numbers with more than one digit need to be in the form "XX..." n to be converted into an actual number since RProgN2 takes each character as is unless it's a concept or string. Edit: @ATaco noted that adding a '$' before a multidigit number will do the same thing.

EDIT: Here is the logic for my solution. As you can see, most definitely not the most refined code, but it works.

{"D"=11{‹1D&¬\D›]"D"=}:]1\2\Š1{[\D‹|"D"=};D¬{1"D"=1\2\Š1{[D‹"D"=};}{[}?D}"~"= # Defines the ~ operator which negates a number
{"D"=                                                                   }     # Remove the top of the stack and assign D with the popped value
     11                                                                       # Push 2 1's to the stack.  The first is used as a counter, the second if the initial truthy value for the loop
       {             }:                                                       # Start a while loop if the top of the stack (popped) is truthy (removes final falsey value)
        ‹                                                                     # Left shift the counter variable
         1D&¬                                                                 # Push negation of last bit of D
             \                                                                # Swap the counter (index 1) and the negated bit (index 0)
              D›]"D"=                                                         # Push D, right shift it, duplicate the value on the stack, then pop and assign the top to D
                       ]1\                                                    # Duplicate the counter, push 1, and swap the counter to the top of the stack
                          2\Š                                                 # Push 2, swap with the counter, then take the log (log_2(counter))
                             1{         };                                    # Run the for loop "for (i=1;i<=log_2(counter);i+=1)"
                               [\                                             # Pop off i, then swap the original counter with the next bit to append
                                 D‹|"D"=                                      # Left shift D, or it with the next bit, then assign D the new value
                                          D¬                                  # Need to check if D was 0 or not (in the case of 0b11...1~)
                                            {                     }{ }?       # Conditional on the truthiness of not D
                                             1"D"=                            # If D was 0, we assign it as 1, then start to bit shift it up
                                                  1\2\Š1{       };            # Same for loop as earlier since the original counter is still on the top of the stack
                                                         [D‹"D"=              # Pop off i, left shift D, then reassign it
                                                                    [         # Else D was non-zero, so just pop off the counter we've been carrying around
                                                                       D      # Push the final value to the top of the stack as a return
                                                                         "~"= # Assign the function between the {}'s to the character '~'

{"d"="g"=g~d&gd~&|}"±"=                                                       # Defines the ± operator which performs a single bit xor
{"d"="g"=         }                                                           # Assign d and g the first and second values on the stack respectively
         g~d&                                                                 # Push ~g&d to the top of the stack
             gd~&                                                             # Push g&~d to the top of the stack
                 |                                                            # Or the top 2 values giving us (~g&d)|(g&~d)
                   "±"=                                                       # Assign this function to the ± operator

{"H"="I"=11{‹H1&I1&±\H›"H"=I›"I"=H¬¬I¬¬|}:1\2\Š1{[H‹|"H"=};H}"×"=             # Defines the × operator which performs a full number xor
{"H"="I"=                                                   }                 # Store the top 2 stack values in H and I (in that order)
         11{                            }:                                    # Another while loop with the first one being a counter for later, and the second is our truthy value to start the loop
            ‹H1&I1&±                                                          # Left shift the counter, then push the bit xor of H's and I's lowest bit ((H&1)±(I&1) in infix notation)
                    \                                                         # Swap the calculated bit and the counter
                     H›"H"=I›"I"=                                             # Right shift both variables and store the values back in them
                                 H¬¬I¬¬|                                      # Effectively pushing the value (H!=0 | I != 0)
                                          1\2\Š1{        };                   # Same for loop as the ones above
                                                 [H‹|"H"=                     # Pop off the for loop counter, left shift H, or it with the next bit, and reassign
                                                           H                  # Push the final computed xor value to the top of the stack
                                                             "×"=             # Assign this whole function to the × operator

{"J"="K"=1{JK&‹JK×"K"=]"J"=}:JK|}"+"=                                         # Finally, a function redefining addition as the "+" operator
{"J"="K"=                       }                                             # Store the top 2 stack values in J and K respectively
         1{                }:                                                 # An initial truthy value to start the while loop and the loop itself
           JK&‹                                                               # Push (J&K)<<1 to the stack
               JK×                                                            # Compute the full xor of J and K (J^K in Python)
                  "K"=                                                        # Assign K the value of J xor K
                      ]"J"=                                                   # Duplicate (J&K)<<1 and assign 1 copy to J, leaving (J&K)<<1 as our while check (while ((J&K)<<1))
                             JK|                                              # Finally push the value J|K to the stack to get the addition
                                 "+"=                                         # Assign this function to the "+" operator, restoring it

Providing a $ before a sting of numbers also groups it as one number, e.g. 56$46$12 will push the numbers 5, 6, 46 and 12. I'll post my actual solution and such tommorow
ATaco

Didn't know that. I sort of just looked through your callables to figure out what things were.
Arnold Palmer

I might actually write some documentation because of this challenge.
ATaco

That'd be wonderful. I managed to find a list of commands for RProgN, but lost it... And it only helped so much since the functions are all different. I had to learn your functions via your old RProgN tutorial page and your callable classes. It was fun to play around with even if it wasn't immediately obvious how everything worked.
Arnold Palmer

1

JavaScript (Node.js) by jrich, 298 bytes

I feel like this isn't the intended solution, but if it is, well done, I spent a while trying to figure out how to get the name of the declared function! :)

var p=process,f;(_=>{var w=p.stdout.write,n='f'+(Math.random()*1e7|0),l=1
f=p.stdout.write=a=>eval(`(function ${n}(a){while(l&&((typeof a)[0]!='s'||'f'+a!=n));a=l?l="":a;w.apply(p.stdout,arguments);})`)(a)})();
process.stderr.write.call(process.stdout,''+((0|process.argv[2])+(0|process.argv[3])));

Try it online!


1
Not the intended solution but very clever! Nice crack +1
jrich

@jrich Yeah, I figured, feel free to patch that out I'll be sure to have another go at the intended solution!
Dom Hastings

whoops... too late! I was satisfied with your solution's creativity though!
jrich
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.