[Sequence] Finding the next number

05/08/2015 00:48 ​Exo#1
Yo,
Some days ago while practicing some algorithmic problems I came by something interesting.

A sequence of numbers formed from 2 special digits 5,8.


Now the problem is, I can't think of any way to find the closest number in the sequence to the given number.

Example:
Code:
If I want to find the number greater than 536
The answer should be 555
Do you have any idea about a fast algorithm that could do the job?
All what I could think of is something very basic [Recursive/Increment function but that's is really slow.
05/08/2015 16:12 warfley#2
There are some ways for example starting from the Highest possible Number and Count down
Code:
function GetNext(Num: Integer): Integer;
  procedure CountOneDown(var Val: integer);      // Help Method

    procedure DecArr(var a: array of byte; const curr: integer);
    begin
      if a[curr] = 8 then
        a[curr] := 5
      else
      begin
        a[curr] := 8;
        DecArr(a, curr - 1);
      end;
    end;

  var
    Digits: array of byte;
    i, len, n: integer;
  begin
    len := trunc(log10(Val)); // Digit Count - 1
    SetLength(Digits, len + 1);
    n := Val;
    // Filling Array
    for i := 0 to len do
    begin
      Digits[i] := n div (10 ** (len - i));
      n := n mod (10 ** (len - i));
    end;
    DecArr(Digits, len);
    Val:=0;
    for i := len downto 0 do
      Val += Digits[len-i] * (10 ** i);
  end;

var
  len, i, n, val, MinVal: integer;
  Digits: array of integer;
begin
  len := trunc(log10(Num)); // Digit Count - 1
  SetLength(Digits, Len + 1);
  n := Num;
  // Filling Array
  for i := 0 to len do
  begin
    Digits[i] := n div (10 ** (len - i));
    n := n mod (10 ** (len - i));
  end;
  val := 0;
  for i := 0 to len do
    val += 8 * (10 ** i); // Checking for Higest number with the same Digit count
  if val <= Num then
  begin
    for i := 0 to len + 1 do
      Result += 5 * (10 ** i); // Give lowest Number with one More Digit
    Exit;   // Exit the Method
  end;
  Result := val;  // Begining from Highest possible Number down till it isnt Greater anymore

  MinVal:=0;
  for i:=0 to len do
    MinVal+=5*(10**i);

  while val > MinVal do
  begin
    CountOneDown(Val); // Get the next lower possible number
    if val > Num then
      Result := val
    else
      Break;
  end;

end;
Other ways are like a Binary search in a sorted List (check Max value and Min Value, get Half check if Bigger than Half or Higher than Half, and search this again till you have only one element left)

Best way to work with this is using Binary system (1 = 8 0 = 5) so 111 = 888 and 000 is 555 and you can use normal Binary Arithmetics

EDIT:
An other Possibility may be checking the Digits beginning with the first, is it lower than 5 set it to 5, if its lower than 8 replace it with 8, and fill the rest with 5 and exit the loop.
is it 5 or 8 leave the digit, and check the next one, and do the same as with the first. I Guess this is the best way