Spraw, by twój język * był w większości * bezużyteczny (wątek rabusia)

31

Zainspirowany przez tym komentarzem ...

Dziękujemy użytkownikom Step Hen , Wheat-Wizard i Dennis za pomoc w ugruntowaniu specyfikacji tego wyzwania przed jego opublikowaniem!

To jest wątek Rabusia! Przejdź do wątku gliniarzy tutaj


W tym wyzwaniu masz za zadanie uruchomić kod, który sprawia, że ​​Twój język nie spełnia już naszych kryteriów bycia językiem programowania. W tym wyzwaniu oznacza to, że język nie może już ...

  • Weź numeryczne dane wejściowe i wyjściowe

  • Dodaj dwie liczby razem

  • Sprawdź, czy określona liczba jest liczbą pierwszą, czy nie.

Jest to wyzwanie dla , w którym istnieją dwa różne wyzwania o dwóch różnych celach: gliniarze spróbują napisać kod, który sprawi, że język będzie w większości bezużyteczny, oraz złodzieje spróbują znaleźć ukryte obejście, które pozwala glinom odzyskać swój język.

Policjanci napiszą dwa fragmenty kodu:

  1. Taki, który sprawia, że ​​ich język jest w większości bezużyteczny, np. Poprzez usunięcie wbudowanych funkcji do pobierania danych wejściowych / wyjściowych i operacji numerycznych. Ten kod nie może ulec awarii ani wyjść. Powinno być możliwe dodanie kodu na końcu tego fragmentu, a ten kod zostanie poddany ocenie . I

  2. Fragment kodu, który przyjmuje dwie liczby jako dane wejściowe, dodaje je do siebie i generuje ich sumę. Ten fragment kodu musi nadal poprawnie działać, nawet po uruchomieniu pierwszego fragmentu kodu. Gdy oba fragmenty zostaną połączone razem, muszą one utworzyć pełny program, który dodaje dwie liczby lub zdefiniować funkcję, która dodaje dwie liczby. Ten fragment kodu prawdopodobnie będzie polegał na niejasnym zachowaniu i będzie trudny do znalezienia.

Gliniarze również wybiorą dowolne standardową metodę wprowadzania i wyprowadzania . Muszą jednak ujawnić dokładnie, jakiego formatu (wejścia i wyjścia) używają. Aby złamać ich odpowiedź, musisz postępować zgodnie z tym samym formatem wejścia / wyjścia, w przeciwnym razie twój crack się nie liczy.

Odpowiedź gliniarzy zawsze ujawni

  • pierwszy fragment (oczywiście nie sekundę).

  • Język (w tym niewielka wersja, ponieważ większość zgłoszeń prawdopodobnie będzie polegać na dziwnych przypadkowych przypadkach)

  • Format IO, w tym czy jest to funkcja czy pełny program. Rabusie muszą używać tego samego formatu, aby być poprawnym crackem.

  • Wszelkie dziwne przypadki brzegowe wymagane do odpowiedzi. Na przykład działa tylko na systemie Linux lub wymaga połączenia z Internetem .

Jako złodziej musisz spojrzeć na jedno z oświadczeń gliniarzy i spróbować je złamać. Możesz go złamać, pisząc dowolny prawidłowy fragment, który mógłby działać jako fragment 2 (dodanie dwóch liczb razem po tym, jak język stanie się w większości bezużyteczny). To nie musi być ten sam fragment, który pierwotnie napisał policjant. Gdy masz pękniętą odpowiedź, opublikuj kod jako odpowiedź w tym wątku i opublikuj link do swojej odpowiedzi jako komentarz do odpowiedzi policjanta. Następnie ten post zostanie edytowany, aby wskazać, że został złamany.

Oto przykład. W przypadku pierwszego fragmentu możesz zobaczyć następujący program w języku Python 3 jako odpowiedź gliniarzy:

Python 3

print=None

Pobiera dane wejściowe ze STDIN i dane wyjściowe do STDOUT

Prawidłowy drugi fragment może być

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

Jest to ważne, ponieważ weźmie dwie liczby jako dane wejściowe i wyświetli ich sumę, nawet jeśli połączysz oba fragmenty razem, np.

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

To jest poprawny crack do ich odpowiedzi.

Jeśli odpowiedź gliniarza pozostaje nieprzetarta przez cały tydzień, może edytować w drugim fragmencie i wskazywać, że jego odpowiedź jest teraz bezpieczna . Po edycji jest bezpieczny, nie możesz już próbować go złamać. Jeśli nie będą go edytować jako bezpieczne, możesz próbować go złamać, dopóki nie zrobią tego.

Zwycięzcą wątku złodzieja jest użytkownik, który złamał najwięcej odpowiedzi, a rozstrzygnięciem był czas, w którym osiągnął N pęknięć. (więc jeśli dwóch różnych użytkowników ma na przykład 5 pęknięć, zwycięzcą jest użytkownik, który jako pierwszy opublikował 5. pęknięcie). Po upływie wystarczającego czasu zaakceptuję odpowiedź zwycięzcy największą liczbą głosów.

Baw się dobrze!

Wyjaśnienia zasad

  • Pierwszy fragment kodu musi działać poprawnie bez żadnych danych wejściowych . Może generować cokolwiek zechcesz, a to wyjście zostanie zignorowane. Tak długo, jak po wykonaniu fragmentu, drugi fragment działa poprawnie.

  • Drugi fragment musi zostać faktycznie wykonany, aby odpowiedź była poprawna. Oznacza to odpowiedź typu

    import sys
    sys.exit()
    

    nie jest poprawny, ponieważ nie łamie języka. Po prostu odchodzi.

  • Po zapewnieniu bezpieczeństwa twój wynik jest liczbą bajtów obu fragmentów .

  • Wróćmy do Proszę ujawnić wszelkie dziwne przypadki brzegowe wymagane do odpowiedzi na twoje pytanie ... Twoje zgłoszenie musi zawierać wystarczającą ilość informacji, zanim zostanie ujawnione, aby było odtwarzalne po ujawnieniu. Oznacza to, że jeśli Twoja odpowiedź stanie się bezpieczna, a następnie edytujesz: Oto moja odpowiedź. O tak, BTW to działa tylko wtedy, gdy uruchamiasz go na Solarisie, żarty na ciebie! Twoja odpowiedź jest nieprawidłowa i zostanie usunięta i nie zostanie uznana za kwalifikującą się do wygranej.

  • Drugi fragment kodu może ulec awarii po wygenerowaniu sumy. Tak długo, jak dane wyjściowe są nadal poprawne (na przykład, jeśli zdecydujesz się na wyjście do STDERR, a następnie otrzymasz kilka informacji o awarii, jest to nieprawidłowe)

Tabela liderów

Oto lista każdego użytkownika z co najmniej jednym pęknięciem, uporządkowana według wyniku, a następnie nazwy (alfabetycznie). Jeśli zgłosisz crack, zaktualizuj odpowiednio swój wynik.

#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
DJMcMayhem
źródło

Odpowiedzi:

3

Java 8 autorstwa Oliviera Grégoire'a

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

Wypróbuj online!

Ponieważ Olivier wyraźnie zezwalał na przekazywanie danych wejściowych za pomocą właściwości ustawianych za pomocą argumentów VM, określę, że dane wejściowe powinny być podawane w argumencie VM -Dline.separator=X,Y, gdzie Xi Ysą liczbami, które należy dodać. To znaczy, aby np. Dodać liczby 17 i 25, program powinien zostać wywołany jako:

java -Dline.separator=17,25 Main

Wierzę, że to powinno działać na każdym systemie, niż można uruchomić programy Java w wierszu poleceń. Nawet w systemach, które nie mają wiersza polecenia, można użyć dowolnego równoważnego mechanizmu ustawiania właściwości systemowych w celu przekazania danych wejściowych do maszyny wirtualnej.


Ps. Oto moja wcześniejsza próba włamania, która została uznana za nieważną ze względu na użycie funkcji specyficznych dla 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);
  }
}

Wypróbuj online!

Okazało się to o wiele mniej gadatliwe niż poprzednie . Trudność polegała na znalezieniu podklasy, SecurityManagerktóra nie istniała w przestrzeni nazw zaczynającej się od „java. ”. Podejrzewam, że nadal nie jest to zamierzone rozwiązanie, ale działa. *

*) Przynajmniej w TIO; sun.awt.AWTSecurityManagerklasy i sun.java.commandwłaściwość nie wydają się być oficjalnie udokumentowane, i może nie być dostępna we wszystkich JVMs.

Ilmari Karonen
źródło
Dobra robota! Próbowałem tego, ale nie mogłem znaleźć takiego, który byłby SecurityManagerw zasięgu ... Możesz również czytać System.inw tym momencie, ponieważ nie jest jeszcze zamknięty.
zbw
Niestety, jest to zależne od platformy odpowiedź na dwóch obszarach: zarówno sun.awt.SecurityManageri "sun.awt.command"są zależne od platformy i nie są częścią Java .
Olivier Grégoire,
Tak, pęknięty! :) Zamierzonym rozwiązaniem było przejście System.getProperties().get("blah")(ponieważ tylko zablokowałem dostęp , ale System.getPropertynie System.getProperties), ale to wystarczy! Dobra robota!
Olivier Grégoire,
22

C (GCC / Linux) autorstwa Syzyfa

Ten fragment kodu zamyka podaną funkcję i uruchamia nową (klasyczny wstrzyknięcie kodu), która sama się redefiniuje, closetak że zamiast zamykać fd, uruchamia pożądany kod.

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

  exit(0);
2012 rcampion
źródło
20

Python, rozwiązanie Wheat Wizard tutaj

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()))

To znaczy, możesz po prostu cofnąć limit rekurencji i nic złego się nie dzieje ...

Działa na TIO

Uwaga

To jest moje pierwsze zgłoszenie CnR, więc jeśli to złamie jakiekolwiek zasady, powiedz mi, a ja to usunę.

HyperNeutrino
źródło
4
Jestem głupi, że tego przegapiłem
Wheat Wizard
@WheatWizard :)
HyperNeutrino
@wheatwizard Nie ujawniaj jeszcze swojego zamierzonego rozwiązania. Chciałbym Looove zobaczyć lepszego policjanta z oryginalnego rozwiązania które rozwiązuje ten problem.
DJMcMayhem
@Djmcmayhem Prawdopodobnie zamierzam repost z del sys.
Wheat Wizard,
@WheatWizard Pamiętaj os.sys, jeśli to robi różnicę: 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)

Nadal mam numery dosłownym i znaki (używam 0, '0'i '-'), a [a..]i [a..b]które są bardzo przydatne. I mam jedno -, ale mógłbym się obejść.

I ponownie ++do wdrożenia r( reverse) i określić t, a tsktóre sątail i tails. x a bzwraca nelement th b, gdzie njest długością aminus jeden. xzwykle można zdefiniować jako snd.last.zip. Funkcja dpobiera listę i zwraca listę z elementami z pozycji, które są wielokrotnościami dziesięciu. l!!szwraca nelement th l, gdzie sjest odwróconą reprezentacją ciągu n. +zwraca jako liczbę całkowitą sumę dwóch liczb naturalnych podanych jako ciągi odwrócone, podobnie -dla różnicy. addzwraca jako liczbę całkowitą sumę dwóch możliwie ujemnych liczb całkowitych podanych jako łańcuchy.

Zastanawiam się, czy jest to trochę podobne do tego, co Ben miał na myśli.

Christian Sievers
źródło
Tak, prawie te same pomysły. Dopasowywanie wzorców względem literałów, aby uzyskać testy równości i rozgałęzienia, wypisz składnię wyliczeń, aby uzyskać formę przyrostu. Byłem dość zaskoczony, gdy stwierdziłem, że :jest w zasięgu, nawet NoImplicitPreludebez importowania czegokolwiek.
Ben
7

C (gcc) Conora O'Briena


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));
}

Wypróbuj online!

Dennis
źródło
ugggg Zapomniałem zakazać fscanf i wielu innych funkcji>.> dobra robota
Conor O'Brien
7

Python 2 by Wheat Wizard (czwarta iteracja)

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[]))`)

Wypróbuj online!

Bez exploitów, tylko funkcja do dodania przy użyciu tylko znaków ' &)(,.:[]a`cdfijmonrt~', zgodnie z przeznaczeniem (właściwie tylko'(),.:[]`acdfijmnort' ).

Nie starałem się streścić; Właśnie napisałem podwyrażenia dla wartości pośrednich, takich jak 0, i pusty ciąg i te zastąpione ciągiem.

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

Wypróbuj online!

Podstawową ideą jest to, że format ciągu '{0:5}'.format('1')dopełnia liczbę od zera do długości 5podobnej '1 '. Przez połączenie dwóch takich ciągów ''.join, suma ich długości jest sumą liczb wejściowych. Następnie zajmujemy się 0końcem i sprawdzamy.find() do końcowej pozycji, która jest sumą.

Łańcuch '{0:5}'do sformatowania jest wytwarzany przez wyodrębnienie {:}znaków z powtórzeń ciągów słowników utworzonych za pomocądict . Ciąg repr dla każdego kolejnego summanda jest umieszczany tam, gdzie byłoby 5. Chciałem użyć takiego słownika {0:5}, ale jego repr zawiera przestrzeń, która go zawiodła.

Dane wejściowe 0 zaburzają proces, ponieważ łańcuch podrzędny ma minimalną długość 1. Mamy and/orw tym przypadku znaki z, aby dać pusty łańcuch w tym przypadku.

xnor
źródło
1
To jest zupełnie inne, niż zamierzałem, chciałbym zobaczyć wyjaśnienie.
Wheat Wizard
Można golf wszystkie swoje int([]in[])po prostu int()zarówno jako wyjście woli 0.
Value Ink
5

16-bitowy montaż w trybie rzeczywistym x86, autor: 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

Wyjaśnienie:

„Złamaniem” wprowadzonym przez kod Joshua jest ustawienie flagi pułapki (TF), która przełącza procesor w tryb jednostopniowy. Oznacza to, że tylko jedna instrukcja będzie wykonywana jednocześnie, zanim CPU zatrzyma się (pułapki) z przerwaniem typu 1. To pozwala debugerom na implementację jednego kroku kodu - jest to bardzo przydatne, ale prawdziwa PITA, jeśli chcesz uruchomić kod poza kontekstem debugera!

To jest następująca sekcja kodu, która włącza flagę pułapki:

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

Wdrożenie flagi pułapki oznacza, że ​​mamy szansę wykonać dokładnie jedną instrukcję przed pułapkami procesora - to jest ta, która pojawia się natychmiast po POPF . Więc musimy sprawić, żeby to się liczyło.

Sztuką jest INT 3instrukcja, która wywołuje przerwanie numer 3. Istnieją dwa powody, dla których działa to w celu „odblokowania” kodu:

  1. Flaga pułapki jest usuwana w modułach obsługi przerwań. To tylko część projektu Intela, ale prawdopodobnie zostało to zrobione z podstawowych powodów rozsądku. Pamiętaj, że realizacja flagą pułapek jest, że typ-1 przerwanie jest wywoływane po wykonaniu każdej instrukcji, więc jeśli TF nie zostało wyczyszczone, INT 1by sama wywołać przerwanie-byłoby przerwania przez całą drogę w dół. Ponadto przerywanie czyszczenia TF ułatwia debugowanie kodu, podobnie jak IDE, które automatycznie zastępuje wywołania funkcji bibliotecznych.

  2. Sposób, w jaki zakłócenia działają, jest zasadniczo taki sam jak daleko CALL. Wywołują procedurę obsługi przerwań, której adres jest przechowywany w odpowiedniej pozycji w globalnej tabeli wektorów przerwań. Ponieważ ta tabela zaczyna się pod adresem0x0000:0000 i jest przechowywana w formacie 4-bajtowym segment:offset, obliczenie adresu jest tak proste, jak pomnożenie 4 przez wektor / liczbę przerwań. W tym przypadku wywołujemy przerwanie 3, więc byłoby to 4 × 3 = 12.

    … A zauważysz, że Joshua starannie to dla nas przygotował. Przed włączeniem flagi pułapki ma następujący kod:

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

    która ustawia 0x0000:000C(moduł obsługi przerwań INT 3) na BP:SI. Oznacza to, że przy każdym INT 3wywołaniu wypycha rejestr FLAGS na stos, a następnie adres zwrotny, a następnie rozgałęzia się do BP:SI, co pozwala nam ponownie uruchomić wykonywanie kodu, w kontekście, w którym flaga pułapki jest wyłączona.

Potem wszystko jest z górki INT 3. Wszystko, co musimy zrobić, to dodać dwie liczby razem i wydrukować wynik. Tyle że nie jest to tak proste w języku asemblerowym, jak w innych językach, więc tutaj spędzana jest większość kodu.

Joshua jest umożliwienie złodzieja określić dowolny mechanizm I / O (S) chce , więc biorę uproszczone podejście od zakładając, że wartości są przekazywane w DXiCX rejestrów . Jest to rozsądne, ponieważ ich kod „prologu” nie jest nigdzie zablokowany.

Dane wyjściowe są następnie wykonywane przez zapisywanie bajtów ASCII bezpośrednio w pamięci wideo. Bufor wideo zaczyna się 0xB800:0000od CGA, EGA i / lub VGA w trybie tekstowym, więc zaczynamy tam drukować. Format to: znak w niskim bajcie i atrybut koloru w wysokim bajcie. Oznacza to, że każdy znak ma przesunięcie 2-bajtowe. Po prostu iterujemy każdą z cyfr w liczbie (podstawa-10), konwertując je na ASCII i drukując je pojedynczo na ekranie. Tak, to dużo kodu. Brak funkcji bibliotecznych, które pomogłyby nam w asemblerze. Prawie na pewno można to dalej zoptymalizować, ale mam już dość pracy nad tym ...

Po wyświetleniu danych wyjściowych kod może ulec awarii lub zrobić cokolwiek innego, więc po prostu usuwamy przerwania i zatrzymujemy procesor.

Cody Gray
źródło
Jestem zdziwiony; Nie mogę zrozumieć, jak to się dzieje po instrukcji hlt w BP: SP + 1.
Joshua
@Joshua Hmm, to dobra uwaga. Nawet o tym nie myślałem. Przechodząc przez kod w Debugowaniu, uruchamiam INT 3i natychmiast kończę na instrukcji po nim, więc po prostu poszedłem z nim. Może ma to coś wspólnego z moim środowiskiem testowym? CLIwyłączałby tylko przerwania sprzętowe, ale nawet gdyby się to udało HLT, pomyślałbyś, że wpadnie i lnatychmiast wykona kod .
Cody Gray
Och, byłeś jednym krokiem. Tak, to by wystarczyło. Zamierzam sprawdzić dwukrotnie, ale chyba przesłałem pobity kod.
Joshua
Testowałem również bez jednego kroku. Bez różnicy. Jest to najnowsze na FreeDOS w VM Virtualbox. Mam prawdziwy sprzęt, ale nie miałem ochoty go zasilać. @Joshua
Cody Gray
Cóż, wtedy wyraźnie to złamałeś. Może znalazłeś sposób na podniesienie tego NMI.
Joshua
4

Pyton 3 , ppperry „S 2. wyzwanie

Wow, było fajnie! Lubię to rozwiązywać.

Edycja: OK, naprawiłem to. Wygląda na to, że klasy znajdowały się pod innym indeksem na liście podklas w TIO niż na moim komputerze, więc sprawiłem, że działa dla obu i dodałem 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()

Wypróbuj online!

zbw
źródło
Dostaję błąd. sys.excepthook is missing?
Rɪᴋᴇʀ
Hmm ... działa dla mnie. Jaki masz prawdziwy błąd? (Dzieje się tak, ponieważ kod ppperry zniszczył prawie wszystko, w tym umiejętność pokazywania wyjątków, więc to jest sys.excepthook, ale gdzieś tam będzie prawdziwa przyczyna.)
zbw
Nieważne, prawdziwy błąd to IndexError('list index out of range',). Jest zgodny z definicją _io_RawIOBase.
Rɪᴋᴇʀ
Problem polega na tym, że kolejność podklas nie jest ustalona. _io_IOBase = [cls for cls in object.__subclasses__() if cls.__name__ == '_IOBase'][0]powinien działać wszędzie.
Dennis
@Dennis Tak, zdałem sobie z tego sprawę i właśnie to naprawiłem. Teraz działa na TIO!
zbw
4

Haskell przez 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 )

Nie można uruchomić kodu w czasie wykonywania? Uruchom go w czasie kompilacji!

To była świetna zabawa, przed tym wyzwaniem nie wiedziałem, że szablon haskell.

Gajówka
źródło
3

Galaretka hiperinino


+

Super proste. Nowa linia powoduje, że pierwszy link nie jest wywoływany.

Wypróbuj online!

DJMcMayhem
źródło
Można również stosować się do nowego wiersza reguły nie jak to
Jonathan Allanowi
Tak, myślałem, że to będzie zbyt łatwe.
HyperNeutrino,
3

Python 2 autorstwa 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))

Wypróbuj online!

Syzyf
źródło
To okazuje się trudniejsze niż myślałem.
Wheat Wizard,
3

Java autorstwa LordFarquaad

Blokowanie dostępu do obiektów na poziomie źródła było naprawdę sprytne (i denerwujące podczas testowania), dobrze zrobione!

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 {}
}
Olivier Grégoire
źródło
Miły! Co by ClassLoaderbyło, gdyby ktoś został zacieniony?
Jakob
1
@JakobCornell "".getClass().getClassLoader(). Zacienianie jest zwykle tylko problemem, o którym musisz pomyśleć raz, a potem jest w porządku. Możesz nawet ocieniać Object, wciąż będę w stanie to rozwiązać. Ok, możesz zmusić mnie do rozwiązania 1kb, ale jest to możliwe.
Olivier Grégoire,
3

Poinformuj 7, Ilmari Karonen

Rażące nadużycie niejednoznacznych rzeczowników ... Mój kod zaczyna się od factory is a room. Poprzedni wiersz to kod policjanta. Wpisz add 1 and 1na przykład 2.

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;
pppery
źródło
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");
    }
}

Zestawy stdoutistderr powrót do ich wartości początkowych.

Wierzę, że jestem w stanie użyć w pełni kwalifikowanej nazwy zamiast importu, jeśli się mylę, popraw mnie (to mój pierwszy post tutaj). Prawdopodobnie można to zrobić również za pomocą refleksji.

Edycja: oto rozwiązanie odblaskowe wykorzystujące tylko 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) {
        }
    }
}
Moira
źródło
Tak, stdin, stdouti stderrsą przechowywane w innym miejscu! Nawet nie trzeba korzystać setOuti setErrjak można po prostu użyć PrintStreambezpośrednio.
Olivier Grégoire,
Dodałem odblaskowe rozwiązanie i myślę, że tego początkowo oczekiwano
Moira
2

JavaScript autorstwa Daniela Franklina

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

To może być uważane za nieco podstępne rozwiązanie, ale działa dla mnie na Chromium 59 / Linux, nawet jeśli otrzymam również ostrzeżenie:

Nadchodzące wersje będą blokować inicjowane przez zawartość nawigacje w górnej ramce do danych: adresów URL. Aby uzyskać więcej informacji, zobacz https://goo.gl/BaZAea .

Ps. Oto kolejny trzask, tym razem bez ostrzeżeń:

Node.prototype.removeChild=function(){}
document.body.innerHTML='<iframe src="data:text/html;base64,PHNjcmlwdD5jb25zb2xlLmxvZygxKnByb21wdCgpKzEqcHJvbXB0KCkpPC9zY3JpcHQ+"/>'
Ilmari Karonen
źródło
Myślę, że prompt()- -prompt()oszczędza dwa bajty
Marie
2

Java 8 autorstwa Oliviera Grégoire'a

Ogromnie verbose crack dla ogromnie verbose wyzwanie. :) Ból związany z pracą pośrednią z klasami, których nie można nazwać, jest wyczuwalny.

    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;

Wypróbuj online!

Ps. Oto moja wcześniejsza próba, napisana zanim Olivier wyjaśnił, że dane wejściowe miały być podejmowane za pomocą argumentów wiersza poleceń. W przeciwieństwie do powyższego crack, ten nie jest specyficzny dla Linuksa.

    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;

Wypróbuj online!

Ilmari Karonen
źródło
Jeśli masz ochotę, oto moje nowe wyzwanie .
Olivier Grégoire,
Żeby napisać to tutaj: ponieważ nie mam prawa mówić „Gotcha! Działa tylko na jednym systemie”, ta odpowiedź nie do końca łamie wyzwanie, ponieważ działa tylko na Linuksie.
Olivier Grégoire,
@ OlivierGrégoire: FWIW, wpadłem na alternatywne rozwiązanie, String[] args = ((String) system.getMethod("getProperty", String.class).invoke(null, "sun.java.command")).split(" ");które nie jest specyficzne dla Linuksa, ale wykorzystuje coś, co wydaje się być nieudokumentowaną właściwością ustawioną przez niektóre maszyny JVM.
Ilmari Karonen,
To wciąż nie jest przenośne. Na przykład nie będzie działać na IBM Java. To jednak fajny pomysł! :)
Olivier Grégoire,
2

C # (.NET Core) przez raznagul

Zakładam, że to nie było zamierzone rozwiązanie.

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());
}
}
Jozuego
źródło
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
}
Olivier Grégoire
źródło
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.

Olivier Grégoire
źródło
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

JavaScript by Grant Davis

document.body.innerHTML='<iframe/>'
w=frames[0]
w.console.log(1*w.prompt()+1*w.prompt())

Works in the JS console on the about:blank page (as specified in the cop post) on Chromium 59 / Linux.

Ilmari Karonen
źródło
That didn't take long. Good Job.
Grant Davis
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.

Skidsdev
źródło
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.

Ilmari Karonen
źródło
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!

ბიმო
źródło
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.

Ilmari Karonen
źródło
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
Arnold Palmer
źródło
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!

Dom Hastings
źródło
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