Programa de automutilación

16

En pocas palabras, su objetivo es crear un programa completo que modifique su propio código fuente hasta que cada carácter de la fuente sea diferente de como comenzó.

Incluya la fuente inicial, así como la fuente final en su publicación, así como una descripción. Por ejemplo, describa qué (más) hace su programa, el lenguaje que utilizó, su estrategia, etc.

Reglas

  • Su programa debe detenerse en algún momento después de que se complete la modificación.
  • En realidad, debe modificar su propio código fuente actualmente en ejecución (no necesariamente el archivo que le pasó al intérprete, modifica sus instrucciones), no imprimir un nuevo programa o escribir un nuevo archivo.
  • Las lagunas estándar no están permitidas.
  • El programa más corto gana.

  • Si su idioma puede modificar su propio archivo y ejecutar un nuevo proceso de compilación, pero no puede modificar su propio código fuente (actualmente en ejecución), puede escribir dicho programa en su lugar con una penalización de + 20% bytes, redondeado. Los lenguajes auto modificables reales deberían tener una ventaja.

Editar : si su programa se detiene con errores, especifíquelo como tal (y tal vez diga cuáles son los errores).

mbomb007
fuente
77
¿Entiendo correctamente que el programa debe modificar su propia fuente mientras se está ejecutando, de una manera que potencialmente afecta su comportamiento? Esto descartaría la mayoría de los lenguajes no esotéricos. ¿O está permitido modificar la fuente y lanzar un nuevo proceso de intérprete / compilador?
Zgarb
@ Zgarb En realidad, debe modificar su propio código fuente, actualmente en ejecución. Sí, eso descarta la mayoría de los idiomas.
mbomb007
8
@ mbomb007 Eso está mal.
mınxomaτ
1
@ mbomb007 Se dice que en ningún lugar del desafío debe ejecutar el código fuente modificado.
mınxomaτ
1
Además, no, no hace que este desafío sea trivial, todavía tendrá un buen alcance. Usted descartó demasiados idiomas con esto.
mınxomaτ

Respuestas:

19

/// , 1 byte

/

El programa encuentra un /(el inicio de un grupo de reemplazo de patrones) y lo elimina en preparación para realizar el reemplazo. Luego llega a EOF, por lo que se rinde y se detiene.

lirtosiast
fuente
El es la respuesta más temprana con 1 byte, por lo que es el ganador.
mbomb007
22

Laberinto , 2 bytes

>@

El >gira la fuente para que se convierta

@>

El puntero de instrucciones ahora está en un callejón sin salida y se da vuelta para golpear el @que termina el programa.

Por supuesto, <@también funcionaría.

Martin Ender
fuente
12

Python 2, 225 bytes

import sys
from ctypes import*
c=sys._getframe().f_code.co_code
i=c_int
p=POINTER
class S(Structure):_fields_=zip("r"*9+"v",(i,c_void_p,i,c_char_p,i,p(i),i,c_long,i,c_char*len(c)))
cast(id(c),p(S)).contents.v=`len([])`*len(c)

El código fuente final es una cadena de "0"s cuya longitud es igual al número de bytes en el objeto de código compilado original.

El código encuentra el objeto de código en ejecución sys._getframe().f_code.co_code, y crea una estructura que representa los objetos de cadena de Python. Luego obtiene la memoria que el código realmente toma y lo reemplaza "0"*len(c).

Cuando se ejecuta, el programa sale con el siguiente rastreo:

XXX lineno: 7, opcode: 49
Traceback (most recent call last):
  File "main.py", line 7, in <module>
    cast(id(c),p(S)).contents.v=`1+1`*len(c)
SystemError: unknown opcode

Esto muestra que la sobrescritura fue exitosa y el programa muere porque 0no es un código de operación válido.

Me sorprende que esto sea incluso posible en Python, los objetos de marco son de solo lectura, no puedo crear otros nuevos. Lo único complicado que esto hace es cambiar un objeto inmutable (una cadena).

Azul
fuente
No estoy seguro si esto cumple con los requisitos de que CADA personaje debe ser diferente. El "1" en el código fuente original aún sería un "1" en el código destrozado ...
Darrel Hoffman
Bueno, en realidad, la "1"cadena en el código no es realmente parte del 'código', es solo una constante a la que se hace referencia en el código de bytes. Lo que realmente estoy cambiando son los códigos de operación compilados de la máquina virtual de Python, no las constantes o variables. Entonces, lo que estoy cambiando no es el código fuente por ejemplo, solo el código compilado. Podría cambiar el código fuente tal como está almacenado, pero eso en realidad no afectaría el código en tiempo de ejecución porque ya se habría compilado. Si quisieras, podría publicar esto en un 'código de operación compilado de Python 2.7 con constantes', pero eso sería una OMI tonta.
Azul
Y tampoco puedo ver el código compilado porque al cambiarlo para ver el interior, en realidad estoy cambiando el código, lo que significa que en realidad no veo el código. Entonces, realmente, no tengo idea si el código realmente reemplaza a cada personaje, solo que cambia la mayoría (?) De ellos
Azul
Para moverse por la cuestión de la 1 no hayan cambiado en el código compilado, se puede cambiar la "1"que <backtick>1+1<backtick>sólo el 2 más bytes
Mego
No es lo que veo (compilado con 2.7.10). Desafortunadamente, el 1+1de mi sugerencia se convierte en un 2en la versión compilada ... ¡El compilador es demasiado inteligente por su propio bien!
Mego
11

mal , 1 byte

q

evil tiene varios almacenes de memoria: uno es el código fuente en sí y otro es la rueda, que es una cola circular que se inicializa en un solo cero. qintercambia el código fuente y la rueda, por lo que reemplaza la fuente con un byte nulo. Sin embargo, solo las letras minúsculas son operadores reales en el mal, por lo que ese personaje es simplemente un no-op y el programa termina.

Martin Ender
fuente
6

MSM , 8 bytes

'.qp.;.;

Transforma el código fuente a pqpqpqpq

MSM opera en una lista de cadenas. Los comandos se toman desde la izquierda y tratan el lado derecho como una pila. MSM siempre funciona en su propia fuente.

Seguimiento de ejecución:

'.qp.;.;                       upon start the source is implicitly split into a
                               list of single char strings

' . q p . ; . ;                ' takes the next element and pushes it on the stack
    q p . ; . ; .              q is not a command so it's pushed
      p . ; . ; . q            same for p
        . ; . ; . q p          . concats the top and next to top element
          ; . ; . pq           ; duplicates the top element
            . ; . pq pq        concat
              ; . pqpq         dup
                . pqpq pqpq    concat
                  pqpqpqpq     MSM stops when there's only one element left      
nimi
fuente
6

Malbolge, 1 o 2 bytes.

D

El lenguaje Malbolge "encripta" cada instrucción después de ejecutarla, por lo que esta letra (Malbolge NOP) se convertirá en un !(que también es un nop), y luego terminará. Por alguna razón, el intérprete de Malbolge que uso requiere dos bytes para ejecutarse, lo que da lugar DC(ambos son nops) !U(ambos son también nops)

Editar: El estado inicial de la memoria Malbolge depende de los últimos dos caracteres en el código, por lo que no está bien definido para los programas de un carácter. (Aunque a este código no le importa el estado inicial de la memoria)

pppery
fuente
5

x86 asm - 6 bytes

no estoy seguro si "hasta que cada carácter de la fuente sea diferente de como comenzó" se refiere a cada byte, cada modificación nemónica o general. si no soy válido, puedo cambiar el xor a un rep xor para que cada bit cambie los valores, pero esperaba no hacer eso para ahorrar 6 bytes más y permanecer al menos un poco comparable a estos idiomas de golf especializados.

Todo lo que hace es cambiar un c2 a un c3 retn obteniendo la dirección en vivo de eip y enviando 5 bytes al frente.

58          | pop eax                        ; store addr of eip in eax
83 70 05 01 | xor dword ptr ds:[eax + 5], 1  ; c2 ^ 1 = c3 = RETN
c2          | retn                           ; leave
Pulga
fuente
5

SMBF , 92 bytes

Se puede jugar al golf, y probablemente trabajaré más en eso más tarde.

>>+>>+>>+>>+>>+>>+[<-[>+<---]>+++++<<]>>>>>--[>-<++++++]>--->>++>+++++[>------<-]>->>++[<<]<

Explicación

El programa genera los siguientes comandos al final de su cinta para borrarse, por lo que debe generar los siguientes valores en la cinta:

[[-]<]          ASCII: 91 91 45 93 60 93

Haga un montón de 91s, con _valores nulos (mostrados como ) entre para usar para valores temporales.

>>+>>+>>+>>+>>+>>+[<-[>+<---]>+++++<<]

code__91_91_91_91_91_91_
   ^

Ajusta los valores por las diferencias

>>>>>--[>-<++++++]>---  Sub 46
>>++                    Add 2
>+++++[>------<-]>-     Sub 31
>>++                    Add 2
[<<]<                   Shift left to the code
code__[_[_-_]_<_]_      Zero out the code
   ^

La cinta que sigue a la ejecución será todo ceros, con la excepción del código generado [_[_-_]_<_].

Nota:

Este programa me hizo darme cuenta de que mi intérprete de Python para SMBF tiene un error o dos, y aún no he descubierto una solución. Ya está arreglado.

mbomb007
fuente
4

Emacs Lisp 22 bytes

(defun a()(defun a()))

Ejecutar desde REPL:

ELISP> (defun a()(defun a()))
a
ELISP> (symbol-function 'a)
(lambda nil
  (defun a nil))

ELISP> (a)
a
ELISP> (symbol-function 'a)
(lambda nil nil)

La función ahora se evalúa como nil.

Alternativamente (desvincularse) 30 bytes

(defun a()(fmakunbound 'a)(a))

Evaluar y errores como void-function. La función existía antes de ejecutarse.

Jonathan Leech-Pepin
fuente
4

Código rojo , 7 bytes, 1 instrucción (solo un ejemplo. No compite)

Este es un ejemplo trivial.

Mueve la siguiente ubicación de memoria sobre sí mismo, luego se detiene (porque se inicializa toda la memoria DAT 0 0, lo que detiene el programa cuando se ejecuta).

MOV 1 0
mbomb007
fuente
2
¿Por qué estás contando esto como instrucciones en lugar de bytes?
Martin Ender
Porque no sé cuántos bytes son. ? Creo que es depende del tamaño de la memoria, o la aplicación ...
mbomb007
44
Contaría con caracteres ASCII si no sabe cómo se implementa.
lirtosiast
1
Desde la página de Wikipedia: cada instrucción de Redcode ocupa exactamente una ranura de memoria y tarda exactamente un ciclo en ejecutarse. ... La memoria se direcciona en unidades de una instrucción.
mbomb007
3
Todas las publicaciones de código de golf se puntúan en bytes. Como no hay un código de máquina Redcode, debemos usar los caracteres en la "fuente de ensamblaje", no en lo que se ensambla.
lirtosiast
3

Powershell 65 bytes

function a{si -pat:function:a -va:([scriptblock]::create($null))}

Defina una función que se reescribe en nula.

Evaluarlo una vez y se elimina a sí mismo.

Alternativamente (se elimina de la memoria) 36 bytes

function a{remove-item function:a;a}

Llamarlo primero lo elimina y luego intenta evaluarlo recursivamente. Error como un comando desconocido.

Jonathan Leech-Pepin
fuente
3

MIXAL, 6 bytes (contando 2 pestañas)

    STZ    0

El programa comienza en la ubicación de memoria 0 y luego escribe 0 en la ubicación de memoria 0, borrándose así mismo. La máquina se detiene automáticamente.

Este es el lenguaje ensamblador para la hipotética computadora MIX de Donald Knuth, que puede ensamblarse y ejecutarse utilizando el kit de desarrollo GNU MIX ( https://www.gnu.org/software/mdk/ ).

musaritmia
fuente
3

> <> , 40 34 30 bytes

0&00a6*0&1+:&060"c"l=?!.~~r >p

Pruébalo aquí!

Explicación:

0&          Adds 0 to the registry
00a6*       Adds "0,0,<" to the stack; coords followed by a character
------------loop start (for clarity)
0           0 added to stack
&1+:&       Registry retrieved, increased by 1, duplicated, one put back in registry
0           ASCII character 0 added to stack (just a 0 but will be converted to that character when inserted in the code)
60          6 and 0 added to stack
"c"         The number 99 added to stack (length of code + 1 * 3)
l=?         Code length added to stack, checks if it is equal to 111

!.          If false, pointer jumps back to character (9,0) (loop start position)
~~r >p      If true, removes the 0 and 9, reverses stack, then loops the p command setting
all the characters to a "<" character and the 2nd character to a " "

Básicamente, esto pone un montón de 3 bloques de caracteres en la pila de la siguiente manera: (ypos, xpos, carácter ASCII) que se invierte al final para que el comando final 'p' lea (carácter, xpos, ypos) y establezca esa posición en el código para ese personaje. El primer carácter se establece manualmente como '<', de modo que el código termina siendo '> p <' al final para repetir el comando. Luego, todos los demás caracteres se sobrescriben como un '', incluido el carácter p. El '' es en realidad "ASCII CHAR 0", que NO es un NOP y dará un error cuando se lea.

También tiene que haber un número impar (?) De caracteres antes del comando 'p' o, de lo contrario, no se colocará en una última vez y se sobrescribirá.

torcado
fuente
2

Lote, 11 bytes

@echo>%0&&*

Modifica el código fuente a ECHO is on.

@           - don't echo the command.
 echo       - print ECHO is on.
     >%0    - write to own file.
        &&* - execute * command after the above is done, * doesn't exist so program halts.

El @está allí para que el comando no se repita, pero sobre todo para que los dos echos no se alineen.

ericw31415
fuente
la @puede quitar, porque ECHO(en mayúsculas) =! echo(minúsculas)
pppery
@ppperry Los dos echos no pueden alinearse.
ericw31415
Pero son casos diferentes.
pppery
2

Jolf, 4 bytes, sin competencia

₯S₯C

Esto proporciona ₯Sel ₯Cvalor del elemento oda a la entrada, undefinedya que no se proporciona ninguno. Pruébalo aquí!

Conor O'Brien
fuente
0

(Sistema de archivos) Befunge 98, 46 bytes

ff*:1100'aof0'ai
               21f0'ai@

Tenga en cuenta que este programa crea y manipula un archivo llamado a. Cómo funciona:

  1. El código crea un archivo llamado a contiene el código completo (hasta 256 caracteres en cada dimensión) desplazado un espacio hacia arriba y dos hacia la izquierda.
  2. Este programa lee el archivo nombrado acomo una línea, reemplazando toda la primera línea con el contenido dea archivo.
  3. Se ejecuta la segunda línea, que se ha copiado frente a la IP.
  4. Lo que lee el aarchivo en la segunda línea se desplazó dos lugares a la derecha.

Como efecto secundario, ¡el código fuente final ni siquiera es válido Befunge! (porque contiene nuevas líneas como datos en una sola línea)

pppery
fuente
0

Python 2, 238 bytes + 20% = 285.6

# coding: utf-8
import codecs
with codecs.open(__file__,'r') as f:
    t = f.read()
n="utf-8" if t.startswith("# coding: ascii") else "ascii"
with codecs.open(__file__,'w', encoding=n) as f:
    f.write(t[0]+" coding: "+n+t[t.find("\n"):])

Básicamente, esto alterna la codificación de archivo actual de la fuente de Python entre asciiy utf-8, por lo tanto, ¡esencialmente cambia cada carácter de la fuente!

Prahlad Yeri
fuente
Hay algunos espacios adicionales que se pueden eliminar. ) as-> )as, ) else-> )else, "utf-8"if, 'w',encoding.
mbomb007