Is it possible that anyone around here might have a run-length DECODER in C#? I'm in real need of said code. Thanks.
using System;
class RLDEC
{
static void Main()
{
int t = int.Parse(Console.ReadLine());
for (int k = 0; k < t; k++)
{
string s = Console.ReadLine();
s = runLengthDecoder(s);
Console.WriteLine(s);
}
}
static string runLengthDecoder(string s)
{
string d = ""; // decoded string
int cv; // current value
for(int k = 0; k < s.Length; k++)
{
cv = Convert.ToInt32(s[k]) - 48;
if (k + 1 < s.Length && cv != 1 && cv >= 2 && cv <= 9)
{
for(int v = 0; v < cv; v++)
d += s[k+1];
}
if (cv == 1)
{
int z = k + 1;
while(k < s.Length && z < s.Length && Convert.ToInt32(s[z]) - 48 != 1)
{
d += s[z];
z++;
k++;
}
k++;
}
}
return d;
}
}
It's hard to solve this without the specification for your encoding, but in this code
if (k + 1 < s.Length && cv != 1 && cv >= 2 && cv <= 9)
{
for(int v = 0; v < cv; v++)
d += s[k+1];
}
I would expect k to be incremented before leaving the if block.
Also, I would expect that the next if (cv==1) is an else if instead.
In that cv==1 block, I think you should just process then next character and let the outer for loop do its work.
I also don't understand how that block could work at all
Related
I need make symmetric letter “W” in string Array
get_w() Is method that should return string array that contains letter "W"
get_w(5) # should return:
public string[] GetW(int h)
{
if (h < 2) return new string[h];
int row = 0;
int stars_number = h * 4 - 3;
int times = 0;
StringBuilder[] c = new StringBuilder[h];
for(int a = 0; a < h; a++)
{
c[a] = new StringBuilder();
c[a].Length = stars_number;
}
for (int i = 0; i < stars_number; i++)
{
if (i == h - 1) times = 1;
if (i == stars_number-2 * h + 1) times = 2;
if (i == stars_number - h) times = 3;
c[row][i] = '*';
if (row < h - 1 && (times == 0 || times == 2))
{
row += 1;
}
else
{
row -= 1;
}
}
string []str = new string[h];
for(int i = 0; i < h; i ++)
{
str[i] = c[i].ToString();
}
return str;
}
if I compile it in a VS i get no errors.Here is an example of the result
This task is taken from the Codewars
but if I try to test on Codewars with the code I described above, I get this error
Edited:I changed returning array with "h" length to empty array and had got this
i found the task solution by replacing charters that equal '\0' with character ' '
here is working code
public string[] GetW(int h)
{
if (h < 2) return new string[]{};
int row = 0;
int stars_number = h * 4 - 3;
int times = 0;
StringBuilder[] c = new StringBuilder[h];
for(int a = 0; a < h; a++)
{
c[a] = new StringBuilder();
c[a].Length = stars_number;
}
for (int i = 0; i < stars_number; i++)
{
if (i == h - 1) times = 1;
if (i == stars_number-2 * h + 1) times = 2;
if (i == stars_number - h) times = 3;
c[row][i] = '*';
if (row < h - 1 && (times == 0 || times == 2))
{
row += 1;
}
else
{
row -= 1;
}
}
string []str = new string[h];
for(int i = 0; i < h; i ++)
{
c[i].Replace('\0', ' ');
str[i] = c[i].ToString();
}
return str;
}
And here is result of test
Here's the part 1 of my question, if you wanna check the background of this question :
Detecting brackets in input string
Forgive me if the title doesn't match, since I also confused how to name it appropriately to picture my problem. If anyone knows a more appropriate title, feel free to edit.
So, given below code (my own code) :
private const int PARTICLE_EACH_CHAR = 4;
/*ProcessBarLines : string s only contains numbers, b, [, and ]*/
private int ProcessBarLines(Canvas canvas, string s, int lastLineAboveNotation)
{
List<int> bracket = new List<int>();
List<int> other = new List<int>();
int currentCloseNumber = 0;
int currentOpenNumber = 0;
for (int i = 0; i < s.Length; i++)
{
if (s[i] == '[')
{
bracket.Add(i);
currentOpenNumber++;
if (i - 1 > 0 && s[i - 1] != '[')
{
currentOpenNumber = 1;
}
}
else if (s[i] == ']')
{
bracket.Add(i);
currentCloseNumber++;
if (i + 1 >= s.Length || s[i + 1] != ']' || currentOpenNumber == currentCloseNumber)
{
int min = bracket.Count - (currentCloseNumber * 2);
int max = bracket[bracket.Count - 1];
List<int> proc = new List<int>();
int firstIndex = -1;
int lastIndex = -1;
for (int ii = 0; ii < other.Count; ii++)
{
if (other[ii] > min && other[ii] < max)
{
proc.Add(other[ii]);
if (firstIndex == -1)
{
firstIndex = ii;
lastIndex = ii;
}
else
{
lastIndex = ii;
}
}
}
double leftPixel = firstIndex * widthEachChar;
double rightPixel = (lastIndex * widthEachChar) + widthEachChar;
DrawLine(canvas, currentCloseNumber, leftPixel,
rightPixel, lastLineAboveNotation * heightEachChar / PARTICLE_EACH_CHAR);
lastLineAboveNotation += currentCloseNumber - 1;
currentOpenNumber -= currentCloseNumber;
currentCloseNumber = 0;
}
}
else
{
other.Add(i);
}
}
return lastLineAboveNotation + 1;
}
Here's the test cases :
Picture 1 & 2 is the correct answer, and picture 3 is the wrong answer. Picture 3 should have a line, just like inverted from number 2, but, apparently, (if you look closely) the line is drawn on the right, but it should be on the left to be correct (above 0).
I figured, the problem is, I'm quite sure on the "min". Since it doesn't give the correct starting value.
Any idea on this? Feel free to clarify anything. It's used for writing numeric musical scores.
Btw, DrawLine() just meant to draw the line above the numbers, it's not the problem.
Finally! I found it!
private int ProcessBarLines(Canvas canvas, string s, int lastLineAboveNotation)
{
List<int> bracket = new List<int>();
List<int> other = new List<int>();
int currentCloseNumber = 0;
int currentOpenNumber = 0;
int space = 0;
for (int i = 0; i < s.Length; i++)
{
if (s[i] == '[')
{
bracket.Add(i);
currentOpenNumber++;
if (i - 1 > 0 && s[i - 1] != '[')
{
currentOpenNumber = 1;
}
}
else if (s[i] == ']')
{
bracket.Add(i);
currentCloseNumber++;
if (i + 1 >= s.Length || s[i + 1] != ']' || currentOpenNumber == currentCloseNumber)
{
int min = bracket[Math.Max(bracket.Count - ((currentCloseNumber * 2) + space), 0)];
int max = bracket[bracket.Count - 1];
space = max - min - 1;
List<int> proc = new List<int>();
int firstIndex = -1;
int lastIndex = -1;
for (int ii = 0; ii < other.Count; ii++)
{
if (other[ii] > min && other[ii] < max)
{
proc.Add(other[ii]);
other[ii] = -1;
if (firstIndex == -1)
{
firstIndex = ii;
lastIndex = ii;
}
else
{
lastIndex = ii;
}
}
}
double leftPixel = firstIndex * widthEachChar;
double rightPixel = (lastIndex * widthEachChar) + widthEachChar;
DrawLine(canvas, currentCloseNumber, leftPixel,
rightPixel, lastLineAboveNotation * heightEachChar / PARTICLE_EACH_CHAR);
lastLineAboveNotation += 1;
currentOpenNumber -= currentCloseNumber;
currentCloseNumber = 0;
}
}
else
{
other.Add(i);
}
}
return lastLineAboveNotation + 1;
}
If someone got a more efficient code, please let us know!
Just got done with the latest Codility, passed it, but didnt get 100% on it
Here is the spec
A prefix of a string S is any leading contiguous part of S. For example, "c" and "cod" are prefixes of the string "codility". For simplicity, we require prefixes to be non-empty.
The product of prefix P of string S is the number of occurrences of P multiplied by the length of P. More precisely, if prefix P consists of K characters and P occurs exactly T times in S, then the product equals K * T.
For example, S = "abababa" has the following prefixes:
"a", whose product equals 1 * 4 = 4,
"ab", whose product equals 2 * 3 = 6,
"aba", whose product equals 3 * 3 = 9,
"abab", whose product equals 4 * 2 = 8,
"ababa", whose product equals 5 * 2 = 10,
"ababab", whose product equals 6 * 1 = 6,
"abababa", whose product equals 7 * 1 = 7.
The longest prefix is identical to the original string. The goal is to choose such a prefix as maximizes the value of the product. In above example the maximal product is 10.
In this problem we consider only strings that consist of lower-case English letters (a−z).
So basically, it is a string traverse problem. I was able to pass all the validation parts, but I lost on the time. Here is what I wrote
int Solution(string S)
{
int finalCount = 0;
for (int i = 0; i <= S.Length - 1; i++)
{
string prefix = S.Substring(0, i + 1);
int count = 0;
for (int j = 0; j <= S.Length - 1; j++)
{
if (prefix.Length + j <= S.Length)
{
string newStr = S.Substring(j, prefix.Length);
if (newStr == prefix)
{
count++;
}
}
if (j == S.Length - 1)
{
int product = count * prefix.Length;
if (product > finalCount)
{
finalCount = product;
}
}
}
}
return finalCount;
}
I know that the nested loop is killing me, but I cannot think of a way to traverse the "sections" of the string without adding the other loop.
Any help would be appreciated.
Naive brute-force solution takes O(N ** 3) time. Choose length from 1 to N, get a prefix of its length and count occurences by brute-force searching. Сhoosing length takes O(N) time and brute force takes O(N ** 2) time, totally O(N ** 3).
If you use KMP or Z-algo, you can find occurences in O(N) time, so the whole solution will be O(N ** 2) time.
And you can precalc occurences, so it will take O(N) + O(N) = O(N) time solution.
vector<int> z_function(string &S); //z-function, z[0] = S.length()
vector<int> z = z_function(S);
//cnt[i] - count of i-length prefix occurrences of S
for (int i = 0; i < n; ++i)
++cnt[z[i]];
//if cnt[i] is in S, cnt[i - 1] will be in S
int previous = 0;
for (int i = n; i > 0; --i) {
cnt[i] += previous;
previous = cnt[i];
}
Here's the blog post, explaining all O(N ** 3), O(N ** 2), O(N) solutions.
my effort was as follows trying to eliminate unnecessary string compares, i read isaacs blog but it is in c how would this translate to c#, i even went as far as using arrays everywhere to avoid the string immutability factor but there was no improvement
int Rtn = 0;
int len = S.Length;
if (len > 1000000000)
return 1000000000;
for (int i = 1; i <= len; i++)
{
string tofind = S.Substring(0, i);
int tofindlen = tofind.Length;
int occurencies = 0;
for (int ii = 0; ii < len; ii++)
{
int found = FastIndexOf(S, tofind.ToCharArray(), ii);
if (found != -1)
{
if ((found == 0 && tofindlen != 1) || (found >= 0))
{
ii = found;
}
++occurencies ;
}
}
if (occurencies > 0)
{
int total = occurencies * tofindlen;
if (total > Rtn)
{
Rtn = total;
}
}
}
return Rtn;
}
static int FastIndexOf(string source, char[] pattern, int start)
{
if (pattern.Length == 0) return 0;
if (pattern.Length == 1) return source.IndexOf(pattern[0], start);
bool found;
int limit = source.Length - pattern.Length + 1 - start;
if (limit < 1) return -1;
char c0 = pattern[0];
char c1 = pattern[1];
// Find the first occurrence of the first character
int first = source.IndexOf(c0, start, limit);
while ((first != -1) && (first + pattern.Length <= source.Length))
{
if (source[first + 1] != c1)
{
first = source.IndexOf(c0, ++first);
continue;
}
found = true;
for (int j = 2; j < pattern.Length; j++)
if (source[first + j] != pattern[j])
{
found = false;
break;
}
if (found) return first;
first = source.IndexOf(c0, ++first);
}
return -1;
}
I only got a 43... I like my code though! Same script in javascript got 56 for what it's worth.
using System;
class Solution
{
public int solution(string S)
{
int highestCount = 0;
for (var i = S.Length; i > 0; i--)
{
int occurs = 0;
string prefix = S.Substring(0, i);
int tempIndex = S.IndexOf(prefix) + 1;
string tempString = S;
while (tempIndex > 0)
{
tempString = tempString.Substring(tempIndex);
tempIndex = tempString.IndexOf(prefix);
tempIndex++;
occurs++;
}
int product = occurs * prefix.Length;
if ((product) > highestCount)
{
if (highestCount > 1000000000)
return 1000000000;
highestCount = product;
}
}
return highestCount;
}
}
This works better
private int MaxiumValueOfProduct(string input)
{
var positions = new List<int>();
int max = 0;
for (int i = 1; i <= input.Length; i++)
{
var subString = input.Substring(0, i);
int position = 0;
while ((position < input.Length) &&
(position = input.IndexOf(subString, position, StringComparison.OrdinalIgnoreCase)) != -1)
{
positions.Add(position);
++position;
}
var currentMax = subString.Length * positions.Count;
if (currentMax > max) max = currentMax;
positions.Clear();
}
return max;
}
Considering there is an array returned from a function which is of very large size.
What will be the fastest approach to test if the array is sorted?
A simplest approach will be:
/// <summary>
/// Determines if int array is sorted from 0 -> Max
/// </summary>
public static bool IsSorted(int[] arr)
{
for (int i = 1; i < arr.Length; i++)
{
if (arr[i - 1] > arr[i])
{
return false;
}
}
return true;
}
You will have to visit each element of the array to see if anything is unsorted.
Your O(n) approach is about as fast as it gets, without any special knowledge about the likely state of the array.
Your code specifically tests if the array is sorted with smaller values at lower indices. If that is not what you intend, your if becomes slightly more complex. Your code comment does suggest that is what you're after.
If you were to have special knowledge of the probable state (say, you know it's generally sorted but new data might be added to the end), you can optimize the order in which you visit array elements to allow the test to fail faster when the array is unsorted.
You can leverage knowledge of the hardware architecture to check multiple parts of the array in parallel by partitioning the array, first comparing the boundaries of the partition (fail fast check) and then running one array partition per core on a separate thread (no more than 1 thread per CPU core). Note though that if a array partition is much smaller than the size of a cache line, the threads will tend to compete with each other for access to the memory containing the array. Multithreading will only be very efficient for fairly large arrays.
Faster approach, platform target: Any CPU, Prefer 32-bit.
A sorted array with 512 elements: ~25% faster.
static bool isSorted(int[] a)
{
int j = a.Length - 1;
if (j < 1) return true;
int ai = a[0], i = 1;
while (i <= j && ai <= (ai = a[i])) i++;
return i > j;
}
Target: x64, same array: ~40% faster.
static bool isSorted(int[] a)
{
int i = a.Length - 1;
if (i <= 0) return true;
if ((i & 1) > 0) { if (a[i] < a[i - 1]) return false; i--; }
for (int ai = a[i]; i > 0; i -= 2)
if (ai < (ai = a[i - 1]) || ai < (ai = a[i - 2])) return false;
return a[0] <= a[1];
}
Forgot one, marginally slower than my first code block.
static bool isSorted(int[] a)
{
int i = a.Length - 1; if (i < 1) return true;
int ai = a[i--]; while (i >= 0 && ai >= (ai = a[i])) i--;
return i < 0;
}
Measuring it (see greybeard's comment).
using System; // ????????? DEBUG ?????????
using sw = System.Diagnostics.Stopwatch; // static bool abc()
class Program // { // a <= b <= c ?
{ // int a=4,b=7,c=9;
static void Main() // int i = 1;
{ // if (a <= (a = b))
//abc(); // {
int i = 512; // i++;
int[] a = new int[i--]; // if (a <= (a = c))
while (i > 0) a[i] = i--; // {
sw sw = sw.StartNew(); // i++;
for (i = 10000000; i > 0; i--) // }
isSorted(a); // }
sw.Stop(); // return i > 2;
Console.Write(sw.ElapsedMilliseconds); // }
Console.Read(); // static bool ABC();
} // {
// int[]a={4,7,9};
static bool isSorted(int[] a) // OP Cannon // int i=1,j=2,ai=a[0];
{ // L0: if(i<=j)
for (int i = 1; i < a.Length; i++) // if(ai<=(ai=a[i]))
if (a[i - 1] > a[i]) return false; // {i++;goto L0;}
return true; // return i > j;
} // }
}
Target: x64. Four cores/threads.
A sorted array with 100,000 elements: ~55%.
static readonly object _locker = new object();
static bool isSorted(int[] a) // a.Length > 3
{
bool b = true;
Parallel.For(0, 4, k =>
{
int i = 0, j = a.Length, ai = 0;
if (k == 0) { j /= 4; ai = a[0]; } // 0 1
if (k == 1) { j /= 2; i = j / 2; ai = a[i]; } // 1 2
if (k == 2) { i = j - 1; ai = a[i]; j = j / 2 + j / 4; } // 4 3
if (k == 3) { i = j - j / 4; ai = a[i]; j = j / 2; } // 3 2
if (k < 2)
while (b && i <= j)
{
if (ai <= (ai = a[i + 1]) && ai <= (ai = a[i + 2])) i += 2;
else lock (_locker) b = false;
}
else
while (b && i >= j)
{
if (ai >= (ai = a[i - 1]) && ai >= (ai = a[i - 2])) i -= 2;
else lock (_locker) b = false;
}
});
return b;
}
1,000,000 items?
if (k < 2)
while (b && i < j)
if (ai <= (ai = a[i + 1]) && ai <= (ai = a[i + 2]) &&
ai <= (ai = a[i + 3]) && ai <= (ai = a[i + 4])) i += 4;
else lock (_locker) b = false;
else
while (b && i > j)
if (ai >= (ai = a[i - 1]) && ai >= (ai = a[i - 2]) &&
ai >= (ai = a[i - 3]) && ai >= (ai = a[i - 4])) i -= 4;
else lock (_locker) b = false;
Let's forget percentages.
Original: 0.77 ns/item, now: 0.22 ns/item.
2,000,000 items? Four cores: 4 times faster.
Linq solution.
public static bool IsSorted<T>(IEnumerable<T> list) where T:IComparable<T>
{
var y = list.First();
return list.Skip(1).All(x =>
{
bool b = y.CompareTo(x) < 0;
y = x;
return b;
});
}
Here is my version of the function IsSorted
public static bool IsSorted(int[] arr)
{
int last = arr.Length - 1;
if (last < 1) return true;
int i = 0;
while(i < last && arr[i] <= arr[i + 1])
i++;
return i == last;
}
While this function is a bit faster than in the question, it will do fewer assignments and comparisons than anything has been posted so far. In the worst case, it does 2n+1 comparisons. It still can be improved if you can make a reasonable assumption about the nature of the data like minimum data size or array contains even number of elements.
The only improvement i can think of is check both ends of the array at the same time, this little change will do it in half time...
public static bool IsSorted(int[] arr)
{
int l = arr.Length;
for (int i = 1; i < l/2 + 1 ; i++)
{
if (arr[i - 1] > arr[i] || arr[l-i] < arr[l-i-1])
{
return false;
}
}
return true;
}
This is what I came up with and find works better particularly with greater sized arrays. The function is recursive and will be called for the very first time, say in a while loop like this
while( isSorted( yourArray, 0 )
The if statement checks if the bounds of the array have been reached.
The else if statement will call itself recursively and break at any time when the condition becomes false
public static bool IsSorted(int[] arr, int index)
{
if (index >= arr.Length - 1)
{
return true;
}
else if ((arr[index] <= arr[ index + 1]) && IsSorted(arr, index + 1))
{
return true;
}
else
{
return false;
}
}
If the order doesn't matter(descending or ascending).
private bool IsSorted<T>(T[] values) where T:IComparable<T>
{
if (values == null || values.Length == 0) return true;
int sortOrder = 0;
for (int i = 0; i < values.Length - 1; i++)
{
int newSortOrder = values[i].CompareTo(values[i + 1]);
if (sortOrder == 0) sortOrder = newSortOrder;
if (newSortOrder != 0 && sortOrder != newSortOrder) return false;
}
return true;
}
The question that comes to my mind is "why"?
Is it to avoid re-sorting an already-sorted list? If yes, just use Timsort (standard in Python and Java). It's quite good at taking advantage of an array/list being already sorted, or almost sorted. Despite how good Timsort is at this, it's better to not sort inside a loop.
Another alternative is to use a datastructure that is innately sorted, like a treap, red-black tree or AVL tree. These are good alternatives to sorting inside a loop.
This might not be the fastest but it's the complete solution. Every value with index lower than i is checked against the current value at i. This is written in php but can easily be translated into c# or javascript
for ($i = 1; $i < $tot; $i++) {
for ($j = 0; $j <= $i; $j++) {
//Check all previous values with indexes lower than $i
if ($chekASCSort[$i - $j] > $chekASCSort[$i]) {
return false;
}
}
}
I feel like my implementation is a bit naive. Take notice of the variables min in max which have a rather small precision of +/- 0.0001. If I raise the precision any further the code is just too slow.
Algorithm
alt text http://img35.imageshack.us/img35/2060/toexponential.jpg
Code
private IDynamic ToExponential(Engine engine, Args args)
{
var x = engine.Context.ThisBinding.ToNumberPrimitive().Value;
if (double.IsNaN(x))
{
return new StringPrimitive("NaN");
}
var s = "";
if (x < 0)
{
s = "-";
x = -x;
}
if (double.IsPositiveInfinity(x))
{
return new StringPrimitive(s + "Infinity");
}
var f = args[0].ToNumberPrimitive().Value;
if (f < 0D || f > 20D)
{
throw new Exception("RangeError");
}
var m = "";
var c = "";
var d = "";
var e = 0D;
var n = 0D;
if (x == 0D)
{
f = 0D;
m = m.PadLeft((int)(f + 1D), '0');
e = 0;
}
else
{
if (!args[0].IsUndefined) // fractionDigits is supplied
{
var lower = (int)Math.Pow(10, f);
var upper = (int)Math.Pow(10, f + 1D);
var min = 0 - 0.0001;
var max = 0 + 0.0001;
for (int i = lower; i < upper; i++)
{
for (int j = (int)f; ; --j)
{
var result = i * Math.Pow(10, j - f) - x;
if (result > min && result < max)
{
n = i;
e = j;
goto Complete;
}
if (result <= 0)
{
break;
}
}
for (int j = (int)f + 1; ; j++)
{
var result = i * Math.Pow(10, j - f) - x;
if (result > min && result < max)
{
n = i;
e = j;
goto Complete;
}
if (result >= 0)
{
break;
}
}
}
}
else
{
var min = x - 0.0001;
var max = x + 0.0001;
// Scan for f where f >= 0
for (int i = 0; ; i++)
{
// 10 ^ f <= n < 10 ^ (f + 1)
var lower = (int)Math.Pow(10, i);
var upper = (int)Math.Pow(10, i + 1D);
for (int j = lower; j < upper; j++)
{
// n is not divisible by 10
if (j % 10 == 0)
{
continue;
}
// n must have f + 1 digits
var digits = 0;
var state = j;
while (state > 0)
{
state /= 10;
digits++;
}
if (digits != i + 1)
{
continue;
}
// Scan for e in both directions
for (int k = (int)i; ; --k)
{
var result = j * Math.Pow(10, k - i);
if (result > min && result < max)
{
f = i;
n = j;
e = k;
goto Complete;
}
if (result <= i)
{
break;
}
}
for (int k = (int)i + 1; ; k++)
{
var result = i * Math.Pow(10, k - i);
if (result > min && result < max)
{
f = i;
n = j;
e = k;
goto Complete;
}
if (result >= i)
{
break;
}
}
}
}
}
Complete:
m = n.ToString("G");
}
if (f != 0D)
{
m = m[0] + "." + m.Substring(1);
}
if (e == 0D)
{
c = "+";
d = "0";
}
else
{
if (e > 0D)
{
c = "+";
}
else
{
c = "-";
e = -e;
}
d = e.ToString("G");
}
m = m + "e" + c + d;
return new StringPrimitive(s + m);
}
Final Version
I swear someone must have hit me with a particularly large hammer back when I originally wrote this...
private IDynamic ToExponential(Engine engine, Args args)
{
var x = engine.Context.ThisBinding.ToNumberPrimitive().Value;
if (args[0].IsUndefined)
{
return new StringPrimitive(x.ToString("0.####################e+0"));
}
var f = args[0].ToNumberPrimitive().Value;
if (f < 0D || f > 20D)
{
RuntimeError.RangeError("The parameter fractionDigits must be between 0 and 20.");
}
return new StringPrimitive(x.ToString("0." + string.Empty.PadRight((int)f, '0') + "e+0"));
}
When you compute result = i * Math.Pow(10, j - f) - x you're trying to find where result is 0. Since j, f, and x are know, you just need to solve for i. Rather than writing a loop to find i, you can just say
i * Math.Pow(10, j - f) = x => i = x / Math.Pow(10, j - f)
The value you need should be either floor(i) or ceil(i).
Just out of curiosity, have you checked to see if ToString("e") gives you the correct answer?
I'd start by using Math.Log10, rather than a loop, to find the exponent.