Ненормальное программирование

индекс
287,20

Цепной квайн произвольного порядка на Python

   Впечатленный цепным полиглотным квайном японца, приведенным в этом хабратопике, я, ранее уже встречавшийся с программами-квайнами, решил познакомиться с ними плотнее. После беглого гугления и непродолжительного чтения вики/блогов/сайтов по теме, у меня зачесались руки и захотелось написать свой квайн. Квайн был написан, даже в нескольких вариантах, но этого мне показалось мало. Позже я даже написал двойной квайн (код на python генерирует код на prolog а код на prolog в свою очередь первоначальный python-код).

   Однако, тут возник вопрос. А можно ли написать квайн любого порядка (т.е. тот, который будет переходить сам в себя после N запусков)? Как оказалось, это вполне возможно. Результатом изысканий явился следующий код:

# xonix
L=19;B,Q,N,q,n=map(chr,(36,81,78,39,10))
X='import sys;sys.stdout.write(%s%s%s.replace(chr(36)+chr(81)+chr(36),chr(39)).replace(chr(36)+chr(81),chr(36)).replace(chr(36)+chr(78)+chr(36),chr(10)).replace(chr(36)+chr(78),chr(36)))'
Y='# xonix%sL=%s;B,Q,N,q,n=map(chr,(36,81,78,39,10))%sX=%s%s%s%sY=%s%s%s%sE="""%s""";exec E%simport sys;sys.stdout.write(b())'
E="""def b(l=L):
  if l==L: Ql=q
  else: Ql=B+Q*(L-l)+B;Nl=B+N*(L-l)+B
  if l>0: return X%(Ql,b(l-1),Ql)
  else: return Y%(Nl,str(L),Nl,Ql,X,Ql,Nl,Ql,Y,Ql,Nl,E.replace(n,Nl),Nl)"
"";exec E
import sys;sys.stdout.write(b())



   Особенностью этого кода является то, что если сохранить его в файл quine_20_0.py а затем выполнить

python quine_20_0.py > quine_20_1.py
python quine_20_1.py > quine_20_2.py
python quine_20_2.py > quine_20_3.py
...
python quine_20_19.py > quine_20_20.py


то файлы quine_20_0.py и quine_20_20.py совпадут бинарно. Меняя L можно получить цикл произвольной длины.

Для желающих проверить так ли это на самом деле могу предоставить проверочный код:

# file: quine_n_gen.py
N = 20 # quine cycle
Q='''# xonix
L=${n};B,Q,N,q,n=map(chr,(36,81,78,39,10))
X='
import sys;sys.stdout.write(%s%s%s.replace(chr(36)+chr(81)+chr(36),chr(39)).replace(chr(36)+chr(81),chr(36)).replace(chr(36)+chr(78)+chr(36),chr(10)).replace(chr(36)+chr(78),chr(36)))'
Y='
# xonix%sL=%s;B,Q,N,q,n=map(chr,(36,81,78,39,10))%sX=%s%s%s%sY=%s%s%s%sE="""%s""";exec E%simport sys;sys.stdout.write(b())'
E="""def b(l=L):
  if l==L: Ql=q
  else: Ql=B+Q*(L-l)+B;Nl=B+N*(L-l)+B
  if l>0: return X%(Ql,b(l-1),Ql)
  else: return Y%(Nl,str(L),Nl,Ql,X,Ql,Nl,Ql,Y,Ql,Nl,E.replace(n,Nl),Nl)""";exec E
import sys;sys.stdout.write(b())'
''.replace('${n}',str(N-1))

qName = 'quine_%s_0.py' % N
q = open(qName,'w')
q.write(Q)
q.close()

# test
import os
for i in range(N+1):
  os.system('python quine_%s_%s.py > quine_%s_%s.py' % (N,i,N,i+1))
  
lastQName = 'quine_%s_%s.py' % (N,N)

print ':)' if open(qName).read()==open(lastQName).read() else ':('


* This source code was highlighted with Source Code Highlighter.


   Этот код создает квайн и прогоняет преобразование. В случае успеха (файл в начале и в конце совпадает) код выводит :).

Если будет интересно, могу рассказать о процессе и идеях создания этого квайна (отдельным топиком).

UPD. Некое пояснение принципа представлено тут.
+25
18 ноября 2009, 20:33
11

комментарии (9)

+1
cheetah #
Если будет интересно, могу рассказать о процессе и идеях создания этого квайна

Конечно интересно, сразу бы и рассказывали.
+1
xonix #
В конце добавил ссылочку с каким-никаким пояснением. В целом принцип многоходового квайна повторяет принцип двухходового.
–4
spycom #
извините, а зачем это нужно? в чем практический смысл подобного… метода? )
+5
moroz1999 #
Развивать собственные мозги и расширять фантазию у окружающих.
+1
bobry #
pep-8 в ужасе :)
+1
xonix #
угу ) искусство требует жертв…
+1
Zak #
Красиво… не поленился, проверил на 2.6.4 все до байта совпало :)
0
bergen1975 #
А как это связано с алгоритмами?
По-моему задача из ряда превращения «мухи» в «слона» перестановкой букв. Сидишь и подбираешь.
Бесполезная игрушка, не?
+2
xonix #
Ну с одной стороны, не зря ведь пост находится в соответствующем разделе. А с другой это just for fun, разминка для мозга.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.