JoshDreamland

Evolve

Nov 12th, 2013
114
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.48 KB | None | 0 0
  1. /*
  2. ** This is free and unencumbered software released into the public domain.
  3. **
  4. ** Anyone is free to copy, modify, publish, use, compile, sell, or
  5. ** distribute this software, either in source code form or as a compiled
  6. ** binary, for any purpose, commercial or non-commercial, and by any
  7. ** means.
  8. **
  9. ** In jurisdictions that recognize copyright laws, the author or authors
  10. ** of this software dedicate any and all copyright interest in the
  11. ** software to the public domain. We make this dedication for the benefit
  12. ** of the public at large and to the detriment of our heirs and
  13. ** successors. We intend this dedication to be an overt act of
  14. ** relinquishment in perpetuity of all present and future rights to this
  15. ** software under copyright law.
  16. **
  17. ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18. ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19. ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  20. ** IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  21. ** OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  22. ** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  23. ** OTHER DEALINGS IN THE SOFTWARE.
  24. **
  25. ** For more information, please refer to <http://unlicense.org/>
  26. */
  27.  
  28. #include <string>
  29. #include <iostream>
  30. #include <cstdlib>
  31. #include <ctime>
  32. #include <map>
  33. #include <set>
  34. using namespace std;
  35.  
  36. #define randquotient 10 // Randomize every one in ten alleles
  37. #define randomization 3 // Randomize up to three extra alleles
  38. #define randrate 0.1 // Randomize somewhat infrequently
  39. #define bufsiz 256 // Max number of characters to read (long strings will take a long time)
  40.  
  41. #define print_dead false // Don't print the ones that didn't survive
  42.  
  43.  
  44. // ==========================================================
  45. // === Character Range Convenience Functions ================
  46. // ==========================================================
  47.  
  48. #define char_min ' '
  49. #define char_max 'z'
  50.  
  51. // Returns true iff a character is in our range.
  52. bool legalChar(char c) {
  53.   return c >= char_min && c <= char_max;
  54. }
  55.  
  56. // Returns a random character in our range
  57. inline char rand_char() {
  58.   return char(rand() % (char_max - char_min) + char_min);
  59. }
  60.  
  61. // Returns a random string of characters in our range
  62. string rand_str(size_t len) {
  63.   string res;
  64.   res.reserve(len);
  65.   for (size_t i = 0; i < len; ++i) {
  66.     res.append(1, rand_char());
  67.   }
  68.   return res;
  69. }
  70.  
  71.  
  72. // ==========================================================
  73. // === Genetic Functions ====================================
  74. // ==========================================================
  75.  
  76. // Generate a child from two parents
  77. string breed(string mother, string father) {
  78.   string res = mother;
  79.  
  80.   // Copy alleles randomly from mother/father
  81.   for (size_t i = 0; i < mother.length(); ++i)
  82.     if (rand() & 1)
  83.       res[i] = father[i];
  84.  
  85.   // Randomize some alleles
  86.   if (rand() / (double)RAND_MAX < randrate) {
  87.     size_t randomize = (mother.length()) / randquotient + (randomization? rand() % randomization : 0);
  88.     for (size_t i = 0; i < randomize; ++i)
  89.       res[rand() % res.length()] = rand_char();
  90.   }
  91.  
  92.   return res;
  93. }
  94.  
  95. // Check a child for fitness; how close is it to the target?
  96. size_t fitness(string child, string target) {
  97.   size_t fit = 0;
  98.   for (size_t i = 0; i < target.length(); ++i)
  99.     fit += target[i] == child[i];
  100.   return fit;
  101. }
  102.  
  103.  
  104. int main() {
  105.   string str;
  106.   char buf[bufsiz];
  107.   size_t children = 5;
  108.   cout << "Enter a string to evolve to:" << endl;
  109.   cin.getline(buf, bufsiz);
  110.  
  111.   str.reserve(bufsiz);
  112.   for (const char* i = buf; *i; ++i)
  113.     if (legalChar(*i)) str.append(i, 1);
  114.  
  115.   srand(time(0));
  116.   string
  117.     parent1 = rand_str(str.length()),
  118.     parent2 = rand_str(str.length());
  119.  
  120.   cout << "Evolve to `" << str << "'" << endl;
  121.   cout << "Initial parents:" << endl << "  " << parent1 << endl << "  " << parent2 << endl << endl;
  122.  
  123.   cout << "Enter the number of children in each generation: ";
  124.   cin >> children;
  125.  
  126.   if (children < 2) children = 2;
  127.   cout << endl << "Each generation will have " << children << " children." << endl << endl;
  128.  
  129.   size_t num_generations = 0;
  130.   for (;;) {
  131.     size_t rounds = 0;
  132.     cout << "Enter the number of generations to run: ";
  133.     cin >> rounds;
  134.     for (size_t gen = 0; gen < rounds; ++gen)
  135.     {
  136.       ++num_generations;
  137.      
  138.       multimap<size_t, string> kids;
  139.       set<string> clones; // Nature doesn't do this, but we can't have clones in our tiny strings
  140.       for (size_t child = 0; child < children; ++child)
  141.       {
  142.         string kid = breed(parent1, parent2);
  143.        
  144.         // Don't allow clones
  145.         if (clones.find(kid) != clones.end()) {
  146.           --child;
  147.           continue;
  148.         }
  149.         clones.insert(kid);
  150.        
  151.         kids.insert(pair<size_t, string>(fitness(kid, str), kid));
  152.       }
  153.      
  154.       map<size_t, string>::reverse_iterator it = kids.rbegin();
  155.       cout << '"' << (parent1 = (it++)->second) << "\" and ";
  156.       cout << '"' << (parent2 = (it++)->second) << "\" live to breed";
  157.      
  158.       if (print_dead) {
  159.         cout << "; ";
  160.         for (; it != kids.rend(); ++it)
  161.           cout << it->second << ", ";
  162.         cout << "died virgins.";
  163.       }
  164.      
  165.       cout << endl;
  166.       if (parent1 == str)
  167.         break;
  168.     }
  169.     if (parent1 == str)
  170.       break;
  171.   }
  172.  
  173.   cout << "Your string, `" << parent1 << "', appeared in generation " << num_generations << "." << endl;
  174. }
Advertisement
Add Comment
Please, Sign In to add comment