Dziś jest poniedziałek, 13 października 2008 roku (z kalendarza...)

Quine

Quine to (zazwyczaj) niewielki program komputerowy, którego zadaniem jest wygenerowanie swojego własnego kodu źródłowego bez żadnych sztuczek w postaci pustego pliku lub odczytania skądś. Pisanie quine'ów nie jest bardzo trudnym zadaniem; wystarczy pomysł oraz dobra znajomość użytego języka programowania. Samo w sobie jest też interesującym ćwiczeniem.

Techniki pisania quine'ów są różne. Ja zaczynam od dwóch zmiennych: x oraz y. Do pierwszej wpisuję kod tworzący te dwie zmienne, lecz bez zawartości. Do drugiej leci druga część programu, zaś w niej znajduje się kod, który pobiera wartość zmiennej x i wstawia w puste miejsca od końca: wartość zmiennej y, a później siebie samej, oczywiście obie escape'owane. Na końcu wyświetlam y. Quine jest gotowy. Oto implementacje w PHP oraz w D (przełamania linii dodane dla czytelności):

<?php $x = '<'.'?php $x = \'%\'; $y = \'^\'; ';
$y = 'echo substr_replace(substr_replace(substr_replace($x,
addslashes($y), 22, 1), addslashes($x), 12, 1).$y, \'\\\'.\\\'\',
13,0); ?>'; echo substr_replace(substr_replace(substr_replace($x,
addslashes($y), 22, 1), addslashes($x), 12, 1).$y, '\'.\'',
13,0); ?>
import std.string; import std.stdio; char[] x = "import
std.string; import std.stdio; char[] x = \"%s\"; char[] y =
\"%s\"; "; char[] y = "char [] addslashes(char [] ppp){ char [] abc;
int i; for(i = 0; i < ppp.length; i++){ switch(ppp[i]){ case '\\\"':
abc ~= \"\\\\\\\"\"; break; case '\\\\': abc ~= \"\\\\\\\\\"; break;
default: abc ~= ppp[i]; } } return abc; } int main(){ writef(x,
addslashes(x), addslashes(y)); writefln(y); return 0; }"; char []
addslashes(char [] ppp){ char [] abc; int i; for(i = 0; i <
ppp.length; i++){ switch(ppp[i]){ case '\"': abc ~= "\\\""; break;
case '\\': abc ~= "\\\\"; break; default: abc ~= ppp[i]; } } return
abc; } int main(){ writef(x, addslashes(x), addslashes(y));
writefln(y); return 0; }

W PHP wykorzystałem do umieszczenia wartości obu zmiennych w $x funkcję substr_replace() (str_replace() odpada, ponieważ nie wstawia wszystkich wartości w jednej iteracji i powstają błędy). W D skorzystałem natomiast ze składni sprintf() :), lecz tu musiałem pisać własną funkcję escape'ującą i stąd listing jest taki długi. Oczywiście białe znaki i ładne formatowanie usuwa się po ukończeniu programu :). Jak komuś się nudzi, może to sobie ładnie rozbić.

W sieci można znaleźć mnóstwo quine'ów napisanych w rozmaitych językach. Oto klasyczny wręcz przykład w języku C:

char*f="char*f=%c%s%c;main(){printf(f,34,f,34,10);}%c";main(){printf(f,34,f,34,10);}

Szczególnie warte uwagi są napisane w językach ezoterycznych, np. Brainfuck (łamanie linii dodane dla lepszej czytelności):

->++>+++>+>+>+++>>>>>>>>>>>>>>>>>>>>>>+>+>++>+++>++>>+++>+>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>+>+>>+++>>>>+++>>>+++>+>>>>>>>++>+++>+++>+>+++>+>>+++>>>+++>+>++>+++>
>>+>+>+>+>++>+++>+>+>>+++>>>>>>>+>+>>>+>+>++>+++>+++>+>>+++>+++>+>+++>+>++>+++>+
+>>+>+>++>+++>+>+>>+++>>>+++>+>>>++>+++>+++>+>>+++>>>+++>+>+++>+>>+++>>+++>>+[[>
>+[>]+>+[<]<-]>>[>]<+<+++[<]<<+]>+[>>]+++>+[+[<++++++++++++++++>-]<++++++++++.<]

Pragnącym zacząć jak najszybciej, polecam napisanie quine'a w języku HQ9+ :). Kod ma długość dokładnie jednego znaku.

Istnieją również odmiany idei quine'a. Iteracyjne quine'y to zbiór różnych programów, z których pierwszy generuje źródła drugiego, drugi trzeciego, itd. zaś n-ty - pierwszego. Można też bawić się w pisanie generatorów quine'ów. Wśród twórców języków programowania popularne jest też pisanie programów wyświetlających treść piosenki 99 butelek piwa. Swego czasu zabrałem się nawet za pisanie takowego dla Revomera, ale po trzech godzinach implementowania mnożenia DWÓCH liczb skapitulowałem - dopiero później wymyśliłem ciekawe sposoby na obejście "tradycyjnej" arytmetyki, operując bezpośrednio na znakach ASCII. Zaś quine w Revomerze... akutalnie nie potrafię sobie takowego wyobrazić :D.

Powrót

Komentarze

Napisał m_gol w piątek, 7 września 2007 o 22:57

Chciałem sprawdzić ten php i wydaje się nie działać. Co mogę robić źle?

Napisał Zyx w sobotę, 8 września 2007 o 08:57

Działa - tylko w przeglądarce trzeba wziąć "Pokaż źródło" lub analogiczną opcję, no i oczywiście przełamania linii usunąć z kodu dodane we wpisie dla czytelności. Na wszelki wypadek sprawdziłem przed chwilą i wszystko jest OK.

Napisał m_gol w piątek, 14 września 2007 o 23:44

Ach, no tak, rzeczywiście, przecież chodzi o źródło, a nie wygląd po interpretacji. :)

Strona 1 z 1 :: 1

Skomentuj

NickInformacja
E-mailTylko do użytku wewnętrznego.
WWWNie zapomnij o http://
LayoutNapisz tu, czy widzisz dzienny czy nocny layout.
WpisFormatowanie wiki
Internauto, pamiętaj! Wolność to nie samowola - dbaj o kulturę wypowiedzi oraz dyskusji w sieci.

Na Zyxist.com panuje swoboda wyrażania opinii oraz krytyki pod dowolnym adresem. Jedyny warunek: musi być ona kulturalna i rzeczowa. Na chamstwo, prostactwo lub jawne obrażanie kogokolwiek nie ma tu miejsca i takie komentarze są bardzo szybko usuwane. Jeśli zamierzasz polemizować z treścią wpisu, wpierw uważnie ją przeczytaj.

© Tomasz "Zyx" Jędrzejewski 2005 - 2008 | Wykonanych zapytań: 2 | Serwer wirtualny zapewnia