Programma che stampa il proprio listato
Descrivere un sistema generale per poter scrivere un programma che mandato in esecuzione stampi il suo stesso set di istruzioni così com'è scritto in un qualsiasi linguaggio di programmazione capace di manipolare stringhe.
Assumiamo che il linguaggio da usare disponga (oltre delle usuali funzionalità) di una funzione di conversione da codice ASCII in carattere, di un'istruzione "print" che stampi a video una stringa, di una serie di funzioni per manipolare le stringhe (la concatenazione ad esempio) e infine che sia possibile scrivere piú istruzioni su una sola riga (in Python ad esempio si puó usare ";" per far questo) in maniera tale da poter rappresentare il listato del programma con un'unica stringa.
P. S. Non frequento spessissimo il forum, perciò chiedo scusa se questo gioco è stato già proposto o se è già molto noto.
Assumiamo che il linguaggio da usare disponga (oltre delle usuali funzionalità) di una funzione di conversione da codice ASCII in carattere, di un'istruzione "print" che stampi a video una stringa, di una serie di funzioni per manipolare le stringhe (la concatenazione ad esempio) e infine che sia possibile scrivere piú istruzioni su una sola riga (in Python ad esempio si puó usare ";" per far questo) in maniera tale da poter rappresentare il listato del programma con un'unica stringa.
P. S. Non frequento spessissimo il forum, perciò chiedo scusa se questo gioco è stato già proposto o se è già molto noto.
Risposte
Non mi sembra sia mai stato proposto in questa particolare forma, ricorso però di aver scritto un codice C che stampava il proprio codice sorgente qualche tempo fa. La mia soluzione era la seguente:
In pratica la stringa contiene la prima metà del codice che viene stampato due volte (con e senza escape characters, virgolette intorno e infine il punto e virgola. È certamente possibile fare la stessa cosa in un qualsiasi linguaggio di programmazione con le caratteristiche da te richieste.
extern char *source; int main(int argc, char *argv[]) { int i = 0; while (source[i] && argv[1][i]) { if (source[i] != argv[1][i]) { return 0; } } if (argv[1][i++] || argv[1][i++] != '\"') { return 0; } for (int j = 0; source[j] && argv[1][i]; ++i, ++j) { if (argv[1][i] == '\\') { if (argv[1][++i] == '\"' && source[j] != '\"' || argv[1][i] != 'n' && source[j] != '\n' || argv[1][i] != '\\' && source [j] != '\\') { return 0; } } if (source[j] != argv[1][i]) { return 0; } } if (argv[1][i++] != '\"' || argv[1][i++] != ';' || !argv[1][i]) { return 0; } return 1; } char *source = "extern char *source;\nint main(int argc, char *argv[]) {\n int i = 0;\n while (source[i] && argv[1][i]) {\n if (source[i] != argv[1][i]) { return 0; }\n }\n if (argv[1][i++] || argv[1][i++] != '\\\"') { return 0; }\n for (int j = 0; source[j] && argv[1][i]; ++i, ++j) {\n if (argv[1][i] == '\\\\') {\n if (argv[1][++i] == '\\\"' && source[j] != '\\\"'\n || argv[1][i] != 'n' && source[j] != '\\n'\n || argv[1][i] != '\\\\' && source [j] != '\\\\') {\n return 0;\n }\n }\n if (source[j] != argv[1][i]) { return 0; }\n }\n if (argv[1][i++] != '\\\"' || argv[1][i++] != ';' || !argv[1][i]) { return 0; }\n return 1;\n}\nchar *source = ";
In pratica la stringa contiene la prima metà del codice che viene stampato due volte (con e senza escape characters, virgolette intorno e infine il punto e virgola. È certamente possibile fare la stessa cosa in un qualsiasi linguaggio di programmazione con le caratteristiche da te richieste.
È quello che si chiama Quine. Un'alternativa è un Ouroboros, dove un programma stampa un listato che, una volta eseguito, stampa un listato che, una volta eseguito, stampa ... il programma originale. Un esempio è Quine-Relay, una mostruosità che usa 100 linguaggi diversi.
Io avevo pensato che se il linguaggio dispone di una funzione di sostituzione sost per le stringhe (o la possibilità di definirla) si risolve il problema (altrimenti bisogna scrivere il codice che simuli questa funzione qua).
Sì, ho semplicemente scambiato la stringa e il testo nel mio codice. Nota comunque che alcuni linguaggi accettano un file vuoto come codice sorgente valido e possiamo quindi dire che tali linguaggi permettono una forma molto più corta di questo "programma che stampa se stesso"..

"apatriarca":
Sì, ho semplicemente scambiato la stringa e il testo nel mio codice. Nota comunque che alcuni linguaggi accettano un file vuoto come codice sorgente valido e possiamo quindi dire che tali linguaggi permettono una forma molto più corta di questo "programma che stampa se stesso"..
