在奎因博客系列之前的冒险中,我们探索了如何编写我们自己的奎因和内含子。今天我们将了解 QuineRelays 是什么以及如何利用 Introns 来创建它们。
想象一圈程序,每个程序都用不同的语言编写。该循环中的每个程序都有一个目的:打印序列中下一个程序的源代码。最后一个程序通过打印第一个程序的源代码来关闭循环。
本质上,QuineRelays 是一组 n 个程序,采用 n 种不同的语言,例如:
让我们看一些例子来更好地理解这个概念。
这个二阶 QuineRelay 具有一个 JavaScript 程序,可以打印一个 Python 程序,然后再打印回原始的 JavaScript 程序。这是自我复制的动态二重奏。
JavaScript → Python ⥀
JavaScript:在线尝试!
console.log((q=_=>`print(${JSON.stringify(`console.log((q=${q []})())`)})`)())
Python:在线尝试!
print("console.log((q=_=>`print(${JSON.stringify(`console.log((q=${q []})())`)})`)())")
使用三阶 QuineRelay 会让事情变得更加有趣。这个从 Haskell 程序开始,输出 Python 程序,Python 程序输出 Ruby 程序,最后 Ruby 程序循环回原始 Haskell 程序。
Haskell → Python2 → Ruby ⥀
Haskell:在线尝试!
q a b c=putStrLn $ b [toEnum 10,'q','('] show b [','] show c [','] show a [')'] main=q "q a b c=putStrLn $ b [toEnum 10,'q','('] show b [','] show c [','] show a [')']" "def q(a,b,c):print b chr(10) 'q(' repr(b) ',' repr(c) ',' repr(a) ')'" "def e(x) return 34.chr x 34.chr end;def q(a,b,c) print b 10.chr 'main=q ' e(b) ' ' e(c) ' ' e(a) ' ' 10.chr end"
Python2:在线尝试!
def q(a,b,c):print b chr(10) 'q(' repr(b) ',' repr(c) ',' repr(a) ')' q("def q(a,b,c):print b chr(10) 'q(' repr(b) ',' repr(c) ',' repr(a) ')'","def e(x) return 34.chr x 34.chr end;def q(a,b,c) print b 10.chr 'main=q ' e(b) ' ' e(c) ' ' e(a) ' ' 10.chr end","q a b c=putStrLn $ b [toEnum 10,'q','('] show b [','] show c [','] show a [')']")
Ruby:在线尝试!
def e(x) return 34.chr x 34.chr end;def q(a,b,c) print b 10.chr 'main=q ' e(b) ' ' e(c) ' ' e(a) ' ' 10.chr end q("def e(x) return 34.chr x 34.chr end;def q(a,b,c) print b 10.chr 'main=q ' e(b) ' ' e(c) ' ' e(a) ' ' 10.chr end","q a b c=putStrLn $ b [toEnum 10,'q','('] show b [','] show c [','] show a [')']","def q(a,b,c):print b chr(10) 'q(' repr(b) ',' repr(c) ',' repr(a) ')'")
这是一个四阶 QuineRelay:Ruby → Java → C# → Python ⥀
GitHub
在不同的文化中,有一些共同的象征意义。其中之一是衔尾蛇,它在埃及、希腊、罗马、印度教、西伯利亚、挪威、非洲和南美神话中都有提及。衔尾蛇是一个古老的符号,描绘了一条蛇或龙吞噬自己的尾巴,代表着创造和毁灭的永恒循环。
在北欧神话中,耶梦加得是一条巨蛇,是洛基和女巨人安格尔博达的中间的孩子。奥丁将耶梦加得扔进米德加德(人类王国)周围的海洋中,这条蛇在那里变得如此巨大,以至于它包围了世界并抓住了自己的尾巴。由于它围绕着米德加德(地球),因此被称为世界之蛇 - 衔尾蛇。耶梦加得释放尾巴是诸神黄昏(世界的最后之战)开始的标志之一。
Quine 中继非常巧妙地体现了这种象征意义,因为循环中的每个程序都会产生下一个程序,最后才会重生,因此被昵称为 Ouroboros 程序。
请坐在座位上。这是一个 128 阶 Ouroboros QuineRelay。是的,你没看错。 128!!!
Ruby → Rust → Scala → ...(其他 120 个)... → Python → R → Ratfor → rc → REXX ⥀
GitHub
好像这还不够令人印象深刻,它还包括一个复活节彩蛋。缩小后的原始 Ruby 代码包含一条 Ouroboros 龙!
让我们启动之前编写的Python内含子,尝试将其变成二阶QuineRelay。
Python Intron:在线尝试!
intron = 'wubbalubbadubdub' data = "print('intron =', repr(intron)); print('data =', repr(data)); print(data)" print('intron =', repr(intron)); print('data =', repr(data)); print(data)
利用内含子的魔力,我们现在可以轻松地将不同语言的同级奎因的代码部分放入内含子中。生成以下形式的程序:
Python:
intron = "code part of sibling" data = "code part of self" print('intron =', repr(intron)); print('data =', repr(data)); print(data)
因为,每个变量都是公正的,充当不同奎因的数据。让我们将 data 和 intron 分别重命名为 d1 和 d2。
Python:
d1 = "code part of self" d2 = "code part of sibling" print('d1 =', repr(d1)); print('d2 =', repr(d2)); print(d1)
现在,d2充当内含子,但上面的程序仍然尝试打印self的代码部分。为了让它打印下一个的源代码,让我们在最后打印(d2)而不是打印(d1)。
Python:
d1 = "code part of self" d2 = "code part of sibling" print('d1 =', repr(d1)); print('d2 =', repr(d2)); print(d2)
我们已经知道 d1 的内容只是第 3 行的副本。但是我们还没有 d2 的内容。
比如说,我们想用 JavaScript 创建一个 QuineRelay。我们在JS中写一个类似的内含子。
JavaScript:
d1 = "code part of sibling" d2 = "code part of self" console.log(`d1 = ${JSON.stringify(d1)}`); console.log(`d2 = ${JSON.stringify(d2)}`); console.log(d1);
现在,上面JS内含子的第3行,就是我们想要的同级程序的代码!
将彼此的代码粘贴为对方的内含子。
笔记。我们需要在js中添加d1''以避免一些引用不匹配
Python:在线尝试!
d1 = "print('d1 =', repr(d1)); print('d2 =', repr(d2)); print(d2)" d2 = "console.log(`d1 = ${JSON.stringify(d1)}`); console.log(`d2 = ${JSON.stringify(d2)}`); console.log(d1 '');" print('d1 =', repr(d1)); print('d2 =', repr(d2)); print(d2)
JavaScript:在线尝试!
d1 = "print('d1 =', repr(d1)); print('d2 =', repr(d2)); print(d2)" d2 = "console.log(`d1 = ${JSON.stringify(d1)}`); console.log(`d2 = ${JSON.stringify(d2)}`); console.log(d1 '');" console.log(`d1 = ${JSON.stringify(d1)}`); console.log(`d2 = ${JSON.stringify(d2)}`); console.log(d1 '');
给你。这是一个真正的二阶 QuineRelay!一个Python程序,打印一个JavaScript程序,循环打印原始Python程序。
创建 QuineRelay 是一项创造性编码和理解不同语言如何表示和操作字符串的练习。它涉及将来自不同程序的内含子编织在一起,每个内含子都包含复制其下一个邻居的代码。
从本质上讲,n 阶接力是一种通过 n 种巧妙的方法来转义跨 n 种编程语言的引号的游戏。
请继续关注 MultiQuine 的下一篇文章!
来源和参考文献:
免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。
Copyright© 2022 湘ICP备2022001581号-3