Quine

December 12, 2021

Quine 是個可以複製自己的程式,不能有任何輸入。

解法思路

乍看像是個自我指涉問題,例如有段程式碼 print(),想要顯示這段程式碼,直覺上會寫為 print('print()'),然而程式碼多寫了 'print()',因此得又加上去成為 print('print(\'print()\')'),這下子不得了,程式碼又變長了,又要 print('print(\'print(\'print()\')\')') …沒完沒了這?

其實程式可以分為 A、B 兩部分,A 是資料,代表程式碼的描述形式,例如,包含了程式碼中使用到的文字符號,這些符號可以組合出程式碼,然而程式碼的描述也可能是其他形式,例如位元組。

B 是程式,會讀取、顯示 A 的資料,例如,若 A 的描述形式是程式碼中使用到的文字符號,最簡單的方式是建構法(constructive method),不必用上特別的技巧,B 就像個磁帶機,來回地讀取 A 資料的某些字元並顯示。

以生物細胞的複製來比喻,DNA 包含了細胞的資料,細胞本身是個程式,讀取 DNA 來複製出另一個細胞。

簡單來說,先將程式碼編碼為資料,然後有另一個解碼程式來還原出程式。

除了以下我寫的 Quine 之外,〈The Quine Page〉有各種語言的 Quine。

程式實作

import static java.lang.System.out;
public class Quine{
  public static void main(String[] args){
    String h="import static java.lang.System.out;\npublic class Quine{\n  public static void main(String[] args){\n";
    String d="String h=String d=String s=String c=";
    String s="\"\\n;}    ";
    String c="    out.println(h+s.substring(5)+d.substring(0,9)+s.charAt(0)+(h.substring(0,35)+s.substring(1,3))+h.substring(36,55)+s.substring(1,3)+h.substring(56,97)+s.substring(1,3)+s.charAt(0)+s.charAt(3));out.println(s.substring(5)+d.substring(9,18)+s.charAt(0)+d+s.charAt(0)+s.charAt(3));out.println(s.substring(5)+d.substring(18,27)+s.charAt(0)+s.charAt(1)+s.charAt(0)+s.charAt(1)+s.charAt(1)+s.substring(2)+s.charAt(0)+s.charAt(3));out.println(s.substring(5)+d.substring(27)+s.charAt(0)+c+s.charAt(0)+s.charAt(3));    out.println(c+s.substring(7)+s.charAt(4)+s.charAt(4));";
    out.println(h+s.substring(5)+d.substring(0,9)+s.charAt(0)+h.substring(0,35)+s.substring(1,3)+h.substring(36,55)+s.substring(1,3)+h.substring(56,97)+s.substring(1,3)+s.charAt(0)+s.charAt(3));out.println(s.substring(5)+d.substring(9,18)+s.charAt(0)+d+s.charAt(0)+s.charAt(3));out.println(s.substring(5)+d.substring(18,27)+s.charAt(0)+s.charAt(1)+s.charAt(0)+s.charAt(1)+s.charAt(1)+s.substring(2)+s.charAt(0)+s.charAt(3));out.println(s.substring(5)+d.substring(27)+s.charAt(0)+c+s.charAt(0)+s.charAt(3));    out.println(c+s.substring(7)+s.charAt(4)+s.charAt(4));  }}
t = 't=\'\\n\nprint(t[0:3]+t[0:2]+t[3]+t[2]+t[3]*2+t[4]+t[3:5]+t[6:]+t[2]+t[5]+t[6:])'
print(t[0:3]+t[0:2]+t[3]+t[2]+t[3]*2+t[4]+t[3:5]+t[6:]+t[2]+t[5]+t[6:])

# r='r=%r;print(r%%r)';print(r%r)
val s="print(\"quine\")";val v="val s=val v=val c=val p=";val c="\\\";";val p="print(v.slice(0,6)+c(1)+s.slice(0,6)+c.slice(0,2)+s.slice(7,12)+c.slice(0,2)+s.last+c.slice(1,3)+v.slice(6,12)+c(1)+v+c.slice(1,3)+v.slice(12, 18)+c(1)+c(0)+c(0)+c(0)+c.slice(1,3)+c.slice(1,3)+v.slice(18, 24)+c(1)+p+c.slice(1,3)+p)";print(v.slice(0,6)+c(1)+s.slice(0,6)+c.slice(0,2)+s.slice(7,12)+c.slice(0,2)+s.last+c.slice(1,3)+v.slice(6,12)+c(1)+v+c.slice(1,3)+v.slice(12, 18)+c(1)+c(0)+c(0)+c(0)+c.slice(1,3)+c.slice(1,3)+v.slice(18, 24)+c(1)+p+c.slice(1,3)+p)
s="print('quine')";v="s=v=l=p=";l='";\'\\';p="print(v[0,2]+l[0]+s+l[0,2]+v[2,2]+l[0]+v+l[0]+l[1]+v[4,2]+l[2]+l[0,2]+l[3]+l[2]+l[3]+l[3]+l[2]+l[1]+v[6,2]+l[0]+p+l[0]+l[1]+p)";print(v[0,2]+l[0]+s+l[0,2]+v[2,2]+l[0]+v+l[0]+l[1]+v[4,2]+l[2]+l[0,2]+l[3]+l[2]+l[3]+l[3]+l[2]+l[1]+v[6,2]+l[0]+p+l[0]+l[1]+p)