#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <iostream>
#include <vector>
using namespace std;
typedef unsigned int UINT;
typedef unsigned short RESULT_t;
#define LIMIT 1000001
RESULT_t infos[LIMIT];
void GetBoundaries(vector<UINT>& bounds1, vector<UINT>& bounds2)
{
UINT tmp1, tmp2;
while(cin >> tmp1 >> tmp2)
{
bounds1.push_back(tmp1);
bounds2.push_back(tmp2);
}
}
RESULT_t GetLen(UINT value)
{
if (value == 1)
return 1;
if ((value < LIMIT) && infos[value])
return infos[value];
RESULT_t len;
if ((value % 2) == 1)
len = GetLen(value * 3 + 1) + 1;
else
len = GetLen(value / 2) + 1;
if (value < LIMIT)
infos[value] = len;
return len;
}
#define Power2(x, n) ((x) << (n))
void GetPartialMaxLenAndCleanForOdds(
UINT lower, UINT upper, UINT currentNumber,
RESULT_t currentLen, RESULT_t delta, RESULT_t& maxLen)
{
if ((currentNumber > upper) || (infos[currentNumber]))
return;
UINT j = (currentNumber << 1);
if ((j > upper) || (infos[j]))
return;
infos[currentNumber] = currentLen;
UINT middle = Power2(currentNumber, delta);
UINT midUpper = (upper > middle) ? middle : upper;
for(j = (currentNumber << 1); j <= midUpper; j <<= 1)
{
++currentLen;
infos[j] = currentLen;
}
if (middle < upper)
{
for(j = (middle << 1); j <= upper; j <<= 1)
{
++currentLen;
infos[j] = currentLen;
++maxLen;
}
}
}
void GetPartialMaxLenAndClean(
UINT lower, UINT upper,
UINT currentNumber, RESULT_t& maxLen)
{
RESULT_t currentLen = GetLen(currentNumber);
RESULT_t tmpMaxLen = currentLen;
UINT i;
for(i = (currentNumber<<1); i <= upper; i <<= 1)
{
++tmpMaxLen;
infos[i] = tmpMaxLen;
}
if (tmpMaxLen > maxLen)
maxLen = tmpMaxLen;
if ((currentNumber % 2) == 1)
{
GetPartialMaxLenAndCleanForOdds(lower, upper, 3*currentNumber + 1, currentLen - 1, maxLen - currentLen + 1, maxLen);
}
else
{
i = currentNumber >> 1;
if ((i % 2) == 1)
GetPartialMaxLenAndCleanForOdds(lower, upper, 3*i + 1, currentLen - 2, maxLen - currentLen + 2, maxLen);
}
}
RESULT_t SmartGetMaxLen(UINT lower, UINT upper)
{
RESULT_t maxLen = 1;
for(UINT i = lower; i <= upper; ++i)
{
if (infos[i])
{
if (infos[i] > maxLen)
maxLen = infos[i];
continue;
}
RESULT_t tmpMaxLen = 1;
GetPartialMaxLenAndClean(lower, upper, i, tmpMaxLen);
if (tmpMaxLen > maxLen)
maxLen = tmpMaxLen;
}
return maxLen;
}
void OutputResult(UINT lower, UINT upper, RESULT_t maxLen)
{
cout << lower << " " << upper << " " << maxLen << endl;
}
void DoJob(UINT bound1, UINT bound2)
{
UINT lower = (bound1 > bound2) ? bound2 : bound1;
UINT upper = bound1 + bound2 - lower;
RESULT_t maxLen = SmartGetMaxLen(lower, upper);
OutputResult(bound1, bound2, maxLen);
}
int main(int argc, char* argv[])
{
infos[1] = 1;
vector<UINT> bounds1, bounds2;
GetBoundaries(bounds1, bounds2);
for(UINT i = 0; i < bounds1.size(); ++i)
{
DoJob(bounds1[i], bounds2[i]);
}
return 0;
}