Как стать автором
Обновить

Комментарии 17

Перечитал два раза, так и не понял «как подобные квайны пишутся». Я один такой? =)
Нет, я тоже не понял, какой метод здесь предлагается. Программа для каждого языка должна напечатать программу на следующем языке, учитывая все особенности представления строк на этом языке. Если взять строку, содержащую такие программы на всех используемых языках, то что-нибудь может получиться (каждая программа вырезает из строки фрагмент, который будет программой на следующем языке плюс вставляет в него генератор всей строки — опять же в терминах следующего языка). Но как здесь это делается за 3 функции? И без единого фрагмента на BF?
Ну почему без единого? Вот это
"+"*ord(c)+".>"
генерирует brainfuck на сколько я понимаю. Но все равно не дает понимания как такое можно написать, с чего вообще начинать то надо?
Кажется, понял. На языке 1 пишется программа P1, содержащая свой текст в двух экземплярах (один раз — внутри текстовой строки). На языке N — программа PN, способная написать программу на языке 1, но содержащая эту строку S только один раз. На языке 1 пишем функцию FN, которая по строке S создаёт программу PN. Дальше — проще: для каждого языка K из цепочки генерируется программа PK, которая печатает уже вычисленную строку P(K+1) (всё это происходит на языке 1). В конце программа P1 распечатывает вычисленную строку P2 — и квайн готов. Но для него нужно, чтобы в цепочке были два достаточно мощных языка подряд. Хотя напечатать два экземпляра строки может и Brainfuck…
Боюсь что без графического объяснения попытка донести суть метода так же обречена на провал. Я уже на 3-й строке начал тупить.
обновил пост
Проще говоря, в какой-то момент сложность добавления нового языка в цепочку, сводится к задаче «Hello, World».
Да, именно так. Но не обязательно весь «настоящий» код писать только на одном языке. У меня в коде все преобразования вида «получи текст, сгенерируй код на языке X, выводящий этот текст». Но в принципе ничего не мешает писать также преобразования вида «получи текст, сгенерируй код на языке X, генерирующий код на языке Y, выводящий этот текст». У товарища из Японии такие преобразования в коде есть.
Если посмотреть шаги тех 50 квайнов, то большинство из них просто выводит строку на другом языке, а какая-то хитрая магическая магия происходит в меньшем количестве шагов.

Что-то вроде (здесь PHP->Python->Ruby)

echo 'print "puts \'код очередного магического и мистического шага\'"';

Главное правильно экранировать строки, и видимо лучше автогенератором.
обновил пост
обновил пост
После смакования статьи понял, что здесь, собственно, предлагается.
'data = %s'%`data`+chr(10)+data
В результате получается код на питоне, который при выполнении печатает себя же.
unlambda('data = %s'%`data`+chr(10)+data)
В результате получается код на unlambda, который при выполнении печатает код на питоне.
brainfuck(unlambda('data = %s'%`data`+chr(10)+data))
В результате получается код на BF, который при выполнении печатает код на unlambda, который в свою очередь при выполнении печатает оригинальный текст программы.

Это означает, что после запуска кода на brainfuck на выходе будет не оригинальный код, а «предыдущий», в данном случае на unlambda.
В результате имеем не уробороса, а некого змея, сложенного вдвое.

Еще при просмотре quine-relay создается впечатление, что квайн основан на чем-то посложнее, чем
data = "..." ...
хм… а почему не уробороса? питон->брейнфак->анлямбда->питон. diffом конечную и начальную программы сравнивал, всё честно :)
а quine-relay конечно сложнее, там кроме этого базового принципа ещё до фига всяких фишек. так я и не ставил целью создать потрясающее произведение искусства, просто хотел показать, как такие уроборосы пишутся.
Верно, я был неправ. Вначале почему-то подумал, что квайн должен работать в обратном порядке.
Ну да, в цепочке есть одна программа, содержащая два одинаковых куска, и одна (перед ней), умеющая писать строку два раза. Все остальные программы просто печатают строку.

Я это вижу так:
P1:
  s="хвост"
  хвост

PN: 
  s="хвост"
  print_N "s="
  print_N string(s)
  print_N s

P_{N-1}: print_{N-1} PN
...
P2: print_2 P3

хвост:
  print_1(G2(G3(...(GN(s))...)))
  G2(s){ return print_2 s}
  G3(s){ return print_3 s}
   ...
  GN(s){ return PN(s) }


Здесь P1 — программа на основном языке, PN — программа на предыдущем. string(s), который встречается в PN — строка в том виде, в котором её хочет видеть P1 в качестве строковой переменной (с правильно размеченными спецсимволами).

Боюсь, что понятнее не стало. Но если будет больше интерпретаций, то, глядишь, и полная картина получится :)
Понять бы ещё как он, автор 50ти, ASCII-art туда засунул.
Спасибо ^_^. Написал свой квайн. (Object Pascal -> PHP -> Object Pascal).
Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории