Haga que su idioma * sea * mayormente * inutilizable (hilo de ladrón)


31

Inspirado por este comentario ...

¡Gracias a los usuarios Step Hen , Wheat-Wizard y Dennis por ayudarme a solidificar la especificación de este desafío antes de publicarlo!

Este es el hilo del ladrón! Para el hilo de los policías, vaya aquí


En este desafío , tiene la tarea de ejecutar un código que haga que su lenguaje ya no satisfaga nuestros criterios de ser un lenguaje de programación. En ese desafío, eso significa hacer que el idioma ya no pueda ...

  • Tomar entrada y salida numérica

  • Suma dos números juntos

  • Prueba si cierto número es primo o no.

Esta es una desafío, donde hay dos retos diferentes con dos objetivos diferentes: Los policías se trate de escribir un código que hace que el lenguaje sobre todo inservible, y los ladrones tratarán de encontrar la solución oculto que permite a la policía para recuperar su lenguaje.

Los policías escribirán dos fragmentos de código:

  1. Uno que hace que su lenguaje sea prácticamente inutilizable, por ejemplo, eliminando las funciones integradas para tomar entradas / salidas y operaciones numéricas. Este código no puede bloquearse o salir. Debería ser posible agregar código al final de este fragmento, y ese código será evaluado . Y

  2. Un fragmento de código que toma dos números como entrada, los agrega y genera su suma. Este fragmento debe funcionar correctamente incluso después de ejecutar el primer fragmento. Cuando los dos fragmentos se combinan, deben formar un programa completo que agregue dos números o definir una función que agregue dos números. Este fragmento probablemente dependerá de un comportamiento oscuro y será difícil de encontrar.

Los policías también elegirán cualquier método estándar de entrada y salida . Sin embargo, deben revelar exactamente qué formato (entrada y salida) están utilizando. Para descifrar su respuesta, debe seguir el mismo formato de entrada / salida, o su crack no cuenta.

La respuesta de un policía siempre revelará

  • El primer fragmento (obviamente no el segundo).

  • Idioma (incluida la versión menor, ya que la mayoría de las presentaciones probablemente dependerán de casos extraños)

  • Formato IO, incluso si es una función o un programa completo. Los ladrones deben usar el mismo formato para ser un crack válido.

  • Cualquier caso marginal extraño requerido para que su respuesta funcione. Por ejemplo, solo se ejecuta en Linux , o requiere una conexión a Internet .

Como ladrón, debes mirar una de las presentaciones de la policía e intentar descifrarla. Puede descifrarlo escribiendo cualquier fragmento válido que pueda funcionar como fragmento 2 (sumando dos números juntos después de que el idioma quede prácticamente inutilizable). Este no tiene que ser el mismo fragmento que el policía escribió originalmente. Una vez que tenga una respuesta descifrada, publique su código como respuesta en este hilo y publique un enlace a su respuesta como un comentario en la respuesta del policía. Luego, esa publicación se editará para indicar que se ha descifrado.

Aquí hay un ejemplo. Para el primer fragmento, es posible que vea el siguiente programa de Python 3 como respuesta de la policía:

Python 3

print=None

Toma entrada de STDIN y salida a STDOUT

Un segundo fragmento válido podría ser

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

Esto es válido porque tomará dos números como entrada y generará su suma incluso si une los dos fragmentos, p. Ej.

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

Esta es una grieta válida para su respuesta.

Si la respuesta de un policía permanece sin descifrar durante una semana entera, puede editar en su segundo fragmento e indicar que su respuesta ahora es segura . Una vez que se edita para que sea seguro, ya no puede intentar descifrarlo. Si no lo editan como seguro, puede continuar intentando descifrarlo hasta que lo hagan.

El ganador del hilo del ladrón es el usuario que ha obtenido la mayor cantidad de respuestas, siendo el desempate el momento en que llegaron a N grietas. (por lo tanto, si dos usuarios diferentes tienen 5 grietas, por ejemplo, el usuario que publicó su quinta grieta primero es el ganador) Después de que haya pasado el tiempo suficiente, aceptaré la respuesta del ganador con la mayor cantidad de votos.

¡Que te diviertas!

Aclaraciones de reglas

  • El primer fragmento debe ejecutarse correctamente sin tomar ninguna entrada . Puede generar lo que desee, y esta salida será ignorada. Siempre que el fragmento esté hecho, el segundo fragmento se ejecutará correctamente.

  • El segundo fragmento debe ejecutarse para que su respuesta sea válida. Esto significa una respuesta como

    import sys
    sys.exit()
    

    no es válido porque no rompe el idioma. Simplemente se cierra.

  • Después de estar seguro, su puntaje es el recuento de bytes de ambos fragmentos .

  • Esto se remonta a Por favor, revele los casos extremos extraños necesarios para que su respuesta funcione ... Su envío debe contener suficiente información antes de ser revelado para ser reproducible después de ser revelado. Esto significa que si su respuesta se vuelve segura y luego edita en: Aquí está mi respuesta. Ah, por cierto, esto solo funciona si lo ejecutas en Solaris, ¡bromeas! su respuesta no es válida y se eliminará y no se considerará elegible para ganar.

  • Se permite que el segundo fragmento se bloquee después de generar la suma. Siempre que la salida sea correcta (por ejemplo, si elige enviar a STDERR, y luego obtiene un montón de información de bloqueo, esto no es válido)

Tabla de clasificación

Aquí hay una lista de cada usuario con al menos un crack, ordenado por puntaje y luego por nombre (alfabético). Si envía un crack, actualice su puntaje en consecuencia.

#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

Respuestas:


3

Java 8 por Olivier Grégoire

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

Pruébalo en línea!

Dado que Olivier permitió explícitamente pasar la entrada a través de las propiedades establecidas usando argumentos de VM, especificaré que la entrada se debe dar en el argumento de VM -Dline.separator=X,Y, donde Xy Yson los números que se agregarán. Es decir, para agregar, por ejemplo, los números 17 y 25, el programa debe invocarse como:

java -Dline.separator=17,25 Main

Creo que esto debería funcionar en cualquier sistema que pueda ejecutar programas Java en la línea de comandos. Incluso en sistemas que no tienen una línea de comando, cualquier otro mecanismo equivalente para configurar las propiedades del sistema podría usarse para pasar la entrada a la VM.


PD. Aquí está mi intento de craqueo anterior, que se consideró inválido debido al uso de funciones específicas de 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);
  }
}

Pruébalo en línea!

Esto resultó mucho menos detallado que el anterior . La parte difícil fue encontrar una subclase SecurityManagerque no viviera en un espacio de nombres que comenzara con " java.". Sospecho que todavía no es la solución prevista, pero funciona. *

*) En TIO, al menos; la sun.awt.AWTSecurityManagerclase y la sun.java.commandpropiedad no parecen estar documentadas oficialmente y es posible que no estén disponibles en todas las JVM.


¡Buen trabajo! Intenté esto, pero no pude encontrar uno SecurityManagerque estuviera dentro del alcance ... Sin embargo, también puedes leer System.inen este punto, porque aún no está cerrado.
zbw

Lo sentimos, esta es una respuesta dependiente de la plataforma en dos sentidos: tanto sun.awt.SecurityManagery "sun.awt.command"son dependientes de la plataforma y no son parte de Java .
Olivier Grégoire

Sí, agrietado! :) La solución prevista era pasar por System.getProperties().get("blah")(ya que solo bloqueé el acceso a System.getProperty, no System.getProperties), ¡pero esto es lo suficientemente bueno! ¡Bien hecho!
Olivier Grégoire

22

C (GCC / Linux) por Sisyphus

Este fragmento cierra la función proporcionada e inicia una nueva (inyección de código clásica), que se redefine a sí misma closepara que, en lugar de cerrar el fd, ejecute nuestro código deseado.

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

  exit(0);

20

Python, la solución de Wheat Wizard aquí

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

Quiero decir, puedes volver a establecer el límite de recursión y no pasa nada malo ...

Funciona en TIO

Nota

Esta es mi primera presentación de CnR, así que si esto rompe alguna regla, dígame y lo eliminaré.


44
Soy tonto por perderme esto
Wheat Wizard

@WheatWizard :)
HyperNeutrino

@wheatwizard No revele su solución prevista todavía. Me looove ver una mejor policía con su solución original que corrige este problema.
DJMcMayhem

@Djmcmayhem Probablemente voy a volver a publicar con un sistema.
Wheat Wizard

@WheatWizard Recuerde os.sys, si eso hace la diferencia: P
HyperNeutrino

15

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

Todavía tengo números literales y caracteres (uso 0, '0'y '-'), [a..]y [a..b]que son muy útiles. Y tengo unario -, pero podría prescindir.

Recreo ++para implementar r( reverse) y definir ty tscuáles son taily tails. x a bdevuelve el nelemento th de b, donde nes la longitud de amenos uno. xgeneralmente se podría definir como snd.last.zip. La función dtoma una lista y devuelve una lista con los elementos de esas posiciones que son múltiplos de diez. l!!sdevuelve el nelemento th de l, donde ses la representación de cadena invertida de n. +devuelve como entero la suma de dos números naturales dados como cadenas invertidas, del mismo modo -para la diferencia. adddevuelve como entero la suma de dos enteros posiblemente negativos dados como cadenas.

Me pregunto si esto es algo similar a lo que Ben tenía en mente.


Sí, más o menos las mismas ideas. La coincidencia de patrones con literales para obtener pruebas de igualdad y ramificación, enumerar la sintaxis de enumeración para obtener una forma de incremento. Me sorprendió bastante descubrir que :estaba dentro del alcance incluso con NoImplicitPreludey sin importar nada.
Ben

7

C (gcc) de 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));
}

Pruébalo en línea!


ugggg Olvidé prohibir fscanf y muchas de esas otras funciones>.> buen trabajo
Conor O'Brien

7

Python 2 por Wheat Wizard (cuarta iteración)

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

Pruébalo en línea!

Sin exploits, solo una función para agregar usando solo caracteres ' &)(,.:[]a`cdfijmonrt~', según lo previsto (en realidad solo '(),.:[]`acdfijmnort').

No hice ningún intento de hacerlo breve; Acabo de escribir subexpresiones para valores intermedios como 0 y la cadena vacía y sustituida por cadenas en esos.

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

Pruébalo en línea!

La idea central es que el formato de cadena '{0:5}'.format('1')agrega el número cero a una longitud 5similar '1 '. Mediante la concatenación de dos cadenas de este tipo ''.join, la suma de su longitud es la suma de los números de entrada. Luego, añadimos 0a al final y llamamos .find()a la posición final, que es la suma.

La cadena '{0:5}'para formatear se produce extrayendo los {:}caracteres de las cadenas de los diccionarios, creados con dict. La cadena repr de cada sumando sucesivo se coloca donde estarían los 5. Quería usar un dict como él {0:5}mismo, pero su repr incluye un espacio que lo estropeó.

Las entradas de 0 desordenan el proceso porque el subcadena tiene una longitud mínima de 1. En and/oreste caso, tenemos aquellos con un para dar la cadena vacía.


1
Esto es bastante diferente de lo que pretendía, me encantaría ver una explicación.
Wheat Wizard

Puedes jugar al golf int([]in[])de manera simple int()ya que ambos generarán 0.
Value Ink el


5

Ensamblaje x86 de 16 bits en modo real, por 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

captura de pantalla del volcado de depuración de código, junto con la salida en la esquina superior izquierda

Explicación:

La "ruptura" introducida por el código de Joshua es la configuración del indicador de trampa (TF), que pone la CPU en modo de un solo paso. Esto significa que solo se ejecutará una sola instrucción a la vez, antes de que la CPU se detenga (trampas) con una interrupción de tipo 1. Esto es lo que permite a los depuradores implementar un solo paso de código, bastante útil allí, ¡pero un verdadero PITA si desea ejecutar el código fuera del contexto de un depurador!

Es la siguiente sección de código que activa el indicador de trampa:

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

La implementación del indicador de trampa significa que tenemos la oportunidad de ejecutar exactamente una instrucción antes de las trampas de la CPU, que es la que viene inmediatamente después del POPFaquí. Entonces, necesitamos hacer que este cuente.

El truco es la INT 3instrucción, que invoca la interrupción número 3. Hay dos razones por las cuales esto funciona para "descifrar" el código:

  1. La bandera de la trampa se borra en los manejadores de interrupciones. Esto es solo parte del diseño de Intel, pero presumiblemente se hizo por razones básicas de cordura. Recuerde que la aplicación de la bandera trampa es que una interrupción de tipo 1 se invoca después de la ejecución de cada instrucción, por lo que si TF no se borra, INT 1lo haría en sí desencadenar una interrupción-sería interrupciones hasta el fondo. Además, tener interrupciones claras TF simplemente hace que sea más fácil depurar el código, al igual que un IDE que pasa automáticamente por las llamadas a las funciones de la biblioteca.

  2. La forma en que interrumpe el trabajo es esencialmente la misma que en un lugar lejano CALL. Invocan al controlador de interrupciones cuya dirección se almacena en la posición correspondiente en la tabla de vectores de interrupción global. Como esta tabla comienza en la dirección 0x0000:0000y se almacena en un segment:offsetformato de 4 bytes , calcular la dirección es tan simple como multiplicar 4 por el vector / número de interrupción. En este caso, invocamos la interrupción 3, por lo que sería 4 × 3 = 12.

    ... y notarás que Joshua pensativo preparó esto para nosotros. Antes de habilitar el indicador de trampa, tiene el siguiente código:

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

    que establece 0x0000:000C(el manejador de interrupciones para INT 3) en BP:SI. Eso significa que cada vez que INT 3se invoca, empuja el registro de BANDERAS a la pila, seguido de la dirección de retorno, y luego se bifurca BP:SI, lo que nos permite comenzar a ejecutar el código nuevamente, en un contexto en el que la bandera trampa está apagada.

Todo es cuesta abajo después INT 3. Todo lo que necesitamos hacer es sumar dos números e imprimir el resultado. Excepto que esto no es tan simple en lenguaje ensamblador como lo sería en otros idiomas, así que aquí es donde se gasta la mayor parte del código.

Joshua está permitiendo que el ladrón especifique cualquier mecanismo de E / S que desee , por lo que estoy adoptando el enfoque simplista de suponer que los valores se pasan en los registros DXy CX. Eso es razonable, ya que su código de "prólogo" no los cubre en ninguna parte.

La salida se realiza almacenando bytes ASCII directamente en la memoria de video. El búfer de video comienza en 0xB800:0000un modo de texto CGA, EGA y / o VGA, por lo que comenzamos a imprimir allí. El formato es: carácter en el byte bajo y atributo de color en el byte alto. Eso significa que cada carácter está en un desplazamiento de 2 bytes. Simplemente iteramos a través de cada uno de los dígitos en el número (base-10), convirtiéndolos a ASCII e imprimiéndolos uno a la vez en la pantalla. Sí, esto es mucho código. No hay funciones de biblioteca que nos ayuden en lenguaje ensamblador. Es casi seguro que esto puede optimizarse aún más, pero me cansé de trabajar en ello ...

Después de que se muestra la salida, se permite que el código se bloquee o haga lo que sea, por lo que simplemente eliminamos las interrupciones y detenemos la CPU.


Estoy confundido; No puedo entender cómo esto pasa la instrucción hlt en BP: SP + 1.
Joshua

@ Joshua Hmm, ese es un buen punto. Ni siquiera pensé en eso. Pasando por el código en Debug, ejecuto INT 3y termino de inmediato con las instrucciones que siguen, así que simplemente seguí con él. Tal vez tiene algo que ver con mi entorno de prueba? CLIsolo deshabilitaría las interrupciones de hardware, pero incluso si HLTpasara el , pensarías que no funcionaría y ejecutaría el código linmediatamente después.
Cody Gray

Oh, estabas solo dando un paso. Sí, eso lo haría Voy a verificar dos veces, pero creo que he subido el código descifrado.
Joshua

También probé sin un solo paso. Ninguna diferencia. Esto está en FreeDOS más reciente en VM Virtualbox. Tengo hardware real disponible, pero no tenía ganas de encenderlo. @Joshua
Cody Gray

Bueno, entonces claramente lo descifraste. Tal vez encontraste una manera de aumentar ese NMI.
Joshua


4

Python 3 , el segundo desafío de ppperry

Wow, esto fue divertido! Disfruté resolviendo esto.

Editar: OK, lo arreglé. Parece que las clases estaban en un índice diferente en la lista de subclases en TIO que en mi computadora, así que lo hice funcionar para ambos y agregué un 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()

Pruébalo en línea!


Me sale un error sys.excepthook is missing?
Rɪᴋᴇʀ

Hmm ... funciona para mi. ¿Cuál es el verdadero error que estás recibiendo? (Lo que está sucediendo porque el código de ppperry destruyó casi todo, incluyendo saber cómo mostrar excepciones, por lo que es el sys.excepthook, pero habrá una causa real que aparece en algún lugar allí.)
ZBW

No importa, el verdadero error es IndexError('list index out of range',). Está en la línea con la definición de _io_RawIOBase.
Rɪᴋᴇʀ

El problema es que el orden de las subclases no es fijo. _io_IOBase = [cls for cls in object.__subclasses__() if cls.__name__ == '_IOBase'][0]debería funcionar en todas partes.
Dennis

@ Dennis Sí, me di cuenta de eso y lo arreglé. ¡Funciona en TIO ahora!
zbw

4

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

¿No se puede ejecutar el código en tiempo de ejecución? ¡Ejecútalo en tiempo de compilación!

Esto fue muy divertido, no conocía la plantilla haskell antes de este desafío.



3

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

Pruébalo en línea!


Esto está resultando ser más difícil de lo que pensaba.
Wheat Wizard

3

Java por LordFarquaad

Bloquear el acceso a los objetos en el nivel de origen fue realmente inteligente (y molesto durante las pruebas), ¡bien hecho!

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 {}
}

¡Agradable! ¿Y si ClassLoaderhubiera sido sombreado?
Jakob

1
@JakobCornell "".getClass().getClassLoader(). El sombreado suele ser solo un problema en el que debe pensar una vez y luego está bien. Incluso podrías hacer sombra Object, todavía podría resolver esto. Ok, podrías forzarme a la solución de 1kb, pero es posible.
Olivier Grégoire


3

Inform 7, por Ilmari Karonen

Abuso flagrante de sustantivos ambiguos ... Mi código comienza con factory is a room. La línea anterior es el código del policía. Escriba add 1 and 1para obtener 2, por ejemplo.

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

Establece stdouty stderrvuelve a sus valores iniciales.

Creo que puedo usar el nombre completo en lugar de una importación, si me equivoco, corríjame (esta es mi primera publicación aquí). Probablemente esto también se pueda hacer usando la reflexión.

Editar: aquí hay una solución reflexiva que usa solo 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) {
        }
    }
}

Sí, stdin, stdouty stderrse almacenan en otro lugar! Ni siquiera necesita usarlo setOuty setErrsimplemente puede usarlo PrintStreamdirectamente.
Olivier Grégoire

Se agregó una solución reflectante, así como creo que esto era lo que se esperaba inicialmente
Moira

2

JavaScript de Daniel Franklin

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

Esto podría considerarse una solución ligeramente engañosa, pero funciona para mí en Chromium 59 / Linux, incluso si también recibo una advertencia que dice:

Las próximas versiones bloquearán las navegaciones de marco superior iniciadas por contenido a datos: URL. Para obtener más información, consulte https://goo.gl/BaZAea .

PD. Aquí hay otra grieta, esta vez sin advertencias:

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

Creo que prompt()- -prompt()ahorra dos bytes
Marie

2

Java 8 por Olivier Grégoire

Una grieta enormemente detallada para un desafío enormemente detallado. :) El dolor de trabajar indirectamente con clases que no puedes nombrar es 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;

Pruébalo en línea!

PD. Aquí está mi intento anterior, escrito antes de que Olivier aclarara que la entrada debía tomarse mediante argumentos de línea de comando. A diferencia del crack anterior, este no es específico de Linux.

    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;

Pruébalo en línea!


Si estás preparado, este es mi nuevo desafío .
Olivier Grégoire

Solo por el hecho de escribirlo aquí: como no tengo derecho a decir "¡Te tengo! Funciona solo en un sistema", esta respuesta no resuelve completamente el desafío porque solo funciona en Linux.
Olivier Grégoire

@ OlivierGrégoire: FWIW, se me ocurrió una solución alternativa String[] args = ((String) system.getMethod("getProperty", String.class).invoke(null, "sun.java.command")).split(" ");que no es específica de Linux, pero utiliza lo que parece ser una propiedad no documentada establecida por algunas JVM.
Ilmari Karonen

Eso todavía no es portátil. No funcionará en IBM Java, por ejemplo. Sin embargo, es una buena idea! :)
Olivier Grégoire

2

C # (.NET Core) por raznagul

Supongo que esta no era la solución prevista.

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

Buen truco con /dev/std*eso. Inicialmente apunté a un enfoque similar, pero no pude encontrar ninguna manera fácil de abrir transmisiones para stdin / out sin acceso a System.Console, por lo que opté por la reflexión. Por supuesto, su solución presumiblemente solo funciona en Linux y otros sistemas Unixish con las /deventradas apropiadas , pero raznagul no dijo explícitamente que tenía que funcionar en Windows. Y funciona en TIO.
Ilmari Karonen

@IlmariKaronen: De hecho; y mi plan para si fuera Windows habría fallado en TIO.
Joshua

1

Java, por racer290

Esto fue más bien un olvido básico que los staticinicializadores son llamados antes del mainmétodo. Fue un buen intento: throw new Error()al principio estaba consternado , pero al final encontré el camino;)

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!");¿No agrega dos enteros? .. " 2. Un fragmento de código que toma dos números como entrada, los suma y genera su suma. Este fragmento debe funcionar correctamente incluso después de ejecutar el primer fragmento. Cuando los dos fragmentos son combinados, deben formar un programa completo que agregue dos números, o definir una función que agregue dos números. Este fragmento probablemente dependerá de un comportamiento oscuro y será difícil de encontrar. "
Kevin Cruijssen

@KevinCruijssen ¿Qué puedo decir? Si los policías no hacen su trabajo, ¿por qué debería hacer el suyo? : P
Olivier Grégoire

1
@KevinCruijssen Allí, puse una adición allí.
Olivier Grégoire

@ OlivierGrégoire, el objetivo es evitar agregar números, ya sea eliminando la capacidad de ingresar, agregar o dar salida.
Stephen

@StepHen Sí, lo entendí un poco más después. Comprueba mis otras 3 grietas para ver que finalmente entendí eso;)
Olivier Grégoire

1

Java por Kevin Cruijssen

Bien construido Una gran cantidad de código para que cualquiera reflexione adecuadamente sobre cómo resolver este desafío. Supongo que "poner su código después" fue una gran, gran pista.

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

Pruébalo aquí.


Eso fue rápido ... ¡Esa fue mi solución exacta! Bien hecho. :) EDITAR: se tomó la libertad de agregar el enlace TIO si no le importa.
Kevin Cruijssen

Bueno, en realidad estaba trabajando en esa idea con el desafío del corredor 290 cuando publicaste el tuyo. Y no, no me importa.
Olivier Grégoire

1

JavaScript de Grant Davis

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

Funciona en la consola JS en la about:blankpágina (como se especifica en la publicación de la policía) en Chromium 59 / Linux.


Eso no tardó mucho. Buen trabajo.
Grant Davis

1

cQuents , Step Hen , 3 bytes

+BC

Pruébalo en línea!

Hablé mucho con Step Hen para descubrir cómo demonios funciona su lenguaje extraño, pero en resumen:

Su código fue #|1,1:A. #|1,1es la entrada predeterminada, lo que significa que cualquier entrada dada al programa se agrega con 2 1's. (IE si pasa un 47 y un 53, su entrada es [47, 53, 1, 1].

:simplemente establece el modo, que generará el nelemento th en la secuencia si nestá configurado, y de lo contrario generará la secuencia completa.

Finalmente Aobtiene la primera entrada.

Debido a que tenemos 4 entradas [47, 53, 1, 1], agregar BCal final también obtendría la 2da y 3ra entrada, y la 4ta entrada se convierte implícitamente n.

Debido a que nuestra secuencia es ABC, se analiza algebraicamente, lo que significa que se convierte en A*B*C. No queremos eso, pero si insertamos a +entre A y B, se convierte en A+B*C, donde Ay Bson nuestras entradas, y Ces 1.


how the hell his weird language workstal vez una vez que lo termine, podría tener más sentido
Stephen

@StepHen no me malinterpreten, es un lenguaje ordenado, pero extraño como el infierno
Skidsdev

1

C # (.NET Core) por 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});

Pruébalo en línea!

Probablemente esto hubiera tomado menos tiempo si realmente conociera C #. Sin embargo, con un poco de exploración de la documentación y un poco de ayuda de Jon Skeet , logré improvisar algo que funciona.


1

Vim Challenge por @DJMcMayhem

Ha pasado un tiempo desde que no pude salir de vim , aquí está mi solución (tenga en cuenta que es mucho más que 23bytes, por lo que probablemente no sea la solución deseada):

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

Pruébalo en línea!

La idea es simplemente tubo de los dos números enteros a awktravés bash, ya que =y +eran discapacitados tuve que usar un pequeño trabajo en torno. La awklínea se expande a:

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

Editar : La intención original era que la entrada ya está en el búfer, pero eso no sería más difícil: la principal dificultad era hacer que la suma funcionara.

Aquí está la solución sugerida por @DJMcMayhem: ¡ Pruébelo en línea!


Creo que no creo que puedas hacerlo [insert your number here]en modo de inserción. En cambio, ya está en el búfer. Pero podrías evitar eso Oecho "<esc>Go"|awk..., así que creo que esto cuenta. ¡Bien hecho! Este no es el crack que tenía en mente (esperaba una respuesta vim pura), así que probablemente publicaré una nueva respuesta que parchee comandos externos y !.
DJMcMayhem

1
Aquí hay un ejemplo que toma la entrada de la manera correcta: ¡ Pruébelo en línea!
DJMcMayhem

Sí, no estaba seguro de la entrada. Pero la solución sería de hecho fácil. Lo editaré de la manera oficial .
ბიმო

Por cierto, mi enfoque parcheado está aquí: codegolf.stackexchange.com/a/133441/31716
DJMcMayhem

1

Java 7 por 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) {

Pruébalo en línea!

No se necesitan trucos específicos de Linux, solo un simple enmascaramiento de los nombres no calificados Stringy de Systemclase. Probablemente esta no sea la solución prevista, pero funciona.



1

RProgN2 por @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|}"+"=

Pruébalo en línea!

Esta no es la mejor respuesta que podría haber dado, pero permite sumar números nuevamente. Si realmente lo hubiera hecho e hice un manejo adecuado de la pila, probablemente podría jugar golf bastante, pero a partir de ahora estoy contento con la respuesta.

En la publicación original de ATaco, efectivamente reasignó todos los operadores aritméticos principales para destruir sus entradas. Para solucionar este problema, redefiní qué adición era en términos de sus operaciones binarias, lo cual fue un dolor porque RProgN2 no tiene un operador de negación binaria o xor.

Nota: Si desea probar la entrada, los números con más de un dígito deben tener la forma "XX..." npara convertirse en un número real, ya que RProgN2 toma cada carácter tal cual, a menos que sea un concepto o una cadena. Editar: @ATaco señaló que agregar un '$' antes de un número de varios dígitos hará lo mismo.

EDITAR: Aquí está la lógica de mi solución. Como puede ver, definitivamente no es el código más refinado, pero funciona.

{"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

Proporcionar un $ antes de una picadura de números también lo agrupa como un número, por ejemplo 56$46$12, empujará los números 5, 6, 46 y 12. Publicaré mi solución real y tal mañana
ATaco

No lo sabia. Me limité a mirar a través de tus llamadas para averiguar qué eran las cosas.
Arnold Palmer

De hecho, podría escribir alguna documentación debido a este desafío.
ATaco

Eso sería maravilloso Logré encontrar una lista de comandos para RProgN, pero la perdí ... Y solo ayudó mucho ya que las funciones son todas diferentes. Tenía que aprender sus funciones a través de su antigua página de tutoría RProgN y sus clases invocables. Fue divertido jugar incluso si no era obvio de inmediato cómo funcionaba todo.
Arnold Palmer

1

JavaScript (Node.js) por jrich , 298 bytes

Siento que esta no es la solución prevista, pero si lo es, bien hecho, ¡pasé un tiempo tratando de descubrir cómo obtener el nombre de la función declarada! :)

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

Pruébalo en línea!


1
¡No es la solución deseada pero es muy inteligente! Nice crack +1
jrich

@jrich Sí, pensé, siéntete libre de parchar eso. ¡Me aseguraré de probar otra vez la solución deseada!
Dom Hastings

whoops ... demasiado tarde! ¡Sin embargo, estaba satisfecho con la creatividad de su solución!
jrich
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.