Самоуничижительная программа

16

Проще говоря, ваша цель состоит в том, чтобы создать законченную программу, которая изменяет свой собственный исходный код до тех пор, пока каждый символ источника не будет отличаться от того, с которого он начинался.

Пожалуйста, включите начальный источник, а также конечный источник в ваш пост, а также описание. Например, опишите, что (еще) делает ваша программа, язык, который вы использовали, вашу стратегию и т. Д.

правила

  • Ваша программа должна остановиться через некоторое время после завершения модификации.
  • Он должен фактически изменить свой собственный, в настоящее время работающий исходный код (не обязательно файл, который вы передали интерпретатору, он изменяет его инструкции), а не печатать новую программу или писать новый файл.
  • Стандартные лазейки запрещены.
  • Кратчайшая программа выигрывает.

  • Если ваш язык может изменить свой собственный файл и выполнить новый процесс компилятора, но не может изменить свой собственный (в настоящее время работающий) исходный код, вы можете вместо этого написать такую ​​программу со штрафом + 20% байтов, округленным в большую сторону. Реальные самоизменяющиеся языки должны иметь преимущество.

Изменить : Если ваша программа останавливается с ошибками, пожалуйста, укажите его как таковой (и, возможно, сказать, что ошибки.)

mbomb007
источник
7
Правильно ли я понимаю, что программа должна изменять свой собственный источник во время работы таким образом, который потенциально влияет на ее поведение? Это исключило бы большинство неэзотерических языков. Или разрешено изменять исходный код и запускать на нем новый процесс интерпретатора / компилятора?
Згарб
@Zgarb На самом деле он должен изменить свой собственный, в настоящее время работающий исходный код. Да, это исключает большинство языков.
mbomb007
8
@ mbomb007 Это плохо.
minxomaτ
1
@ mbomb007 Нигде не сказано, что вам нужно запускать модифицированный исходный код.
Mynxomaτ
1
Кроме того, нет, это не делает этот вызов тривиальным, он по-прежнему будет хорошим. Вы исключили слишком много языков с этим.
Mynxomaτ

Ответы:

19

/// , 1 байт

/

Программа находит /(начало группы замены шаблона) и удаляет ее при подготовке к замене. Затем он достигает EOF, поэтому он сдается и останавливается.

lirtosiast
источник
Самый ранний ответ с 1 байтом, так что это победитель.
mbomb007
22

Лабиринт , 2 байта

>@

В >вращает источник , так что он становится

@>

Указатель инструкции теперь находится в тупике и поворачивается, чтобы ударить, @что завершает программу.

Конечно, <@тоже будет работать.

Мартин Эндер
источник
12

Python 2, 225 байт

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)

Конечный исходный код представляет собой строку "0"s, длина которой равна числу байтов в исходном объекте скомпилированного кода.

Код находит работающий объект кода sys._getframe().f_code.co_codeи создает структуру, которая представляет объекты строки Python. Затем он получает память, которую фактически занимает код, и заменяет ее "0"*len(c).

При запуске программа завершается со следующей трассировкой:

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

Это показывает, что перезапись была успешной, и программа умирает, потому что 0не является действительным кодом операции.

Я удивлен, что это даже возможно в python, фреймы доступны только для чтения, я не могу создавать новые. Единственная сложная вещь, которую это делает, - это изменение неизменяемого объекта (строки).

синий
источник
Не уверен, что это вполне соответствует требованиям, что КАЖДЫЙ персонаж должен отличаться. «1» в исходном исходном коде все равно будет «1» в искаженном коде ...
Даррел Хоффман
Ну, на самом деле, "1"строка в коде на самом деле не является частью «кода», это просто константа, на которую ссылается байт-код. На самом деле я меняю скомпилированные коды операций виртуальной машины python, а не константы или переменные. Так что я меняю не исходный код, а скомпилированный код. Я мог бы изменить исходный код как сохраненный, но это фактически не повлияло бы на код во время выполнения, потому что он уже был бы скомпилирован. Если бы вы хотели, я мог бы опубликовать это в «скомпилированных кодах Python 2.7 с константами», но это было бы глупо для ИМО.
Синий
Кроме того, я не могу смотреть на скомпилированный код, потому что, изменяя его, чтобы видеть изнутри, я фактически изменяю код, то есть фактически не вижу код. Так что на самом деле, я понятия не имею, действительно ли код заменяет каждый символ, просто он меняет большинство (?) Из них
Blue
Чтобы обойти проблему того, что 1 не изменяется в скомпилированном коде, вы можете изменить на "1"значение <backtick>1+1<backtick>только на 2 байта
Mego
Не то, что я вижу (составлено с 2.7.10). К сожалению, 1+1из моего предложения превращается 2в скомпилированную версию ... Компилятор слишком умен для своей пользы!
Мего
11

зло , 1 байт

q

У зла есть несколько хранилищ памяти: один - это сам исходный код, а другой - колесо, представляющее собой круговую очередь, которая инициализируется одним нулем. qменяет местами исходный код и колесо, поэтому он заменяет исходный код нулевым байтом. Тем не менее, только строчные буквы являются действительными операторами зла, поэтому этот символ просто не используется, и программа завершается.

Мартин Эндер
источник
6

МСМ , 8 байт

'.qp.;.;

Преобразует исходный код в pqpqpqpq

МСМ оперирует списком строк. Команды берутся слева и обрабатывают правую сторону как стек. МСМ всегда работает на свой собственный источник.

Трассировка выполнения:

'.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      
Ними
источник
6

Malbolge, 1 или 2 байта.

D

Язык Malbolge «шифрует» каждую инструкцию после ее выполнения, поэтому это письмо (Malbolge NOP) станет !(что также является nop), а затем завершится. По какой-то причине для использования интерпретатора Malbolge, который я использую, требуется два байта, что дает DC(оба из которых являются nops) ставшими !U(оба из которых также являются nops)

Редактирование: начальное состояние памяти Malbolge зависит от последних двух символов в коде, поэтому оно не является четко определенным для односимвольных программ. (Хотя этот код не заботится о начальном состоянии памяти)

pppery
источник
5

x86 asm - 6 байт

не уверен, относится ли «до тех пор, пока каждый символ источника отличается от того, с которого он начинался», относится к каждому байту, каждому немоническому или общему изменению. если я неверный, я могу изменить xor на rep xor, чтобы каждый бит менял значения, но надеялся не делать этого, чтобы сохранить еще 6 байтов, чтобы они оставались хотя бы немного сравнимыми с этими специальными языками гольфа.

Все, что это делает, это изменяет c2 на c3 retn, получая действующий адрес eip и хоринг 5 байтов впереди.

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
источник
5

SMBF , 92 байта

Может быть в гольф, и я, вероятно, над этим поработаю позже.

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

объяснение

Программа генерирует следующие команды в конце своей ленты, чтобы стереть себя, поэтому она должна генерировать следующие значения на ленте:

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

Создайте связку 91s с нулями (показано как _) между ними для использования в качестве временных значений.

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

code__91_91_91_91_91_91_
   ^

Отрегулируйте значения по различиям

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

Лента после выполнения будет иметь все нули, за исключением сгенерированного кода [_[_-_]_<_].

Замечания:

Эта программа дала мне понять, что мой интерпретатор Python для SMBF имеет одну или две ошибки, и я еще не нашел исправления. Это исправлено сейчас.

mbomb007
источник
4

Emacs Lisp 22 байта

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

Запустить из 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)

Функция теперь оценивается как nil.

Поочередно (отвязать себя) 30 байтов

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

Оцените и ошибки как void-function. Функция существовала до запуска.

Джонатан Лич-Пепин
источник
4

Redcode , 7 байт, 1 инструкция (просто пример. Не конкурирует)

Это тривиальный пример.

Перемещает следующую ячейку памяти на себя, затем останавливает (потому что инициализируется вся память DAT 0 0, что останавливает программу при выполнении.)

MOV 1 0
mbomb007
источник
2
Почему вы считаете это инструкциями, а не байтами?
Мартин Эндер
Потому что я не знаю, сколько это байтов. Я думаю, что это зависит от объема памяти или реализации? ...
mbomb007
4
Я бы посчитал символы ASCII, если вы не знаете, как это реализовано.
lirtosiast
1
Со страницы Википедии: Каждая инструкция Redcode занимает ровно один слот памяти и занимает ровно один цикл. ... Память адресована в единицах одной инструкции.
mbomb007
3
Все сообщения кода-гольфа оцениваются в байтах. Поскольку машинный код Redcode отсутствует, мы должны использовать символы в «источнике сборки», а не то, к чему он собирается.
lirtosiast
3

Powershell 65 байт

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

Определите функцию, которая переписывает себя в нуль.

Оцените это один раз, и оно само себя устраняет.

Поочередно (удаляет себя из памяти) 36 байт

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

Вызов его сначала удаляет, а затем пытается рекурсивно оценить. Ошибка как неизвестная команда.

Джонатан Лич-Пепин
источник
3

MIXAL, 6 байт (считая 2 вкладки)

    STZ    0

Программа запускается в ячейке памяти 0, а затем записывает 0 в ячейку памяти 0, тем самым стирая себя. Машина останавливается автоматически.

Это язык ассемблера для гипотетического компьютера MIX Дональда Кнута, который может быть собран и запущен с использованием комплекта разработки GNU MIX ( https://www.gnu.org/software/mdk/ ).

musarithmia
источник
3

> <> , 40 34 30 байт

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

Попробуй это здесь!

Объяснение:

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

По сути, это помещает в стек набор из 3-х символьных блоков следующим образом: (ypos, xpos, ASCII символ), который в конце переворачивается, поэтому последняя команда 'p' читает (символ, xpos, ypos) и устанавливает эту позицию в код для этого символа. Первый символ вручную устанавливается как «<», так что код заканчивается в конце как «> p <» для цикла команды. Затем каждый другой символ перезаписывается как '', включая символ p. '' На самом деле является "ASCII CHAR 0", который НЕ является NOP и выдаст ошибку при чтении.

Кроме того, перед командой «p» должно быть нечетное (?) Количество символов, иначе оно не будет возвращено в последний раз и перезаписано.

torcado
источник
2

Пакет, 11 байт

@echo>%0&&*

Изменяет исходный код 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.

Это @есть, поэтому команда не отображается, но в основном так, чтобы эти две echoстроки не совпадали.

ericw31415
источник
@может быть удалена, потому что ECHO( в верхнем регистре) =! echo( в нижнем регистре)
pppery
@ppperry Два echoне могут выстроиться в линию.
ericw31415
Но это разные случаи.
pppery
2

Джольф, 4 байта, неконкурентный

₯S₯C

Это ₯Sустанавливает ₯Cзначение элемента ode на вход, так undefinedкак ни один не указан. Попробуй это здесь!

Конор О'Брайен
источник
0

(Файловая система) Befunge 98, 46 байт

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

Обратите внимание, что эта программа создает и манипулирует файлом с именем a. Как это устроено:

  1. Код создает файл с именем, aсодержащим весь код (до 256 символов в каждом измерении), смещенный на один пробел вверх и на два влево.
  2. Затем эта программа считывает файл, названный aодной строкой, заменяя всю первую строку содержимым aфайла.
  3. Вторая строка, которая была скопирована перед IP, выполняется
  4. Который читает aфайл во вторую строку, сдвинув два места вправо.

Как побочный эффект, конечный исходный код даже не действует Befunge! (потому что он содержит новые строки в виде данных в одной строке)

pppery
источник
0

Python 2, 238 байт + 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"):])

По сути, это переключает текущую кодировку файла источника Python между asciiи utf-8, таким образом, существенно изменяя каждый символ источника!

Прахлад Ери
источник
Есть несколько лишних пробелов, которые можно удалить. ) as-> )as, ) else-> )else, "utf-8"if, 'w',encoding.
mbomb007