Friday, February 3, 2012

PrintMe (print my source code)

Hi all my readers.

Some time ago I bet to write a program that prints its own source code.

The restriction was - to use only C/C++, and that the result of the program can be substituted into the source code, recompile, which would receive the same result.

As far as I remember, it's funny, a little problem with a solution, though not simple. I wrote it and won the bet.

Then I asked how many solutions to this problem has been posted on the Internet? And to my surprise, it turned out that the Internet is almost no such solutions.

I decided to remedy this situation and show the solution here. If someone will have any questions or clarifications, I would be happy to discuss it in the comments.

 #include <stdio.h>
 #include <string>
 #include <iostream>
 #include <fstream>
 std::string a = "\
      std::ofstream     myfile(@PrintMe.txt@);$\
      std::string          b(a);$\
      std::string::iterator     it(b.begin());$\
      while (it != b.end())$\
      {$\
           if (*it == 36)$\
           {$\
                it = b.insert(++it, '__');$\
                it = b.insert(++it, '_n');$\
           }$\
           ++it;$\
      }$\
      myfile << @#include <stdio.h>@ << std::endl;$\
      myfile << @#include <string>@ << std::endl;$\
      myfile << @#include <iostream>@ << std::endl;$\
      myfile << @#include <fstream>@ << std::endl;$\
      myfile << @std::string a = _@__@ << std::endl;$\
      myfile << b << @_@;@ << std::endl;$\
      it = a.begin();$\
      while (it != a.end())$\
      {$\
           if (*it == 64)$\
           {$\
                *it = '_@';$\
           }$\
           else$\
           if (*it == 36)$\
           {$\
                *it = '_n';$\
           }$\
           else$\
           if (*it == 95)$\
           {$\
                *it = '__';$\
           }$\
           ++it;$\
      }$\
      myfile << @void main()@ << std::endl;$\
      myfile << @{@ << std::endl;$\
      myfile << a << std::endl;$\
      myfile << @}@ << std::endl;$\
      myfile.close();$\
 ";
 void main()
 {
      std::ofstream     myfile("PrintMe.txt");
      std::string          b(a);
      std::string::iterator     it(b.begin());
      while (it != b.end())
      {
           if (*it == 36)
           {
                it = b.insert(++it, '\\');
                it = b.insert(++it, '\n');
           }
           ++it;
      }
      myfile << "#include <stdio.h>" << std::endl;
      myfile << "#include <string>" << std::endl;
      myfile << "#include <iostream>" << std::endl;
      myfile << "#include <fstream>" << std::endl;
      myfile << "std::string a = \"\\" << std::endl;
      myfile << b << "\";" << std::endl;
      it = a.begin();
      while (it != a.end())
      {
           if (*it == 64)
           {
                *it = '\"';
           }
           else
           if (*it == 36)
           {
                *it = '\n';
           }
           else
           if (*it == 95)
           {
                *it = '\\';
           }
           ++it;
      }
      myfile << "void main()" << std::endl;
      myfile << "{" << std::endl;
      myfile << a << std::endl;
      myfile << "}" << std::endl;
      myfile.close();
 }



Hope you will enjoy.
Thanks.

2 comments:

  1. This is called a Quine. There are gazillions of these around the net:
    http://en.wikipedia.org/wiki/Quine_%28computing%29
    http://www.nyx.net/~gthompso/quine.htm

    ReplyDelete
    Replies
    1. @Ofek Shilon

      Oh, I really haven't known it. Thanks a lot.

      Interesting, is there exist some other interesting algorithmic-tasks similar to Quine? Do you know some other?

      Delete