Here is a working C# solution you can check in LINQPad:
void Main()
{
FindMissingNumberInString("9899100101103104105").Dump("Should be 102");
FindMissingNumberInString("78910121314").Dump("Should be 11");
FindMissingNumberInString("99899910011002").Dump("Should be 1000");
// will throw InvalidOperationException, we're missing both 1000 and 1002
FindMissingNumberInString("99899910011003");
}
public static int FindMissingNumberInString(string s)
{
for (int digits = 1; digits < 4; digits++)
{
int[] numbers = GetNumbersFromString(s, digits);
int result;
if (FindMissingNumber(numbers, out result))
return result;
}
throw new InvalidOperationException("Unable to determine the missing number fro '" + s + "'");
}
public static int[] GetNumbersFromString(string s, int digits)
{
var result = new List<int>();
int index = digits;
int number = int.Parse(s.Substring(0, digits));
result.Add(number);
while (index < s.Length)
{
string part;
number++;
digits = number.ToString().Length;
if (s.Length - index < digits)
part = s.Substring(index);
else
part = s.Substring(index, digits);
result.Add(int.Parse(part));
index += digits;
}
return result.ToArray();
}
public static bool FindMissingNumber(int[] numbers, out int missingNumber)
{
missingNumber = 0;
int? found = null;
for (int index = 1; index < numbers.Length; index++)
{
switch (numbers[index] - numbers[index - 1])
{
case 1:
// sequence continuing OK
break;
case 2:
// gap we expect to occur once
if (found == null)
found = numbers[index] - 1;
else
{
// occured twice
return false;
}
break;
default:
// not the right sequence
return false;
}
}
if (found.HasValue)
{
missingNumber = found.Value;
return true;
}
return false;
}
This can likely be vastly simplified but during exploratory coding I like to write out clear and easy to understand code rather than trying to write it in as few lines of code or as fast as possible.