Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Мультиязыковые квайны

Anna | 16.06.2014 | нет комментариев
Прочитал статью «Эстафета из 50-ти квайнов». Подлинно, человек написал ошеломляющую штуку, грандиозный труд, реальное произведение искусства. Но по комментам судя, многие не понимают, как сходственные вещи делаются и предполагают их чем-то на грани, если не за гранью, человеческих вероятностей, исключительно много эмоций было по поводу эзотерических языков (Brainfuck, Unlambda, Whitespace) в списке.
В этой статье я попытаюсь объяснить, как сходственные квайны пишутся.

Вот код на питоне, тот, что генерирует код на брейнфаке, тот, что генерирует код на анлямбде, тот, что генерирует изначальный код на питоне:

data = 'def brainfuck(st): return "".join([" "*ord(c) ".>" for c in st])ndef unlambda(st): return "`r" "`"*len(st) "".join(["." e for e in st]) "i"nprint brainfuck(unlambda('data = %s'%`data` chr(10) data))'
def brainfuck(st): return "".join([" "*ord(c) ".>" for c in st])
def unlambda(st): return "`r" "`"*len(st) "".join(["." e for e in st]) "i"
print brainfuck(unlambda('data = %s'%`data` chr(10) data))

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

>>> data = 'def brainfuck(st): return "".join([" "*ord(c) ".>" for c in st])ndef unlambda(st): return "`r" "`"*len(st) "".join(["." e for e in st]) "i"nprint brainfuck(unlambda('data = %s'%`data` chr(10) data))'
>>> print data
def brainfuck(st): return "".join([" "*ord(c) ".>" for c in st])
def unlambda(st): return "`r" "`"*len(st) "".join(["." e for e in st]) "i"
print brainfuck(unlambda('data = %s'%`data` chr(10) data))

Соответственно, текст программы целиком дозволено представить дальнейшей строкой:

'data = %s'%`data` chr(10) data

Функция unlambda получает текст и возвращает программу на unlambda его печатающую.
Функция brainfuck — то же самое для brainfuck.

Ну и соответственно

brainfuck(unlambda('data = %s'%`data` chr(10) data))

это строка, представляющая из себя программу на Brainfuck, выводящую программу на Unlambda, выводящую начальную программу на
Питоне.
В цепочку легко добавлять новые языки, для всякого языка пишется функция, которая получает строчку и возвращает программу на этом языке, которая эту строчку печатает, после этого эта функция добавляется к строчке итога, ну и соответственно data вычисляется снова.

Апдейт.

Посмотрел на дискуссию в комментах и осознал, что необходимо объяснить получше.
Квайноподобную конструкцию (тут и дальше речь только о языках, где дозволено поделить данные и код) дозволено поделить на две части:
1) секция данных (значимый момент, эта часть остаётся незаполненной до того момента, когда код будет завершён, позже этого он кодируется).
2) секция кода
Секция данных — это некоторый шифр, тот, что дозволено расшифровать двумя методами, в итоге расшифровки первым методом получится строковое представление собственно сегмента данных, при расшифровке вторым методом получится строковое представление сегмента кода. Объединив итоги этих расшифровок, мы получим строку, в которой содержится каждый начальный код программы.
В вышеприведённом примере, такая строка это - ’data = %s’%`data` chr(10) data.
‘data = %s’%`data` — расшифровка дающая секция данных, data — расшифровка дающая секция кода, ну и chr(10) — переход строки между ними.
А дальше, позже того, как у нас в руках есть эта магическая строчка, мы можем сделать с ней всё что захотим. Если мы её легко распечатаем, получим обыкновенный квайн:

data = "l = 'data = %s'%`data` chr(10) datanprint l"
l = 'data = %s'%`data` chr(10) data
print l

Если перевернём, получим программу, которая печатает свой текст задом-наперёд:

data = "l = 'data = %s'%`data` chr(10) datanprint l[-1::-1]"
l = 'data = %s'%`data` chr(10) data
print l[-1::-1]

Можем написать программу, которая печатает своё шестнадцатеричное представление:

data = "l = 'data = %s'%`data` chr(10) datanprint ' '.join([hex(ord(e)) for e in l])"
l = 'data = %s'%`data` chr(10) data
print ' '.join([hex(ord(e)) for e in l])

В всеобщем можем написать программу, которая печатает свой код позже всякий трансформации (ну либо цепочки трансформаций, как в нашем случае). «Шифр» не обязан быть именно внутренним питоновским представлением строк, дозволено зашифровать скажем в виде ascii-кодов либо ещё как-нибудь и соответствующем образом изменить процедуру расшифровки:

data = [108, 32, 61, 32, 39, 100, 97, 116, 97, 32, 61, 32, 37, 115, 39, 37, 100, 97, 116, 97, 43, 99, 104, 114, 40, 49, 48, 41, 43, 39, 39, 46, 106, 111, 105, 110, 40, 91, 99, 104, 114, 40, 101, 41, 32, 102, 111, 114, 32, 101, 32, 105, 110, 32, 100, 97, 116, 97, 93, 41, 10, 112, 114, 105, 110, 116, 32, 108]
l = 'data = %s'%data chr(10) ''.join([chr(e) for e in data])
print l

 Источник: programmingmaster.ru
Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB