RosettaCodeData/Task/Quine/Prolog/quine-3.pro

112 lines
3.1 KiB
Prolog

% Tested with SWI-Prolog version 7.1.37
:- initialization(main).
before(Lines) :- Lines = [
"% Tested with SWI-Prolog version 7.1.37",
":- initialization(main).",
"",
"before(Lines) :- Lines = ["
].
after(Lines) :- Lines = [
"].",
"",
"% replaces quotes by harmless ats",
"% replaces backslashes by harmless slashes",
"% replaces linebreaks by harmless sharps",
"maskCode(34, 64).",
"maskCode(92, 47).",
"maskCode(10, 35).",
"maskCode(X, X).",
"",
"% Encodes dangerous characters in a string",
"encode(D, S) :- ",
" string_codes(D, DC),",
" maplist(maskCode, DC, SC),",
" string_codes(S, SC).",
"",
"decode(S, D) :- ",
" string_codes(S, SC),",
" maplist(maskCode, DC, SC),",
" string_codes(D, DC).",
"",
"% writes each entry indented by two spaces,",
"% enclosed in quotes and separated by commas,",
"% with a newline between the list entries.",
"mkStringList([],@@).",
"mkStringList([Single],Out) :-",
" atomics_to_string([@ /@@, Single, @/@@], Out).",
"",
"mkStringList([H|T], Res) :-",
" mkStringList(T, TailRes),",
" atomics_to_string([@ /@@, H, @/@,/n@, TailRes], Res).",
"",
"quine(Q) :- ",
" before(BeforeEncoded),",
" after(AfterEncoded),",
" maplist(decode, BeforeEncoded, BeforeDecoded),",
" maplist(decode, AfterEncoded, AfterDecoded),",
" atomic_list_concat(BeforeDecoded, @/n@, B),",
" atomic_list_concat(AfterDecoded, @/n@, A),",
" mkStringList(BeforeEncoded, BeforeData),",
" mkStringList(AfterEncoded, AfterData),",
" Center = @/n]./n/nafter(Lines) :- Lines = [/n@,",
" atomic_list_concat([",
" B, @/n@, BeforeData, ",
" Center, ",
" AfterData, @/n@, A, @/n@",
" ], Q).",
"",
"main :- (quine(Q), write(Q);true),halt.",
"% line break in the end of file is important"
].
% replaces quotes by harmless ats
% replaces backslashes by harmless slashes
% replaces linebreaks by harmless sharps
maskCode(34, 64).
maskCode(92, 47).
maskCode(10, 35).
maskCode(X, X).
% Encodes dangerous characters in a string
encode(D, S) :-
string_codes(D, DC),
maplist(maskCode, DC, SC),
string_codes(S, SC).
decode(S, D) :-
string_codes(S, SC),
maplist(maskCode, DC, SC),
string_codes(D, DC).
% writes each entry indented by two spaces,
% enclosed in quotes and separated by commas,
% with a newline between the list entries.
mkStringList([],"").
mkStringList([Single],Out) :-
atomics_to_string([" \"", Single, "\""], Out).
mkStringList([H|T], Res) :-
mkStringList(T, TailRes),
atomics_to_string([" \"", H, "\",\n", TailRes], Res).
quine(Q) :-
before(BeforeEncoded),
after(AfterEncoded),
maplist(decode, BeforeEncoded, BeforeDecoded),
maplist(decode, AfterEncoded, AfterDecoded),
atomic_list_concat(BeforeDecoded, "\n", B),
atomic_list_concat(AfterDecoded, "\n", A),
mkStringList(BeforeEncoded, BeforeData),
mkStringList(AfterEncoded, AfterData),
Center = "\n].\n\nafter(Lines) :- Lines = [\n",
atomic_list_concat([
B, "\n", BeforeData,
Center,
AfterData, "\n", A, "\n"
], Q).
main :- (quine(Q), write(Q);true),halt.
% line break in the end of file is important