Using variable value as for loop index - c#

I have a code which contains 2 for loops:
for (int count = 0; list_Level[count] < list_Level[list_Level.Count]; count++)
{
for (int a = 0; list_Level[a] < Initial_Lvl; a++)
{
var dOpt = new DataGridObjectOpt();
double Closest_Goallvl = list_Level.Aggregate((x, y) => Math.Abs(x - Initial_Lvl) < Math.Abs(y - Initial_Lvl) ? x : y);
dOpt.ImageSource = new Uri(filePaths[a], UriKind.RelativeOrAbsolute);
dOpt.Level_Index = Initial_Lvl;
dOpt.Level_Goal = goallvl;
dOpt.Stage = 1;
LOpt_Temp.Add(dOpt);
}
count = a;
int best_Profit_Ind = LOpt_Temp.FindIndex(x => x.TotalCost == LOpt_Temp.Max(y => y.TotalCost));
LOpt.Add(LOpt_Temp[best_Profit_Ind]);
dataGridOpt.ItemsSource = LOpt;
}
I want the loops to begin at 0, however once the inner loop ends for the first time and ends at a value of a, i want the outer loop to begin from this place now.
For example, first loop begins at 0, inner loop exits when a=6. Now i want count to start for 6 and not 1.
Thank you.

As #dcg mentioned, do count+=a-1 before iterating again. As #dlatikay mentioned, you could run into IndexOutOfRangeException. To avoid that, add and condition in the outer for loop. So that your final code looks something like this:
for (int count = 0; list_Level[count] < list_Level[list_Level.Count] && count < list_Level.Count; count++)
{
for (int a = 0; list_Level[a] < Initial_Lvl; a++)
{
//Your code
}
count+=a-1
//Your code
}
Notice the middle condition in the outer for loop. Hope it helps.

First of all
list_Level[count] < list_Level[list_Level.Count]
by using this condition you will get IndexOutOfRangeException you should use
list_Level[count] < list_Level[list_Level.Count - 1]
something like that.
on the other hand this may help you:
for (int count = 0; list_Level[count] < list_Level[list_Level.Count - 1] && count < list_Level.Count; count++){
for (int a = 0; list_Level[a] < Initial_Lvl; a++)
{
//Your code
}
count = a-1;
if(count >= list_Level.Count)
{
break;
}
//Your code
}

Related

How can I skip loop for first and last element of array and set them to constant value?

I would like the loop to start from the second element and to end before the last one.
So that I can set the first and last one to constant value.
for (int i = 0; i < n; i++) {
for (int j = 0; j < 3; j++) {
Console.Write($"A[{i},{j}] = ");
tab[i, j] = double.Parse(Console.ReadLine());
}
}
You can use LINQ simply:
var result = yourArray.Skip(1).SkipLast(1).Prepend(theConstValue)
.Append(theConstValue).ToArray();
The Prepend, Adds a value to the beginning of the sequence.
The Append, Appends a value to the end of the sequence.
Why don't do something like that?
for (int i = 1; i < n - 1; i++)
{
//your code
}
Let the loop start at element 1 and end it one earlier

Can I put a specific condition statement to the increment in a for loop?

For example:
for (int i = 0; i < 9; i++ && (a specific condition to the incremented variable))
This would be use to stall a loop in a fake infinity until the said condition would be reached.
This point of this would be to have the loop still continue to do it's operation while stopping the increment of the i variable until a condition is met. For example if('another varible' < 9) then i can have it's normal increment. In other case if the condition is not met the i would not increment but the loop would still proceed the instruction one by one.
You can implement
for (int i = 0; i < 9; i++ && (a specific condition to the incremented variable))
as
for (int i = 0; i < 9; i = (a specific condition to the incremented variable) ? i + 1 : i)
but this goes against the general purpose and intention of a for loop. It would just confuse your testers, reviewers and fellow coders.
And, not unimprortant, it would make the CLR optimizer give up and slow down myArray[i] by adding a range check each time.
I think what you're looking at is something like this:
var counter = 0;
var otherCondition = 15;
while (counter < 9)
{
if (otherCondition < 9)
{
counter++;
}
// Do other stuff
}
You're starting the counter at 0 just like in the for loop, and terminates when it reaches 9. But increments only when the other condition is met.
I think the appropriate flow of control structure is a nested loop, with the inner loop "stalling" to infinity.
for (int i = 0; i < 9; i++ )
{
do
{
Foo();
} while (!condition)
}
What about i += (true/false) ? 1 : 0?
for (int i = 0; i < 9; i += (a specific condition to the incremented variable) ? 1 : 0)
For example:
var n = 0;
for (int i = 0; i < 9; i += (n++%2==0) ? 1 : 0) {
Console.WriteLine(i);
}
Having said that it makes the code unnecessarily harder to read and to understand your intention.
The following two examples are much clearer.
int met = 0;
while(true)
{
if(a specific condition to the incremented variable) met++;
if(met >= 9) break;
}
or
var met = 0;
while( met < 9 )
{
if(a specific condition to the incremented variable) met++;
}
I think while will be more helpful in this case:
int i = 0;
while (i < 9)
{
if (condition)
i++;
}

c# split string in 2. letter by letter

I need split my string in 2, one letter to each variable.
Example: string = "ABCDEFGHIJ"
name1: ACEGI
name2: BDFHJ
I done so far:
var builderM = new StringBuilder();
var builderK = new StringBuilder();
for (int i = 0; i < s.Length; i++)
{
builderM.Append(s[i]);
builderK.Append(s[i++]);
}
txtM.Text = builderM.ToString();
txtK.Text = builderK.ToString();
But its showing same text in the 2.
you should use ++i instead of i++
for (int i = 0; i < s.Length; i++)
{
builderM.Append(s[i]);
if(i + 1 < s.Length) // to prevent IOR exception when count is odd.
builderK.Append(s[++i]); // pre increment.
}
the reason is that i++ is post incremented. that means i gets incremented after the expression therefor s[i++] will give you same item as s[i].
Another approach would be to use LINQ to filter odd and even indices into two strings, something like:
var even = new string(input.Where((c, idx) => idx % 2 == 0).ToArray());
var odd = new string(input.Where((c, idx) => idx % 2 != 0).ToArray());
If performance is not an issue, you can use LINQ:
var name1 = String.Join(String.Empty, str.Where((v, i) => i % 2 == 0));
var name2 = String.Join(String.Empty, str.Where((v, i) => i % 2 == 1));
You can also use the modulus operator (%) to determine if the index is even or odd, and put the even indexes in the first array and the odd indexes in the second one:
for (int i = 0; i < s.Length; i++)
{
if (i % 2 == 0) builderM.Append(s[i]);
else builderK.Append(s[i]);
}
If you'd rather increment the i inside the for body, you have to repeat the check against s.Length (as we do in the for condition). Also, you will need to either move the post-increment to the previous line (so that i is incremented in time), or use a pre-increment:
// Move post-increment to previous line example:
for (int i = 0; i < s.Length; i++)
{
builderM.Append(s[i++]);
if (i < s.Length) builderK.Append(s[i]);
}
// Use a pre-increment example:
for (int i = 0; i < s.Length; i++)
{
builderM.Append(s[i]);
if (++i < s.Length) builderK.Append(s[i]);
}

C# : Find the largest palindromic number made from product of 3-digit numbers

I'm writing a program to find the largest palindromic number made from product of 3-digit numbers. Firstly,i Create a method which has ability to check if it is a palindromic number. Here is my code :
static int check(string input_number)
{
for (int i = 0; i < input_number.Length/2; i++)
if (input_number[i] != input_number[input_number.Length - i])
return 0;
return 1;
}
After that, it's my main code:
static void Main(string[] args)
{
int k = 0;
for (int i = 0; i < 999; i++)
for (int j = 0; j < 999; j++)
{
k = i * j;
if (check(k.ToString()) == 1)
Console.Write(k + " ");
}
}
But when it has a problem that the length of input_number is zero. So my code doesn't run right way. What can I do to solve the length of input_number?
You have a few bugs in your code:
1. 3-digit-numbers range from `100` to `999`, not from `0` to `998` as your loops currently do.
So your Main method should look like this:
static void Main(string[] args)
{
int k = 0;
for (int i = 100; i <= 999; i++)
for (int j = 100; j <= 999; j++)
{
k = i * j;
if (check(k.ToString()) == 1)
Console.Write(k + " ");
}
}
Now all pairs of three digit numbers are checked. But to improve performance you can let j start at i, because you already checked e.g. 213 * 416 and don't need to check 416 * 213 anymore:
for (int i = 100; i <= 999; i++)
for (int j = i; j <= 999; j++) // start at i
And since you want to find the largest, you may want to start at the other end:
for (int i = 999; i >= 100; i--)
for (int j = 999; j >= 100; j--)
But that still does not guarantee that the first result will be the largest. You need to collect the result and sort them. Here is my LINQ suggestion for your Main:
var results = from i in Enumerable.Range(100, 900)
from j in Enumerable.Range(i, 1000-i)
let k = i * j
where (check(k.ToString() == 1)
orderby k descending
select new {i, j, k};
var highestResult = results.FirstOrDefault();
if (highestResult == null)
Console.WriteLine("There are no palindromes!");
else
Console.WriteLine($"The highest palindrome is {highestResult.i} * {highestResult.j} = {highestResult.k}");
2. Your palindrome-check is broken
You compare the character at index i to input_number[input_number.Length - i], which will throw an IndexOutOfRangeException for i = 0. Strings are zero-based index, so index of the last character is Length-1. So change the line to
if (input_number[i] != input_number[input_number.Length - i - 1])
Finally, I suggest to make the check method of return type bool instead of int:
static bool check(string input_number)
{
for (int i = 0; i < input_number.Length/2; i++)
if (input_number[i] != input_number[input_number.Length - i - 1])
return false;
return true;
}
This seems more natural to me.
You can use method below. Because you are trying to find the largest number you start from 999 and head backwards, do multiplication and check if its palindrome.
private void FindProduct()
{
var numbers = new List<int>();
for (int i = 999; i > 99; i--)
{
for (int j = 999; j > 99; j--)
{
var product = i * j;
var productString = product.ToString();
var reversed = product.Reverse();
if (product == reversed)
{
numbers.Add(product);
}
}
}
Console.WriteLine(numbers.Max());
}

Does C# have a nice way of iterating through every integer in a range, minus 1 of them?

The situation I have is like
// radius is an int[]
for ( int i = 0; i < radius.length; ++i )
{
for ( int j = 0; j < radius.length; ++j )
{
// do some stuff
}
}
Except I actually want j to go through the range 0-radius.length, but skip over i:
{0,1,..., i-1, i+1, ..., radius.length}
I'm wondering if there's a way to do this that is compact, elegant, efficient, readable, and maybe even correct.
How I planned to do it was
for ( int i = 0; i < radius.length; ++i )
{
for ( int j = 0; j < radius.length; )
{
// do some stuff
j += j != i ? 1 : 2;
}
}
Perhaps you may consider of using continue:
// radius is an int[]
for (int i = 0; i < radius.length; ++i)
for (int j = 0; j < radius.length; ++j)
{
if (i == j)
continue;
// do some stuff
}
That is one of the simplest I could think of. It is representing exactly what you want as an independent block.
If you want to be more "compact" (with the cost of "little" readability), you may consider of using multi-variables single loop instead of single variable nested loops:
int r = radius.Length;
for (i = 0, j = 0; i < r - 1 || j < r; j++) {
i += j == r ? 1 : 0;
j %= r;
if (i == j)
continue;
//do stuff
}
Or another alternative without using continue would be (suggested by Millie Smith):
for (int i = 0; i < radius.length; ++i)
for (int j = 0; j < radius.length; ++j)
if (i != j) {
// do some stuff
}
This way, at least you could get rid of all the curly brackets but on if.
Note: But I personally think that your solution (using j += j != i ? 1 : 2;) is already quite compact, elegant, efficient, readable! It is quite hard to "beat"! ;)
Edit:
"quite hard to beat..." except that the original solution contains a single error (as identified by Ivan Stoev) when i == 0 && j == 0.
To make it right, a modified solution would be something like this:
for ( int i = 0; i < radius.length; ++i )
for ( int j = 0; j < radius.length; )
{
// do some stuff
j += j != i || i + j == 0 ? 1 : 2; //i + j == 0 condition added
}
How about this?
var query =
from i in Enumerable.Range(0, radius.Length)
from j in Enumerable.Range(0, radius.Length)
where i != j
select new { i, j };
foreach (var x in query)
{
/* Do stuff with x.i && x.j */
}
I think that's fairly neat.
You could build it into the iterator:
for (int i = 0; i < radius.length; i++)
{
for (int j = i == 0 ? 1 : 0; j < radius.length; j += j == i - 1 ? 2 : 1)
{
//-Do something
}
}
Edit:
Updated inner loop initializer to: int j = i == 0 ? 1 : 0
Another variant is using foreach loop and Range method:
foreach(var i in Enumerable.Range(0,radius.length))
{
foreach(var j in Enumerable.Range(0,radius.length).Where(r => r != i))
{
// do some stuff
}
}
Or you can even put it in one foreach loop, but expression will be not very compact:
var range = Enumerable.Range(0, radius.length)
.SelectMany(i => Enumerable.Range(0, Enumerable.Range(0, radius.length)
.Where(r => r != i))
.Select(j => new {i, j}));
foreach (var value in range)
{
value.i //i value
value.j //j value
}
The orthodox solution as demonstrated above is the continue statement, but if the if keyword is taboo at your workplace, an alternative is to split the loop in two:
for ( int j = 0; j < i; ++j )
{
}
for ( int j = i+1; j < radius.Length; ++j )
{
}

Categories