sourcecode

Wednesday, November 14, 2012

closely hovering

/**30 Answers
From the set of natural integer numbers
Let x = 1234 = {1, 2, 3, 4}
Let y = 2410 = {2, 4, 1, 0}

Write an algorithm to compute the rearrangement of x that is closest 
to y but still greater than y. Both x and y have the same number of digits.

So in the example above, the answer would be { 2, 4, 1, 3 } = 2413 which is
greater than y = 2410 and closer than any other arrangements of x.

And whats the time complexity of this algorithm?

- CameronWills on October 30, 2012 in United States | Report Duplicate 
*/

/**In another word, we want to find a number as small as possible,
call it hoverNumber;
First we construct the largest number from x. If this number is larger than y,
it proves the hoverNumber exists for such x,y.

Next, find the exact hoverNumber. Using DP and DFS.
Two cases:
1. when the higher digits are equal to y. Then the current digit can select
from the equal digit of y, and up;
2. when the higher digits are larger than y already. Then the current digit
should be as small as possible, selecting from the remaining digit pool.
*/
#include <iostream>
#include <vector>
#include <set>
using namespace std;

unsigned int parseInt(vector<unsigned int> const& v){
  //in vector v, v[0] is the highest digit position
  unsigned int result = 0;
  for(size_t ii = 0; ii < v.size(); ++ii){
    result = (result<<3) + (result<<1)+ v[ii];//10 = 8 + 2
  }
  return result;
}

vector<unsigned int> parseChar(unsigned int number){
  vector<unsigned int> result;
  while(number){
    result.push_back(number%10);
    number /= 10;
  }
  return vector<unsigned int>(result.rbegin(),result.rend());
}

ostream& operator<<(ostream& os, vector<unsigned int>const& v){
  for(size_t ii = 0; ii < v.size(); ++ii){
    os<<v[ii];
  }
  return os;
}

int compV(vector<unsigned int> const& v1, vector<unsigned int>const& v2,
  size_t end_index){//assume v1.size() == v2.size()
    //range [0, end_index)
    //return -1 if v1 < v2
    //return 0 if v1 == v2
    //return +1 if v1 > v2
    if (!end_index) return 0;
    for(size_t ii = 0; ii < end_index; ++ii){
      if (v1[ii] < v2[ii]) return -1;
      if (v1[ii] > v2[ii]) return 1;
    }
    return 0;
}
int compV(vector<unsigned int> const& v1, vector<unsigned int>const& v2){
  return compV(v1,v2,v1.size());
}

bool operator<(vector<unsigned int> const& v1, vector<unsigned int>const& v2){
  return (-1 == compV(v1,v2,v1.size()));
}


int hoverNumCalc(set<unsigned int>& digit_pool, vector<unsigned int>& result,
  vector<unsigned int> const& v_y){//assume the solution exists
    static int digit_level = 0;//inception...level, can use for vector index
    set<unsigned int>::iterator it = digit_pool.begin();
    if (digit_level + 1 == v_y.size()){//or use digit_pool.size() == 1
      //last element, only one way to construct the number
      result.push_back(*it);
      if (compV(result, v_y) <= 0){//not a good one
        result.pop_back();
        return -1;
      } else return 0;//succeed!
    }//if last one element
    if (0 == compV(result, v_y, digit_level)){//high digits the same
      //choose a minimum number that is barely larger than y-digit
      it = digit_pool.lower_bound(v_y[digit_level]);
    }
    for (;it != digit_pool.end();){
      result.push_back(*it);
      digit_pool.erase(it++);
      ++digit_level;
      if (!hoverNumCalc(digit_pool, result, v_y)) return 0;//relay the success
      --digit_level;
      digit_pool.insert(result.back());
      result.pop_back();
    }//for it
    return -1;
}

unsigned int hoverNumber(unsigned int number_x, unsigned int number_y){
  vector<unsigned int> vx(parseChar(number_x));
  set<unsigned int> sx(vx.begin(),vx.end());//small to big
  vector<unsigned int> vx_max(sx.rbegin(), sx.rend());//big to small
  vector<unsigned int> vy(parseChar(number_y));
  if (!(vy < vx_max)) return 0;//hoverNumber does not exist
  vx.resize(0);
  vx.reserve(vy.size());
  hoverNumCalc(sx, vx, vy);
  return parseInt(vx);
}

int main(){
  cout<<"Hello"<<endl;
  unsigned int a = 1234;
  unsigned int const b = 5678;//2410;
  unsigned int result = hoverNumber(a,b);
  if (!result) cout<<"No way!"<<endl;
  else cout<<result<<" is hovering over "<<b<<endl;

}

No comments: