For loop took too much time if 20000+ users hit - c#

Here I have 2 datatables, I want to make some changes runtime, so I used 2 for loops. But when user hit is huge like 20k+, system get down. It took more than 2 minutes every hit, I want to optimize, can anyone help on this?
Datatable BuybackResponse = ResourceCenterDAL.GetBuyBack(2);;
Datatable dt = ResourceCenterDAL.GetBuyBack(4);;
if (BuybackResponse.Count > 0)
{
for (int i = 0; i < dt.Rows.Count; i++)
{
for (int k = 0; k < BuybackResponse.Count; k++)
{
var Exch = !string.IsNullOrEmpty(Convert.ToString(dt.Rows[i]["Nsetradingsymbol"])) ? "NSE" : "BSE";
//if (Exch == BuyBackExchangeMapping[Convert.ToInt32(BuybackResponse[k]["Exchange"])] &&
if (BuybackResponse[k]["ProductCode"].Trim().ToLower() == Convert.ToString(dt.Rows[i]["Nsetradingsymbol"]).Trim().ToLower() ||
BuybackResponse[k]["ProductCode"].Trim().ToLower() == Convert.ToString(dt.Rows[i]["Bsetradingsymbol"]).Trim().ToLower())
{
if (!Convert.ToString(dt.Rows[i]["isBuyBack"]).Trim().ToLower().Equals("y"))
dt.Rows[i]["isBuyBack"] = "Y";
dt.Rows[i]["productcode"] = BuybackResponse[k]["ProductCode"];
BBcount++;
}
else
{
if (string.IsNullOrEmpty(Convert.ToString(dt.Rows[i]["isBuyBack"])))
dt.Rows[i]["isBuyBack"] = "N";
}
}
if (BBcount.Equals(BuybackResponse.Count)) { break; }
}
}

Related

How to solve time constraint with coding challenge

I was doing a coding test (for practice) that went something like this:
Input is a string with |'s and *'s.
E.g. **|*|*|**|***
Implement the function:
List<int> countItems(string line, List<int> startLocations, List<int> endLocations)
Count the number of * characters that are between an opening and closing pair of | characters.
Where the 2 locations are arrays with the start and end locations (indices) to consider withing the string line.
For example if line = *|*|* and startLocations = [1] and endLocations = [3] it means
I need to check the substring *|*.
And since there is only 1 pipe, the result is zero.
The location values seemed to be 1-based and not 0-based for some reason.
If the range was 1 and 5, for example, the result would be 1 because there is only 1 * between pipes.
The code I came up with that did manage to solve about half the test cases is as follows:
List<int> countItems(string line, List<int> startLocations, List<int> endLocations)
{
var results = new List<int>();
if (String.IsNullOrWhiteSpace(line) || startLocations.Count == 0)
{
return results;
}
for (var i = 0; i < startLocations.Count; i++)
{
var startIndex = startLocations[i] - 1;
var endIndex = endLocations[i] - 1;
var start = false;
var total = 0;
var tempTotal = 0;
for (var j = startIndex; j < endIndex; j++)
{
if (!start && line[j] == '|')
{
start = true;
tempTotal = 0;
}
else if (start && line[j] == '*')
{
tempTotal++;
}
else if (line[j] == '|')
{
total += tempTotal;
tempTotal = 0;
}
}
if (line[endIndex] == '|')
{
total += tempTotal;
}
results.Add(total);
}
return results;
}
All the test cases either passed or failed because it ran out of time.
The error said it exceeded a time of 3 seconds.
Now I couldn't see the actual data being passed into the tests, so I'm not able to test it more.
But I suspect the solution was some kind of temporary list or dictionary so as to only iterate over the string 1 time instead of many times as in my code.
I want to learn what kind of solution to use in cases like this, but not really sure if this is a common type of question where the solution has some kind of name or common concept.
I would appreciate any obvious pointers to solving this type of question or even links to similar programming challenges where I can practice more.
In this case I think the best option would be to use stack theory.
It is a variation of the parenthesis balancing problem. You can find more about it here
Article parenthesis balancing problem
I managed to redo the test and I found the answer and problem type.
This is a "plates between candles" type of problem.
I was trying to solve it myself but almost ran out of time and eventually just copy/pasted an answer I found.
This was a practice run, not an actual test or application.
This was the solution that worked... I'll be studying it to better understand it...
List<int> numberOfItems(string s, List<int> startIndices, List<int> endIndices)
{
int q = startIndices.Count;
int l = s.Length;
for (var i = 0; i < startIndices.Count; i++)
{
startIndices[i]--;
endIndices[i]--;
}
var ans = new List<int>();
var prev = new int[l];
var next = new int[l];
var preSum = new int[l];
int p = -1, nxt = -1;
// calculating prev candle up to this index.
for (int i = 0; i < l; i++)
{
if (s[i] == '|')
{
p = i;
}
prev[i] = p;
}
//Calculating next candle from this index.
for (int i = l - 1; i >= 0; i--)
{
if (s[i] == '|')
{
nxt = i;
}
next[i] = nxt;
}
int c = 0;
// calculating the number of stars between these indices.
for (int i = 0; i < l; i++)
{
if (s[i] == '*')
{
c++;
}
preSum[i] = c;
}
// calculating ans.
for (int k = 0; k < q; k++)
{
int i = startIndices[k];
int j = endIndices[k];
int right = prev[j];// position of left candle.
int left = next[i];// position of right candle.
//cout<<right<<left;
if (left == -1 || right == -1 || left > right)
{
ans.Add(0);
}
else
{
ans.Add(preSum[right] - preSum[left]);
}
}
return ans;
}

Cross Search generate char Matrix

I am trying to create a word search puzzle matrix, this is the code I have,
static void PlaceWords(List<string> words)
{
Random rn = new Random();
foreach (string p in words)
{
String s = p.Trim();
bool placed = false;
while (placed == false)
{
int nRow = rn.Next(0,10);
int nCol = rn.Next(0,10);
int nDirX = 0;
int nDirY = 0;
while (nDirX == 0 && nDirY == 0)
{
nDirX = rn.Next(3) - 1;
nDirY = rn.Next(3) - 1;
}
placed = PlaceWord(s.ToUpper(), nRow, nCol, nDirX, nDirY);
}
}
}
static bool PlaceWord(string s, int nRow, int nCol, int nDirX, int nDirY)
{
bool placed = false;
int LetterNb = s.Length;
int I = nRow;
int J = nCol;
if (MatriceIndice[nRow, nCol] == 0)
{
placed = true;
for (int i = 0; i < s.Length-1; i++)
{
I += nDirX;
J += nDirY;
if (I < 10 && I>0 && J < 10 && J>0)
{
if (MatriceIndice[I, J] == 0)
placed = placed && true;
else
placed = placed && false;
}
else
{
return false;
}
}
}
else
{
return false;
}
if(placed==true)
{
int placeI = nRow;
int placeJ = nCol;
for (int i = 0; i < s.Length - 1; i++)
{
placeI += nDirX;
placeJ += nDirY;
MatriceIndice[placeI,placeJ] = 1;
MatriceChars[placeJ, placeJ] = s[i];
}
}
return placed;
}
However it seems like it is an infinite loop. I am trying to add the code in a 1010 char matrix linked to a 1010 int matrix initially filled with 0 where I change the cases to 1 if the word is added to the matrix. How should I fix the code?
There are several errors. First,
MatriceChars[placeJ, placeJ] = s[i];
should be
MatriceChars[placeI, placeJ] = s[i];
Second,
for (int i = 0; i < s.Length - 1; i++)
(two occurrences) should be
for (int i = 0; i < s.Length; i++)
(You do want all the letters in the words, right?)
Third, when testing indices, you should use I >= 0, not I > 0, as the matrix indices start at 0.
However, the main logic of the code seems to work, but if you try to place too many words, you will indeed enter an infinite loop, since it just keeps trying and failing to place words that can never fit.

Find inconsistent and consecutive objects from List in C#

I'm having trouble with getting a consecutive and nonconsecutive number from list. I'm sure it's pretty simple, but i can't get it.
If consecutiveNum=2, then if result from before last and last is equal, i need to throw an exception.
If nonConsecutiveNum=4, then if from 10 pieces there are 4 with same result, i need to throw an exception.
I'm trying with nested loops and couple checks, but i didn't succeeded at all. Same is for both cases, i tried a couple solutions with System.LINQ, but again i don't get the result i need.
Thanks in advance to all of you!
int consecutiveNum = 2;
int nonConsecutiveNum = 4;
int counter = 1;
var sensInfo = new ResultInfo()
{
Product = CurrentLot.Info.Product,
Result = code
};
if (consecutiveNum > 0)
{
for (int i = ListSensors.Count + 1; i >= 0; i--)
{
if (sensInfo.Result == ListSensors[i].Result)
{
counter++;
if (counter >= consecutiveNum)
{
throw new Exception("Consecutive num");
}
}
}
}
if (nonConsecutiveNum > 0)
{
for (int i = 0; i < ListSensors.Count; i++)
{
for (int j = i + 2; j < ListSensors.Count - 2; j++)
{
if (ListSensors[i].Result == ListSensors[i+1].Result)
continue;
if (ListSensors[i].Result == ListSensors[j].Result)
{
counter++;
if (counter >= nonConsecutiveNum)
{
throw new Exception("NonConsecutive num");
}
}
}
}
}
// consecutiveNum
for (int i = ListSensors.Count - 1; i >= 0; i--)
{
if (sensInfo.Result == ListSensors[i].Result)
{
counter++;
if (counter >= consecutiveNum)
{
throw new Exception("Consecutive num");
}
}
else
{
counter = 1;
}
}
// nonConsecutiveNum
IDictionary<int, int> resultCountDictionary = new Dictionary<int,int>();
foreach (var listSensor in ListSensors)
{
if (resultCountDictionary.ContainsKey(listSensor.Result))
{
resultCountDictionary[listSensor.Result] = resultCountDictionary[listSensor.Result] + 1;
if (resultCountDictionary[listSensor.Result] >= nonConsecutiveNum)
{
throw new Exception();
}
}
else
{
resultCountDictionary.Add(listSensor.Result, 1);
}
}
Consecutive:
Using MoreLinq's Window function:
ListSensors.Window(consecutiveNum).Any(x => x.Distinct().Count() == 1);
Nonconsecutive:
ListSensors.Any(x => ListSensors.Count(s => s == x) >= nonConsecutiveNum);

How to check if row contains "0" or is empty in DataGridView before doing calculations, and delete this row

guys!
I need some help with my code.
So, the story is, I had a task to do a form application, where user could count entropy of discrete random variables. He types events and probabilities, and program calculates the entropy.
So I used DataGridView, a button and a TextBox. I've made everything, including restriction, such as "sum of all probabilities must be equal to 1".
But the thing I can't do is - the program itself must delete or ignore rows, which contain "0" or rows, which are empty (because formula of entropy contains log of a number, and log of 0 is an infinity, that's why program will output "NaN - not a number").
The main code is located in "button".
Here is a snippet of it:
for (int z = dataGridView1.Rows.Count - 1; z >= 0; z--)
{
if (dataGridView1[1, z].Value == null)
{
dataGridView1.Rows.Remove(dataGridView1.Rows[z]);
}
else if (dataGridView1[1, z].Value == "0")
{ dataGridView1.Rows.Remove(dataGridView1.Rows[z]);}
}
The only thing I get after this code, is an error saying, that it can't delete a new "transmitted" (don't know how to translate that to English) line.
This is the whole code, located in "button":
int counter = 1;
for (int i = 0; i < dataGridView1.RowCount - 1; i++)
{
dataGridView1[0, i].Value = counter++;
}
double X = 0;
double A = 1;
for (int i = 0; i < dataGridView1.RowCount; i++)
{
X += Convert.ToDouble(dataGridView1[1, i].Value);
}
if (X < A && X > A)
{
MessageBox.Show("Cумма вероятностей меньше или больше 1, введите другие значения вероятностей", "АШИППКА", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
double H = 0;
for (int i = 0; i < dataGridView1.RowCount - 1; i++)
{
for (int z = dataGridView1.Rows.Count - 1; z >= 0; z--)
{
if (dataGridView1[1, z].Value == null)
{
dataGridView1.Rows.Remove(dataGridView1.Rows[z]);
}
else if (dataGridView1[1, z].Value == "0")
{ dataGridView1.Rows.Remove(dataGridView1.Rows[z]);}
}
double p = Convert.ToDouble(dataGridView1[1, i].Value);
H += p * Math.Log(p, 2.0);
}
textBox1.Text = Convert.ToString(-H);
}
Sorry for my bad english, it's not my native language, that's why there are a lot of mistakes. Please, ask, if you don't understand something.
Help me, please.
Elaborating on comment above.
If your DataGridView uses a DataTable or a BindingSource, e.g.
DataTable table = new DataTable();
table.Columns.Add(...);
DataGridView dgv = new DataGridView();
dgv.DataSource = table;
Anywhere your loops reference dataGridView1, replace that with table instead.
E.g.
for (int i = 0; i < table.Rows.Count; i++) {
//...
}

Getting position in a list and comparasion

I am trying to get positions in a list of some values to compare them with another list.
for (int i = 0; i <= commands.ToArray().Length; i++)
{
levensheteinvalues_commands.Add(commands.ToArray()[i].ToString());
levensheteinvalues_numbers.Add(
Program.ComputeLevenshteinDistance(args[0],
commands.ToArray()[i].ToString()));
}
for (int i = 0; i <= commands.ToArray().Length; i++)
{
if (smallestlevensheteinvalue == 0)
{
smallestlevensheteinvalue = levensheteinvalues_numbers[i];
}
else if (smallestlevensheteinvalue > levensheteinvalues_numbers[i])
{
smallestlevensheteinvalue = levensheteinvalues_numbers[i];
}
}
var indexes = levensheteinvalues_numbers.GetIndexes(smallestlevensheteinvalue);
Why doesn't
var indexes = levensheteinvalues_numbers.GetIndexes(smallestlevensheteinvalue);
work? And when I get the value how can I compare it to another list?
The code you have posted have some serious problems. This May solve your problem since your code as well as your approach is very unclear and ambiguous. I have blindly edited the code to fix the serious problems.
for (int i = 0; i < commands.Count(); i++) {
levensheteinvalues_commands.Add(commands.ElementAt(i).ToString());
Program.ComputeLevenshteinDistance(args[0], commands.ElementAt(i).ToString()));
}
for (int i = 0; i < commands.Count(); i++) {
if (smallestlevensheteinvalue == 0)
{
smallestlevensheteinvalue = levensheteinvalues_numbers[i];
}
else if (smallestlevensheteinvalue > levensheteinvalues_numbers[i])
{
smallestlevensheteinvalue = levensheteinvalues_numbers[i];
}
}
int index = levensheteinvalues_numbers.IndexOf(levensheteinvalues_numbers.Min());

Categories