QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#432948#7117. Quineucup-admin-3-1100 ✓1ms3572kbC++2313.9kb2024-06-07 21:08:332024-06-07 21:08:33

Judging History

This is the latest submission verdict.

  • [2024-06-07 21:08:33]
  • Judged
  • Verdict: 100
  • Time: 1ms
  • Memory: 3572kb
  • [2024-06-07 21:08:33]
  • Submitted

answer

/*
ИНСТРУКЦИЯ — КАК НАПИСАТЬ КУАЙН

Мы будем всё делать на сайте
https://godbolt.org на языке C++ (именно
он открывается на этом сайте по
умолчанию).

Начнём с заготовки следующего вида:

#include <iostream>
#include <string>

const std::string s = "@";

int main() {
    std::cout << s;
}

Проблема сейчас в том, что эта программа
выводит пустую строку. Если мы сейчас
возьмём эту программу, скопируем и вставим
меж кавычек, то код не скомпилируется
из-за того, что в тексте программы есть
кавычки, переводы строк и прочие символы,
которые надо экранировать. Давайте напишем
вспомогательную программу, которая читает
текст и выводит его как строковый литерал
в кавычках (то есть экранирует всё, что
требуется, для помещения этой строки в код
сторонней программы). Реализовать это
можно, например, так:

#include <iostream>
#include <string>

int main() {
    std::string ans = "\"";
    char c;
    while (std::cin.get(c))
        switch (c) {
            case '\n':
                ans += "\\n";
                break;
            case '\\':
                ans += "\\\\";
                break;
            case '"':
                ans += "\\\"";
                break;
            default:
                ans += c;
        }
    ans += '"';
    std::cout << ans;
}

Я сохранил эту программу по адресу:
https://godbolt.org/z/TeMM6csxr

После того, как я допишу этот комментарий,
я хочу попробовать взять всё содержимое
этой программы, выделить, скопировать и
вставить на место кавычек. Но квайна не
получится, так как на месте программы всё
ещё будут пустые кавычки.

Давайте сформулируем наш алгоритм:
1) написать программу, в которой
   объявлена строковая переменная, которая
   должна будет хранить исходный код, но
   которая пока что инициализирована
   пустой строкой;
2) выделить всю эту программу, скопировать
   и вставить в вспомогательную программу;
3) выводом вспомогательной программы
   заменить кавычки в исходной программе.
Если бы этот алгоритм исполняла сама
программа, а не мы вручную, то всё бы
идеально сработало!
Так давайте и напишем заготовку программы,
которая бы всё это делала сама:

#include <iostream>
#include <string>

std::string escape(const std::string& s) {
    std::string ans;
    char c;
    for (char c : s)
        switch (c) {
            case '\n':
                ans += "\\n";
                break;
            case '\\':
                ans += "\\\\";
                break;
            case '"':
                ans += "\\\"";
                break;
            default:
                ans += c;
        }
    return ans;
}

const std::string s = "@";

int main() {
    std::string output;
    for (char c : s)
        switch (c) {
            case '@':
                output += escape(s);
                break;
            default:
                output += c;
        }
    std::cout << output;
}

Теперь дело за малым: скопировать всю
написанную тут программу в программу,
превращающую вход в строковый литерал,
и подставить её вывод вместо "@".

К сожалению, это не сработает: в нашей
программе более одного символа '@'.
Поэтому надо заменять '@' на код
программы аккуратно. В нашем случае
будет правильно сделать так: сделать
подстановку в тот символ '@', который
имеет второй номер с конца.
Заготовка получается такая:

#include <iostream>
#include <string>

std::string escape(const std::string& s) {
    std::string ans;
    char c;
    for (char c : s)
        switch (c) {
            case '\n':
                ans += "\\n";
                break;
            case '\\':
                ans += "\\\\";
                break;
            case '"':
                ans += "\\\"";
                break;
            default:
                ans += c;
        }
    return ans;
}

const std::string s = "@";

int main() {
    int cnt = 0;
    int at;
    for (at = s.size() - 1; at >= 0; --at) {
        if (s[at] == '@')
            ++cnt;
        if (cnt == 2)
            break;
    }
    std::string output = s.substr(0, at)
                       + escape(s)
                       + s.substr(at + 1);
    std::cout << output;
}

Снова скопируем этот код во
вспомогательную программу, её выводом
проинициализируем s. Это уже работает:
можно у полученного нами квайна сравнить
вывод и код с помощью веб-сервиса,
например, https://www.diffchecker.com.
*/

#include <iostream>
#include <string>

std::string escape(const std::string& s) {
    std::string ans;
    char c;
    for (char c : s)
        switch (c) {
            case '\n':
                ans += "\\n";
                break;
            case '\\':
                ans += "\\\\";
                break;
            case '"':
                ans += "\\\"";
                break;
            default:
                ans += c;
        }
    return ans;
}

const std::string s = "/*\nИНСТРУКЦИЯ — КАК НАПИСАТЬ КУАЙН\n\nМы будем всё делать на сайте\nhttps://godbolt.org на языке C++ (именно\nон открывается на этом сайте по\nумолчанию).\n\nНачнём с заготовки следующего вида:\n\n#include <iostream>\n#include <string>\n\nconst std::string s = \"@\";\n\nint main() {\n    std::cout << s;\n}\n\nПроблема сейчас в том, что эта программа\nвыводит пустую строку. Если мы сейчас\nвозьмём эту программу, скопируем и вставим\nмеж кавычек, то код не скомпилируется\nиз-за того, что в тексте программы есть\nкавычки, переводы строк и прочие символы,\nкоторые надо экранировать. Давайте напишем\nвспомогательную программу, которая читает\nтекст и выводит его как строковый литерал\nв кавычках (то есть экранирует всё, что\nтребуется, для помещения этой строки в код\nсторонней программы). Реализовать это\nможно, например, так:\n\n#include <iostream>\n#include <string>\n\nint main() {\n    std::string ans = \"\\\"\";\n    char c;\n    while (std::cin.get(c))\n        switch (c) {\n            case '\\n':\n                ans += \"\\\\n\";\n                break;\n            case '\\\\':\n                ans += \"\\\\\\\\\";\n                break;\n            case '\"':\n                ans += \"\\\\\\\"\";\n                break;\n            default:\n                ans += c;\n        }\n    ans += '\"';\n    std::cout << ans;\n}\n\nЯ сохранил эту программу по адресу:\nhttps://godbolt.org/z/TeMM6csxr\n\nПосле того, как я допишу этот комментарий,\nя хочу попробовать взять всё содержимое\nэтой программы, выделить, скопировать и\nвставить на место кавычек. Но квайна не\nполучится, так как на месте программы всё\nещё будут пустые кавычки.\n\nДавайте сформулируем наш алгоритм:\n1) написать программу, в которой\n   объявлена строковая переменная, которая\n   должна будет хранить исходный код, но\n   которая пока что инициализирована\n   пустой строкой;\n2) выделить всю эту программу, скопировать\n   и вставить в вспомогательную программу;\n3) выводом вспомогательной программы\n   заменить кавычки в исходной программе.\nЕсли бы этот алгоритм исполняла сама\nпрограмма, а не мы вручную, то всё бы\nидеально сработало!\nТак давайте и напишем заготовку программы,\nкоторая бы всё это делала сама:\n\n#include <iostream>\n#include <string>\n\nstd::string escape(const std::string& s) {\n    std::string ans;\n    char c;\n    for (char c : s)\n        switch (c) {\n            case '\\n':\n                ans += \"\\\\n\";\n                break;\n            case '\\\\':\n                ans += \"\\\\\\\\\";\n                break;\n            case '\"':\n                ans += \"\\\\\\\"\";\n                break;\n            default:\n                ans += c;\n        }\n    return ans;\n}\n\nconst std::string s = \"@\";\n\nint main() {\n    std::string output;\n    for (char c : s)\n        switch (c) {\n            case '@':\n                output += escape(s);\n                break;\n            default:\n                output += c;\n        }\n    std::cout << output;\n}\n\nТеперь дело за малым: скопировать всю\nнаписанную тут программу в программу,\nпревращающую вход в строковый литерал,\nи подставить её вывод вместо \"@\".\n\nК сожалению, это не сработает: в нашей\nпрограмме более одного символа '@'.\nПоэтому надо заменять '@' на код\nпрограммы аккуратно. В нашем случае\nбудет правильно сделать так: сделать\nподстановку в тот символ '@', который\nимеет второй номер с конца.\nЗаготовка получается такая:\n\n#include <iostream>\n#include <string>\n\nstd::string escape(const std::string& s) {\n    std::string ans;\n    char c;\n    for (char c : s)\n        switch (c) {\n            case '\\n':\n                ans += \"\\\\n\";\n                break;\n            case '\\\\':\n                ans += \"\\\\\\\\\";\n                break;\n            case '\"':\n                ans += \"\\\\\\\"\";\n                break;\n            default:\n                ans += c;\n        }\n    return ans;\n}\n\nconst std::string s = \"@\";\n\nint main() {\n    int cnt = 0;\n    int at;\n    for (at = s.size() - 1; at >= 0; --at) {\n        if (s[at] == '@')\n            ++cnt;\n        if (cnt == 2)\n            break;\n    }\n    std::string output = s.substr(0, at)\n                       + escape(s)\n                       + s.substr(at + 1);\n    std::cout << output;\n}\n\nСнова скопируем этот код во\nвспомогательную программу, её выводом\nпроинициализируем s. Это уже работает:\nможно у полученного нами квайна сравнить\nвывод и код с помощью веб-сервиса,\nнапример, https://www.diffchecker.com.\n*/\n\n#include <iostream>\n#include <string>\n\nstd::string escape(const std::string& s) {\n    std::string ans;\n    char c;\n    for (char c : s)\n        switch (c) {\n            case '\\n':\n                ans += \"\\\\n\";\n                break;\n            case '\\\\':\n                ans += \"\\\\\\\\\";\n                break;\n            case '\"':\n                ans += \"\\\\\\\"\";\n                break;\n            default:\n                ans += c;\n        }\n    return ans;\n}\n\nconst std::string s = \"@\";\nint main() {\n    int cnt = 0;\n    int at;\n    for (at = s.size() - 1; at >= 0; --at) {\n        if (s[at] == '@')\n            ++cnt;\n        if (cnt == 2)\n            break;\n    }\n    std::string output = s.substr(0, at)\n                       + escape(s)\n                       + s.substr(at + 1);\n    std::cout << output;\n}\n";
int main() {
    int cnt = 0;
    int at;
    for (at = s.size() - 1; at >= 0; --at) {
        if (s[at] == '@')
            ++cnt;
        if (cnt == 2)
            break;
    }
    std::string output = s.substr(0, at)
                       + escape(s)
                       + s.substr(at + 1);
    std::cout << output;
}

詳細信息

Test #1:

score: 100
Accepted
time: 1ms
memory: 3572kb

input:


output:

/*
ИНСТРУКЦИЯ — КАК НАПИСАТЬ КУАЙН

Мы будем всё делать на сайте
https://godbolt.org на языке C++ (именно
он открывается на этом сайте по
умолчанию).

Начнём с заготовки следующего вида:

#include <iostream>
#include <string>

const std::string s = "@";

int main() {
    std::cout << s;
}

Проблема ...

result:

ok 221 lines