Advertisement
Kaelygon

brusselSearch.cpp

Jun 24th, 2023 (edited)
704
0
Never
1
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.77 KB | None | 0 0
  1. #include <iostream>
  2. #include <unordered_map>
  3. #include <queue>
  4. #include <vector>
  5. #include <algorithm>
  6. #include "32baseten.h"
  7. #include <cstdint>
  8.  
  9. using namespace std;
  10.  
  11. unordered_map<unsigned int, tuple<uint8_t, uint8_t, bool >> steps; // steps[num] offset, length, operation(0=dobl 1=half)
  12.  
  13. // Function to find the minimal number of steps to reach m from n using Choix de Bruxelles rules
  14. vector<unsigned int> brusselSearch(unsigned int n, unsigned int m, double l) {
  15.     queue<unsigned int> branch;
  16.  
  17.     steps[m]={0,m,1};
  18.     branch.push(m);
  19.    
  20.     //biggest possible value
  21.     unsigned int largest = n>m ? n : m ;
  22.     //speeds up significantly, but if too low this can skip good paths
  23.     //21 of numbers from 1 to 1000 have steps that are 10-20x larger than n or m
  24.     //4 of the numbers: 539 389 3 and 289 has steps 20x to 39x
  25.     //999 has an optimal path that has a step of 92x. But also has an optimal path that's <10x
  26.     //these anomalies become even rarer the bigger m or n gets
  27.     //1599 ratio: 69.536
  28.     //10x is good starting point. Increase to confirm optimal path for a specific number.
  29.     largest*=l;
  30.  
  31.     unsigned long long iters = 0;
  32.  
  33.     while (!branch.empty()) {
  34.         unsigned int curr = branch.front();
  35.         branch.pop();
  36.  
  37.         if (curr == n) {
  38.             // Reconstruct the steps sequence, repeat steps in reverse
  39.             vector<unsigned int> sequence;
  40.             while (curr != m) {
  41.                 sequence.push_back(curr);
  42.                 bool operation = get<2>(steps[curr]);
  43.                 if (operation==0) {
  44.                     curr = brusselDouble(curr, get<0>(steps[curr]), get<1>(steps[curr]));
  45.                 } else if (operation==1) {
  46.                     curr = brusselDivide(curr, get<0>(steps[curr]), get<1>(steps[curr]));
  47.                 }
  48.             }
  49.             sequence.push_back(m);
  50.  
  51.             cout << iters << " Brussel operations\n";
  52.             return sequence;
  53.         }
  54.  
  55.         // Generate new numbers by doubling or dividing substrings
  56.         int currLen = logt10(curr);
  57.         for (uint8_t i = 0; i < currLen; i++) {
  58.             for (uint8_t j = i + 1; j <= currLen; j++) {
  59.  
  60.                 unsigned int newNum = brusselDouble(curr, i, j-i);
  61.                 bool tooBig = newNum>largest;
  62.                 bool overflow = newNum<curr;
  63.                 if ( !tooBig && steps.find(newNum) == steps.end() && !overflow) {
  64.                     iters++;
  65.                     int magDif = ( (int)logt10(newNum)-(int)logt10(curr) ); // magnitude difference for reconstructing sequence, 0 or doubling +1 or halving -1
  66.                     steps[newNum] = {i, j-i+magDif, 1}; //{offset, len+magdif, inverse operation} rules to go back from newNum to curr
  67.                     branch.push(newNum); //insert to queue
  68.                 }
  69.  
  70.                 newNum = brusselDivide(curr, i, j-i);
  71.                 if (newNum && steps.find(newNum) == steps.end()) {
  72.                     iters++;
  73.                     int magDif = ( (int)logt10(newNum)-(int)logt10(curr) );
  74.                     steps[newNum] = {i, j-i+magDif, 0};
  75.                     branch.push(newNum);
  76.                 }
  77.  
  78.             }
  79.         }
  80.     }
  81.  
  82.     // If no path is found
  83.     return vector<unsigned int>();
  84. }
  85.  
  86. int main(int argc, char** argv){
  87.     unsigned int start = 999;
  88.     unsigned int target = 1;
  89.     double maxmult = 10;
  90.  
  91.     if( argc>1 ){
  92.         start = stoll(argv[1]);
  93.     }
  94.     if( argc>2 ){
  95.         target = stoll(argv[2]);
  96.     }
  97.     if( argc>3 ){
  98.         maxmult = stoll(argv[3]);
  99.     }
  100.  
  101.     if( (start%5==0) != (target%5==0) ){
  102.         cout << "Can't be reached\n";
  103.         return 0;
  104.     }
  105.  
  106.     vector<unsigned int> sequence = brusselSearch(start,target,maxmult);
  107.  
  108.     if (!sequence.empty()) {
  109.         cout << "Steps: " << sequence.size()-1 << "\n";
  110.         if(start>target){
  111.             for (auto it = sequence.begin(); it != sequence.end(); ++it) {
  112.                 cout << *it << "\n";
  113.             }
  114.         }else{
  115.             for (auto it = sequence.rbegin(); it != sequence.rend(); ++it) {
  116.                 cout << *it << "\n";
  117.             }
  118.         }
  119.  
  120.         cout << "\n";
  121.  
  122.         start = start>target ? start : target; //bigger of the starting values
  123.  
  124.         auto big = max_element(sequence.begin(), sequence.end()); //biggest in sequence
  125.  
  126.         cout << "ratio: " << (double)*big/start << "\n";
  127.     } else {
  128.         cout << "No path found \n";
  129.     }
  130.  
  131.     return 0;
  132. }
Advertisement
Comments
Add Comment
Please, Sign In to add comment
Advertisement