說明
自產生程式(quine)是一個程式,這個程式可以複製它自己。複製可以是不同方式,例如單純地顯示出自身程式碼,很多人會想到,不就是讀取原始碼顯示出來嗎?這被認為是作弊的行為,而且程式本身不一定知道原始碼檔案存在哪,或者不一定有原始碼,例如,若寫了一個.java,編譯它後產生一個.class檔,然後將.java檔案刪除,您的.class檔必須在沒有.java檔的情況下,也能描述自己的原始碼。
自產生程式限定不能有任何輸入,程式運行本身要能複製自己!
解法
這乍看像是個自我指涉問題,例如有段程式碼print(),你想要顯示這段程式碼,直覺上就會寫為print('print()'),然而程式碼多寫了'print()',因此得又加上去成為print('print(\'print()\')'),這下子不得了,程式碼又變成長了,又要print('print(\'print(\'print()\')\')')...沒完沒了這?根據計算理論(Computation Theorem)遞迴原理,任何的程式語言都可以簡單的寫出自產生程式,簡單指的是寫出自產生程式並不需要特別的算法。
撇開計算理論這看似高深的學科不談,來用一般的解釋來說明如何寫自產生程式,程式分做A、B兩個部分。
A是資料,代表程式碼的描述形式,例如,包含了程式碼中使用到的文字符號,這些符號可以組合出程式碼,然而程式碼的描述也可能是其他形式,例如位元組。
B是程式,會讀取、顯示A的資料,例如,若A的描述形式是程式碼中使用到的文字符號,最簡單的方式是建構法(constructive method),不必用上特別的技巧,B就像個磁帶機,來回地讀取A資料的某些字元並顯示。
以生物細胞的複製來比喻,DNA包含了細胞的資料,細胞本身是個程式,讀取DNA來複製出另一個細胞。
從程式面上更簡單來說,先將程式碼編碼為資料,然後有另一個解碼程式來還原出程式。