Looking for a more elegant DO WHILE solution - c#

So I have some code centered around a do while loop.
string token;
var count = 0;
var checkDataLength= data.Length == 16;
do
{
count = 0;
token = GenerateToken(data, start, end);
if (checkDataLength)
{
if (Mod120Check(token))
{
count += 1;
}
}
if (IsCompliant(token))
{
count += 1;
}
}
while (count > 0);
return token;
Basically, I am generating a token and for this token to be valid, has to FAIL the Mod120Check and the IsCompliant check. I cannot change how those methods return the data.
While the above code works, I feel that its ugly and I was wondering if anyone had a better way of doing it?
Thanks

Try this:
do
{
token = GenerateToken(data, start, end);
}
while (checkDataLength && Mod120Check(token) || IsCompliant(token))
Just moving your conditions to the while.
(!) Notice that IsCompliant(token) will only be called if checkDataLength && Mod120Check(token) states false. It shouldn't cause any colateral effects, but it could, depending on what your IsCompliant method does.

You're right, it is ugly. You are using count in an unexpected way (it gets reset to zero at the top of every loop, and can go positive for two different reasons). When I see count, I expect something to start at zero and count up (or start high and count done). Try this instead:
Change var count = 0; to var goodEnough = false; up at the top
Remove the count = 0; statement
Change the two count += 1; statements to goodEnough = true;
Change the while (count > 0); to while (!goodEnough);
This emphasizes that you are starting in a "not good enough" state, and you will loop until some condition makes it good enough to continue past the loop.

Related

How to compare a fixed value against multiple values and find if any one fails to match

I have a fixed int value - 1050. I have around 50 dynamic values that I want to compare with the fixed value. So I compare it in a for loop. I have a public variable which I set as ok or notok depending on result. But my problem is that the value of the public variable is always the last value that I compared. Example, If I have the 20th dynamic value as 1000, it should return notok, but the value of the variable is always the last compared value. How do I set the variable to notok even if one/multiple of the values of dynamic variable doesnt match with fixed variable? I also display the total number of notok values in a listbox.
Here is what I have:
string result;
for(int i = 0; i < dynamicvalue.count; i++)
{
if(dynamicvalue[i] != setvalue)
{
result = "notok";
listBox1.Items.Add(result);
}
else
{
result = "ok";
}
}
To have "notok" if theres at least one not matching, one way to do it in plain code:
string result = "ok";
for(int i=0; i<dynamicvalue.count; ++i)
{
if(dynamicvalue[i] != setvalue)
{
result = "notok";
break;
}
}
You can use .Any() from Linq,
Determines whether any element of a sequence exists or satisfies a
condition.
string result = dynamicvalue.Any(x => x == setValue) ? "Ok" : "Not Ok";
If you want to use for loop without a break statement, you are just increasing the time complexity of your code.
I will never recommend it, but if you want you can try the below code
string result = "Ok";
bool flag = true;
//This for loop will iterate for n times.
for(int i = 0; i < dynamicvalue.Count; i++)
{
if(dynamicvalue[i] != setvalue && flag)
{
result = "Not Ok";
flag = false; //flag will help us to execute this block of code only once.
}
}
Perhaps the most performant way to answer this would be to keep your numbers in a HashSet instead (make dynamicvalue a HashSet<int>), then it's:
dynamicvalue.Contains(setvalue) ? "ok" : "notok"
A HashSet can much more quickly answer "do you contain this value?" than a list/array can
By the discussion going on in the comments I'm thinking that you want to go through all the elements in dynamicvalue and check all if any of them are ok or notok. If that is the case, you should turn result into an array. You get the last compared result because each time the cycle loops, the string gets assigned a new value all over again so the previous value gets discarded.
Is this what you want to do? I wrote it in c++
int setvalue = 1050;
int notok = 0;
int dynamicvalue[5] = {1, 2, 3, 1050, 4}; //for example
string result[5];
for (int i = 0; i < sizeof(dynamicvalue); i++){
if (dynamicvalue[i] != setvalue){
result[i] = "notok";
notok++; //to keep track of notok
}
else{
result[i] = "ok";
}
}
Afterwards if you cycle through the result array you will see that all the values were saved. I find it simpler to have an int variable to know how many times the result was notok
You forgot to get the actual value within dynamicvalue: your test should be if (dynamicvalue[i] != setvalue).
EDIT: And add a break; after the result="ok"; instruction to break the loop, too.
EDIT 2: An above answer gives the corrected code using a break.
I found a solution to this by reading #deminalla 's answer.
I added two more integers to work as counters and after the for loop I compare the values of these integers to get the final result.
Here's what I did:
string result;
int okcounter = 0;
int notokcounter = 0;
for(int i = 0; i < dynamicvalue.count; i++)
{
if(dynamicvalue[i] != setvalue)
{
notokcounter ++;
listBox1.Items.Add(notokcounter);
}
else
{
okcounter++;;
}
}
if(notokcounter >=1)
{
result = "notok";
}
else if(okcounter == dynamicvalue.count)
{
result = "ok";
}

Enumerable.Range(...).Any(...) outperforms a basic loop: Why?

I was adapting a simple prime-number generation one-liner from Scala to C# (mentioned in a comment on this blog by its author). I came up with the following:
int NextPrime(int from)
{
while(true)
{
n++;
if (!Enumerable.Range(2, (int)Math.Sqrt(n) - 1).Any((i) => n % i == 0))
return n;
}
}
It works, returning the same results I'd get from running the code referenced in the blog. In fact, it works fairly quickly. In LinqPad, it generated the 100,000th prime in about 1 second. Out of curiosity, I rewrote it without Enumerable.Range() and Any():
int NextPrimeB(int from)
{
while(true)
{
n++;
bool hasFactor = false;
for (int i = 2; i <= (int)Math.Sqrt(n); i++)
{
if (n % i == 0) hasFactor = true;
}
if (!hasFactor) return n;
}
}
Intuitively, I'd expect them to either run at the same speed, or even for the latter to run a little faster. In actuality, computing the same value (100,000th prime) with the second method, takes 12 seconds - It's a staggering difference.
So what's going on here? There must be fundamentally something extra happening in the second approach that's eating up CPU cycles, or some optimization going on the background of the Linq examples. Anybody know why?
For every iteration of the for loop, you are finding the square root of n. Cache it instead.
int root = (int)Math.Sqrt(n);
for (int i = 2; i <= root; i++)
And as other have mentioned, break the for loop as soon as you find a factor.
The LINQ version short circuits, your loop does not. By this I mean that when you have determined that a particular integer is in fact a factor the LINQ code stops, returns it, and then moves on. Your code keeps looping until it's done.
If you change the for to include that short circuit, you should see similar performance:
int NextPrimeB(int from)
{
while(true)
{
n++;
for (int i = 2; i <= (int)Math.Sqrt(n); i++)
{
if (n % i == 0) return n;;
}
}
}
It looks like this is the culprit:
for (int i = 2; i <= (int)Math.Sqrt(n); i++)
{
if (n % i == 0) hasFactor = true;
}
You should exit the loop once you find a factor:
if (n % i == 0){
hasFactor = true;
break;
}
And as other have pointed out, move the Math.Sqrt call outside the loop to avoid calling it each cycle.
Enumerable.Any takes an early out if the condition is successful while your loop does not.
The enumeration of source is stopped as soon as the result can be determined.
This is an example of a bad benchmark. Try modifying your loop and see the difference:
if (n % i == 0) { hasFactor = true; break; }
}
throw new InvalidOperationException("Cannot satisfy criteria.");
In the name of optimization, you can be a little more clever about this by avoiding even numbers after 2:
if (n % 2 != 0)
{
int quux = (int)Math.Sqrt(n);
for (int i = 3; i <= quux; i += 2)
{
if (n % i == 0) return n;
}
}
There are some other ways to optimize prime searches, but this is one of the easier to do and has a large payoff.
Edit: you may want to consider using (int)Math.Sqrt(n) + 1. FP functions + round-down could potentially cause you to miss a square of a large prime number.
At least part of the problem is the number of times Math.Sqrt is executed. In the LINQ query this is executed once but in the loop example it's executed N times. Try pulling that out into a local and reprofiling the application. That will give you a more representative break down
int limit = (int)Math.Sqrt(n);
for (int i = 2; i <= limit; i++)

Messagebox If Loop

I have a simple message box pop up when a variable is achieved. It spirals into infinity since I have no stopper. Perhaps it's just my inability to figure out where the stopper is to be placed, but it doesn't seem to halt no matter my solution.
if (number == 10)
{
MessageBox.Show("Woot!");
}
Without more code, you can either use a break (as it sounds like you are using a loop), or set your number to something other than 10
while(switchstatement)
{
...logic...
if(number == 10)
{
MessageBox.Show("woot");
break;
}
...more logic...
}
Or, you can set the switch that kills your loop
while(switchstatement)
{
...logic...
if(number == 10)
{
MessageBox.Show("woot");
switchstatement = false;
}
...more logic...
}
That is based off of limited code...so you may have to provide more code if this is not correct.
You are using a variable but i don't see where you set the value so i assume that you never change it in the loop. Hence you are in an infinite loop.
You could use a for-loop instead
for(int number = 0; number < 10; number++)
{
MessageBox.Show("Woot!");
}
or in a while
int number = 0;
while(number++ < 10)
{
MessageBox.Show("Woot!");
}
C# Increment Int
++ Operator (C# Reference)

c# do while ( Two condition )

im trying to do a loop when either one of the two conditions are met for ten times..
This involves a box of bottles either Sugar or Salt where the person must pick randomly two bottles. He/She will stop picking when it was choosen 10 times... It doesnt seem to work.
int sugar = 0;
int salt = 0;
do
bottle1.choose
bottle2.choose
{
if ((bottle1 = 'Sugar') && (bottle2 = 'Sugar'))
{
Console.Write("Sugar");
Sugar++;
}
else if (bottle1 = 'Salt') && bottle1 = 'Salt')
{
Salt++;
Console.Write("Salt");
}
else
{
Console.Write("None");
}
}
while ((Salt < 10) || Sugar < 10);
Currently you'll keep looping while either of them have been chosen 10 times. I suspect you want:
while (Salt < 10 && Sugar < 10)
Having said that, the code you've given is clearly pseudo-code anyway - it wouldn't compile for various reasons. If you could post a short but complete program demonstrating the problem, we could give an answer with more confidence. Likewise, saying "It doesn't seem to work" is akin to going to the doctor and expecting a diagnosis from "I'm not feeling well." More details please...
You declare salt and suger at the start here, but inside the loop you use Salt and Sugar. Are they properties you have defined somewhere else? Are you sure they do what you expect them to? Have you tried using the variables inside the loop instead of the properties, so your code looks like this?
int sugar = 0;
int salt = 0;
do
bottle1.choose
bottle2.choose
{
if ((bottle1 = 'Sugar') && (bottle2 = 'Sugar'))
{
Console.Write("Sugar");
sugar++;
}
else if (bottle1 = 'Salt') && bottle1 = 'Salt')
{
salt++;
Console.Write("Salt");
}
else
{
Console.Write("None");
}
}
while ((salt < 10) || sugar < 10);
Your parentheses are uneven on your if and while statements, your variable names mismatch, your bottle.choose statements must also be under the do-while loop, and you're using an assignment operator = on your conditions:
int sugar = 0;
int salt = 0;
do {
bottle1.choose();
bottle2.choose();
if ((bottle1 == 'Sugar') && (bottle2 == 'Sugar'))
{
Console.Write("Sugar");
sugar++;
}
else if ((bottle1 == 'Salt') && (bottle1 == 'Salt'))
{
salt++;
Console.Write("Salt");
}
else
{
Console.Write("None");
}
} while ((salt < 10) || (sugar < 10));
I can't tell from your question if you want to stop if EITHER salt or sugar has been chosen, or if you want to stop when 10 total items have been chosen.
If you're looking for the former, then Jon Skeet's answer will do it for you.
If you're looking for the latter, then I think you're looking for the following:
while (Salt + Sugar < 10);
If I understand the code correctly, both bottles must be of the same taste to do the increment.
First error seem to be the test condition for the "Salt", you check twice for the "bottle1", test should be :
else if (bottle1 = 'Salt') && bottle2 = 'Salt')
Your Variables names are mismatching, again you may take the condition for selection of both salt and sugar in the "while statement" itself.

Interpolation in c# - performance problem

I need to resample big sets of data (few hundred spectra, each containing few thousand points) using simple linear interpolation.
I have created interpolation method in C# but it seems to be really slow for huge datasets.
How can I improve the performance of this code?
public static List<double> interpolate(IList<double> xItems, IList<double> yItems, IList<double> breaks)
{
double[] interpolated = new double[breaks.Count];
int id = 1;
int x = 0;
while(breaks[x] < xItems[0])
{
interpolated[x] = yItems[0];
x++;
}
double p, w;
// left border case - uphold the value
for (int i = x; i < breaks.Count; i++)
{
while (breaks[i] > xItems[id])
{
id++;
if (id > xItems.Count - 1)
{
id = xItems.Count - 1;
break;
}
}
System.Diagnostics.Debug.WriteLine(string.Format("i: {0}, id {1}", i, id));
if (id <= xItems.Count - 1)
{
if (id == xItems.Count - 1 && breaks[i] > xItems[id])
{
interpolated[i] = yItems[yItems.Count - 1];
}
else
{
w = xItems[id] - xItems[id - 1];
p = (breaks[i] - xItems[id - 1]) / w;
interpolated[i] = yItems[id - 1] + p * (yItems[id] - yItems[id - 1]);
}
}
else // right border case - uphold the value
{
interpolated[i] = yItems[yItems.Count - 1];
}
}
return interpolated.ToList();
}
Edit
Thanks, guys, for all your responses. What I wanted to achieve, when I wrote this questions, were some general ideas where I could find some areas to improve the performance. I haven't expected any ready solutions, only some ideas. And you gave me what I wanted, thanks!
Before writing this question I thought about rewriting this code in C++ but after reading comments to Will's asnwer it seems that the gain can be less than I expected.
Also, the code is so simple, that there are no mighty code-tricks to use here. Thanks to Petar for his attempt to optimize the code
It seems that all reduces the problem to finding good profiler and checking every line and soubroutine and trying to optimize that.
Thank you again for all responses and taking your part in this discussion!
public static List<double> Interpolate(IList<double> xItems, IList<double> yItems, IList<double> breaks)
{
var a = xItems.ToArray();
var b = yItems.ToArray();
var aLimit = a.Length - 1;
var bLimit = b.Length - 1;
var interpolated = new double[breaks.Count];
var total = 0;
var initialValue = a[0];
while (breaks[total] < initialValue)
{
total++;
}
Array.Copy(b, 0, interpolated, 0, total);
int id = 1;
for (int i = total; i < breaks.Count; i++)
{
var breakValue = breaks[i];
while (breakValue > a[id])
{
id++;
if (id > aLimit)
{
id = aLimit;
break;
}
}
double value = b[bLimit];
if (id <= aLimit)
{
var currentValue = a[id];
var previousValue = a[id - 1];
if (id != aLimit || breakValue <= currentValue)
{
var w = currentValue - previousValue;
var p = (breakValue - previousValue) / w;
value = b[id - 1] + p * (b[id] - b[id - 1]);
}
}
interpolated[i] = value;
}
return interpolated.ToList();
}
I've cached some (const) values and used Array.Copy, but I think these are micro optimization that are already made by the compiler in Release mode. However You can try this version and see if it will beat the original version of the code.
Instead of
interpolated.ToList()
which copies the whole array, you compute the interpolated values directly in the final list (or return that array instead). Especially if the array/List is big enough to qualify for the large object heap.
Unlike the ordinary heap, the LOH is not compacted by the GC, which means that short lived large objects are far more harmful than small ones.
Then again: 7000 doubles are approx. 56'000 bytes which is below the large object threshold of 85'000 bytes (1).
Looks to me you've created an O(n^2) algorithm. You are searching for the interval, that's O(n), then probably apply it n times. You'll get a quick and cheap speed-up by taking advantage of the fact that the items are already ordered in the list. Use BinarySearch(), that's O(log(n)).
If still necessary, you should be able to do something speedier with the outer loop, what ever interval you found previously should make it easier to find the next one. But that code isn't in your snippet.
I'd say profile the code and see where it spends its time, then you have somewhere to focus on.
ANTS is popular, but Equatec is free I think.
few suggestions,
as others suggested, use profiler to understand better where time is used.
the loop
while (breaks[x] < xItems[0])
could cause exception if x grows bigger than number of items in "breaks" list. You should use something like
while (x < breaks.Count && breaks[x] < xItems[0])
But you might not need that loop at all. Why treat the first item as special case, just start with id=0 and handle the first point in for(i) loop. I understand that id might start from 0 in this case, and [id-1] would be negative index, but see if you can do something there.
If you want to optimize for speed then you sacrifice memory size, and vice versa. You cannot usually have both, except if you make really clever algorithm. In this case, it would mean to calculate as much as you can outside loops, store those values in variables (extra memory) and use them later. For example, instead of always saying:
id = xItems.Count - 1;
You could say:
int lastXItemsIndex = xItems.Count-1;
...
id = lastXItemsIndex;
This is the same suggestion as Petar Petrov did with aLimit, bLimit....
next point, your loop (or the one Petar Petrov suggested):
while (breaks[i] > xItems[id])
{
id++;
if (id > xItems.Count - 1)
{
id = xItems.Count - 1;
break;
}
}
could probably be reduced to:
double currentBreak = breaks[i];
while (id <= lastXIndex && currentBreak > xItems[id]) id++;
and the last point I would add is to check if there is some property in your samples that is special for your problem. For example if xItems represent time, and you are sampling in regular intervals, then
w = xItems[id] - xItems[id - 1];
is constant, and you do not have to calculate it every time in the loop.
This is probably not often the case, but maybe your problem has some other property which you could use to improve performance.
Another idea is this: maybe you do not need double precision, "float" is probably faster because it is smaller.
Good luck
System.Diagnostics.Debug.WriteLine(string.Format("i: {0}, id {1}", i, id));
I hope it's release build without DEBUG defined?
Otherwise, it might depend on what exactly are those IList parameters. May be useful to store Count value instead of accessing property every time.
This is the kind of problem where you need to move over to native code.

Categories