I've been learning about Python lately, but recently wanted to do a project that involved a 2D array, so I decided to switch over to C# (So sorry if my code is poor)
Basically I'm writing a program that does a crossword puzzle for me.
I have i iterating through top/bottom
I have j iterating through left to right
I find the first letter i want - lets call this "keyletter"
Now I need to look in all 8 spaces around it. If the i/j position is [1,2], I'm looking at [0,2] first.
In my code I want to change i from 1 to 0, and print, (if this is the correct letter) second letter is: [0,2]
As soon as I change i from 1 to 0 and try to print, it spits it out a million times and gets stuck.
public static void Main(string[] args)
{
string keyLetter = "g";
string keyLetter2 = "b";
string[,] crossword = new string[,]
{
{ "a", "b", "c", "d" },
{ "e", "f", "g", "h" },
{ "a", "e", "b", "c" },
{ "i", "j", "k", "l" }
};
for (int i = 0; i < crossword.GetLength(0); i++)
{
for (int j = 0; j < crossword.GetLength(1); j++)
{
if (keyLetter == crossword[i, j])
{
Console.Write(keyLetter + " is [" + i + ", " + j + "]");
Console.WriteLine();
Console.WriteLine();
Console.Write("i is: " + i);
Console.WriteLine();
Console.Write("j is: " + j);
Console.WriteLine();
if (keyLetter2 == crossword[i - 1, j])
{
// i--;
Console.Write("[i/j] position for " + keyLetter2 + " is [" + i +
", " + j + "]");
}
else if (keyLetter2 == crossword[i + 1, j])
{
Console.Write("[i/j] position for " + keyLetter2 + " is [" + i +
", " + j + "]");
}
/*
else if (keyLetter2 == crossword[i + 1, j - 1])
{
Console.Write("[i/j] position for " + keyLetter2 + " is [" + i +
", " + j + "]");
}
else if (keyLetter2 == crossword[i, j - 1])
{
Console.Write("[i/j] position for " + keyLetter2 + " is [" + i +
", " + j + "]");
}
else if (keyLetter2 == crossword[i - 1, j - 1])
{
Console.Write("[i/j] position for " + keyLetter2 + " is [" + i +
", " + j + "]");
}
else if (keyLetter2 == crossword[i + 1, j + 1])
{
Console.Write("[i/j] position for " + keyLetter2 + " is [" + i +
", " + j + "]");
}
else if (keyLetter2 == crossword[i, j + 1])
{
Console.Write("[i/j] position for " + keyLetter2 + " is [" + i +
", " + j + "]");
}
else if (keyLetter2 == crossword[i - 1, j + 1])
{
Console.Write("[i/j] position for " + keyLetter2 + " is [" + i +
", " + j + "]");
}*/
Console.WriteLine();
}
}
}
}
I have it setup like:
keyletter = "a"
keyletter2 = "b"
etc.
Loop problem picture
The Problem is with the statement
//if (keyLetter2 == crossword[i-1, j])
Here, if the matrix is like
"
a b c
d e f
g h i
"
and suppose you want to search for pattern "ba", Then obviously you will look for b, hence i will be 0 and j will be 1. Now, you are going to do (i-1) which will be -1(there are no negative indexes), Hence the error.
The best approach to do this is to check if i or j are already 0 or not. If they are 0, then you don't need a i-1 or j-1 and you can go like
" if(i!=0)
then
if (keyLetter2 == crossword[i-1, j])
...
"
I can't see any infinite loop, but run time exceptions (IndexOutOfRangeException) at
if (keyLetter2 == crossword[i-1, j]) {...} // if i == 0
...
else if (keyLetter2 == crossword[i+1, j]) {...} // if i == crossword.GetLength(0) - 1
Let's get rid of these exceptions and brush up the loop:
for (int i = 0; i < crossword.GetLength(0); ++i)
for (int j = 0; j < crossword.GetLength(1); ++j)
if (keyLetter == crossword[i, j]) {
// Keep you messages being readable with a help of string interpolation - $""
Console.WriteLine(string.Join(Environment.NewLine,
$"{keyLetter} is [{i}, {j}]",
""
$"i is: {i}",
""
$"j is: {j}",
""
));
// Do not repeat yourself: if you want 4 neighbors to test
for (int neighbor = 0; neighbor < 4; ++neighbor) {
int ii = i + (neighbor % 2) * (neighbor - 1);
int jj = j + (1 - neighbor % 2) * (neighbor - 1);
// Check indexes ii, jj before addressing [ii, jj]
if (ii >= 0 && ii < crossword.GetLength(0) &&
jj >= 0 && jj < crossword.GetLength(1) &&
keyLetter2 == crossword[ii, jj]) {
Console.Write($"[i/j] position for {keyLetter2} is [{i}, {j}]");
// In case we want at most one neighbor; comment it out if we want all of them
break;
}
}
}
In case you have 8 (not 4) neighbors to check
...
bool found = false;
for (int ii = Math.Max(0, i - 1); ii <= Math.Min(i + 1, crossword.GetLength(0)) && !found; ++ii)
for (int jj = Math.Max(0, j - 1); jj <= Math.Min(j + 1, crossword.GetLength(0)) && !found; ++jj) {
if ((ii != i || jj != j) && keyLetter2 == crossword[ii, jj])) {
Console.Write($"[i/j] position for {keyLetter2} is [{i}, {j}]");
// In case we want at most one neighbor; comment it out if we want all of them
found = true;
}
}
I would take a slightly different approach, which would be to delegate the "neighbor search" to a helper method. You can pass to this method the array, the cell whose neighbors should be searched, and the value that you're searching for.
Because a cell item is defined by two integer coordinates, and because there's an existing Point structure we can use that has two integer properties (X and Y), I'm using that to represent a cell in our array.
The helper function works by determining the minimum value of X and Y around the cell whose neighbors we're searching by subtracting 1 from it's X and Y values. Then we need to make sure this result is not less than 0 to ensure we stay within the bounds of the array.
Likewise, we add 1 to get the maximum value, and make sure it's not greater than the upper bound of the array.
Finally, we return the list of matches (if any were found) in a List<Point>:
public static List<Point> GetNeighborMatches(string[,] grid, Point item, string valueToFind)
{
var result = new List<Point>();
// if our grid is empty or the item isn't in it, return an empty list
if (grid == null || grid.Length == 0 ||
item.X < 0 || item.X > grid.GetUpperBound(0) ||
item.Y < 0 || item.Y > grid.GetUpperBound(1))
{
return result;
}
// Get min and max values of x and y for searching
var minX = Math.Max(item.X - 1, 0);
var maxX = Math.Min(item.X + 1, grid.GetUpperBound(0));
var minY = Math.Max(item.Y - 1, 0);
var maxY = Math.Min(item.Y + 1, grid.GetUpperBound(1));
// Loop through all neighbors to find a match
for (int x = minX; x <= maxX; x++)
{
for (int y = minY; y <= maxY; y++)
{
// Continue looping if we're on the 'item'
if (x == item.X && y == item.Y) continue;
// If this is a match, add it to our list
if (grid[x, y] == valueToFind) result.Add(new Point(x, y));
}
}
// Return all the matching neighbors
return result;
}
Now we can use this helper method inside your existing code:
public static void Main(string[] args)
{
string keyLetter = "g";
string keyLetter2 = "b";
string[,] crossword = new string[,]
{
{ "a", "b", "c", "d" },
{ "e", "f", "g", "h" },
{ "a", "e", "b", "c" },
{ "i", "j", "k", "l" }
};
for (int i = 0; i < crossword.GetLength(0); i++)
{
for (int j = 0; j < crossword.GetLength(1); j++)
{
if (keyLetter == crossword[i, j])
{
// we found a match for our first letter!
Console.WriteLine("The first value (" + keyLetter + ") is at [" +
i + ", " + j + "]");
// get neighboring matches for keyLetter2
List<Point> matches = GetNeighborMatches(crossword,
new Point(i, j), keyLetter2);
// Output our matches if we found any
if (matches.Any())
{
foreach (var match in matches)
{
Console.WriteLine("The second value (" + keyLetter2 +
") is at [" + match.X + ", " + match.Y + "]");
}
}
else
{
Console.WriteLine("No match was found for '" + keyLetter2 +
"' near [" + i + ", " + j + "]");
}
}
}
}
}
Output
here's my current code that I am using
public string obfuscateNums(string src)
{
string returnSrc = src;
string[] numbers = Regex.Split(src, #"\D+");
foreach (string val in numbers)
{
if (!string.IsNullOrEmpty(val))
{
string newNum = obfuscateNumber(val);
Regex reg = new Regex(val);
returnSrc = reg.Replace(returnSrc, newNum);
}
}
return returnSrc;
}
public string obfuscateNumber(string origNumber)
{
Random random = new Random();
int orig = Convert.ToInt32(origNumber);
int add = random.Next(0, orig * 2);
int sub = add;
int mul = random.Next(0, orig * 2);
int div = mul;
return "((((" + orig + " + " + add + ")-" + sub + ")*" + mul + ")/" + div + ")";
}
Before it would only obfuscate the last number but now it's obfuscating numbers inside of the already obfuscated number. Anyone know how I would fix this?
Current Result:
local x = ((((27 + ((((5 + 9)-9)*0)/0)1)-((((5 + 9)-9)*0)/0)1)*((((3 + ((((5 + 9)-9)*0)/0))-((((5 + 9)-9)*0)/0))*0)/0))/((((3 + ((((5 + 9)-9)*0)/0))-((((5 + 9)-9)*0)/0))*0)/0)) + ((((29 + ((((5 + 9)-9)*0)/0)((((4 + 7)-7)*0)/0))-((((5 + 9)-9)*0)/0)((((4 + 7)-7)*0)/0))*((((4 + 7)-7)*0)/0))/((((4 + 7)-7)*0)/0)) + ((((28 + ((((5 + 9)-9)*0)/0)((((3 + ((((5 + 9)-9)*0)/0))-((((5 + 9)-9)*0)/0))*0)/0))-((((5 + 9)-9)*0)/0)((((3 + ((((5 + 9)-9)*0)/0))-((((5 + 9)-9)*0)/0))*0)/0))*((((3 + ((((5 + 9)-9)*0)/0))-((((5 + 9)-9)*0)/0))*0)/0))/((((3 + ((((5 + 9)-9)*0)/0))-((((5 + 9)-9)*0)/0))*0)/0)) + ((((26 + ((((4 + 7)-7)*0)/0)9)-((((4 + 7)-7)*0)/0)9)*((((3 + ((((5 + 9)-9)*0)/0))-((((5 + 9)-9)*0)/0))*0)/0))/((((3 + ((((5 + 9)-9)*0)/0))-((((5 + 9)-9)*0)/0))*0)/0)) + ((((3 + ((((5 + 9)-9)*0)/0))-((((5 + 9)-9)*0)/0))*0)/0) + ((((4 + 7)-7)*0)/0) + ((((5 + 9)-9)*0)/0)
You can use the overload of Regex.Replace(...) that takes a MatchEvaluator for this:
https://msdn.microsoft.com/en-us/library/cft8645c(v=vs.110).aspx
Like so:
public string obfuscateNums(string src)
{
string returnSrc = src;
var reg = new Regex(#"\d+");
return reg.Replace(src, (match) => obfuscateNumber(match.Value));
}
public string obfuscateNumber(string origNumber)
{
Random random = new Random();
int orig = Convert.ToInt32(origNumber);
int add = random.Next(0, orig * 2);
int sub = add;
int mul = random.Next(0, orig * 2);
int div = mul;
return "((((" + orig + " + " + add + ")-" + sub + ")*" + mul + ")/" + div + ")";
}
The MatchEvaluator method parameter is a method that processes each match and returns a replacement value.
Change obfuscateNums to:
var returnSrc = src;
var numbers = Regex.Split(src, #"\D+");
var lastIndex = 0;
foreach (var val in numbers)
if (!string.IsNullOrEmpty(val))
{
var newNum = ObfuscateNumber(val);
var startIndex = returnSrc.IndexOf(val, lastIndex);
if (startIndex == -1) continue;
returnSrc = returnSrc.Remove(startIndex, val.Length);
returnSrc = returnSrc.Insert(startIndex, newNum);
lastIndex = startIndex + newNum.Length;
}
return returnSrc;
for (int i = 0; i < metroGrid1.Rows.Count; i++)
{
if (metroGrid1.Rows[i].Cells[0].Value.ToString() == radGridView1.SelectedRows[0].Cells[0].Value.ToString())
{
counter = i;
metroGrid1.Rows[counter].Cells[2].Value = Convert.ToInt32(metroGrid1.Rows[counter].Cells[2].Value) + radSpinEditor1.Value;
MessageBox.Show("for loop");
}
else
{
metroGrid1.Rows.Add(radGridView1.SelectedRows[0].Cells[0].Value.ToString(), radGridView1.SelectedRows[0].Cells[1].Value.ToString() + " " + radGridView1.SelectedRows[0].Cells[2].Value.ToString() + " " + radGridView1.SelectedRows[0].Cells[3].Value.ToString() + " " + radGridView1.SelectedRows[0].Cells[4].Value.ToString(), radSpinEditor1.Value, decimal.Round(prodamt, 2), decimal.Round(prodtotamt, 2));
totamt += prodtotamt;
metroLabelTotalamt.Text = (string.Format("{0:#,###0.00}", totamt));
radSpinEditor1.Value = 1;
MessageBox.Show("else ");
}
}
Shouldn't that be? Since you yourself adding rows to your gridview by calling Add() method as can be seen in your posted code
metroGrid1.Rows.Add(radGridView1.SelectedRows[0].Cells[0].Value.ToString(),
No idea since I don't know your requirement but to me it feels like you wanted to have the other part as else block.
for (int i = 0; i < metroGrid1.Rows.Count; i++)
{
if (metroGrid1.Rows[i].Cells[0].Value.ToString() == radGridView1.SelectedRows[0].Cells[0].Value.ToString())
{
counter = i;
metroGrid1.Rows[counter].Cells[2].Value = Convert.ToInt32(metroGrid1.Rows[counter].Cells[2].Value) + radSpinEditor1.Value;
MessageBox.Show("for loop");
}
else
{
metroGrid1.Rows.Add(radGridView1.SelectedRows[0].Cells[0].Value.ToString(), radGridView1.SelectedRows[0].Cells[1].Value.ToString() + " " + radGridView1.SelectedRows[0].Cells[2].Value.ToString() + " " + radGridView1.SelectedRows[0].Cells[3].Value.ToString() + " " + radGridView1.SelectedRows[0].Cells[4].Value.ToString(), radSpinEditor1.Value, decimal.Round(prodamt, 2), decimal.Round(prodtotamt, 2));
totamt += prodtotamt;
metroLabelTotalamt.Text = (string.Format("{0:#,###0.00}", totamt));
radSpinEditor1.Value = 1;
MessageBox.Show("else ");
}
}
I have some code:
var result = new List<string>;
...
for (var i = 0; i < level; ++i)
if (result.ElementAtOrDefault(i) == null)
result.Insert(i, " " + positions[i]);
else
result[i] += " " + positions[i];
if (result.ElementAtOrDefault(level) == null)
result.Insert(level, " " + currentPosition);
else
result[level] += " " + currentPosition;
Can I do this without checking element for null from i-position? I need to add a part of string in i-position. But I have "ArgumentOutOfRangeException" if element wasn't created. Also method "insert" don't replace the element but push back it.
I tried to get data from "ArgumentOutOfRangeException" (which index called this exception) but I've failed.
You can reduce using ElementAtOrDefault with adding some condition like this
int i;
for (i = 0; i < level && i < result.Count; ++i){
//change existing items
result[i] += " " + positions[i];
}
for (int j = 0, countAdd = level - result.Count; j < countAdd; ++j)
//add new items
result.Add(" " + positions[i+j]);
//add current
if (level >= result.Count)
result.Add(" " + currentPosition);
else
result[level] += " " + currentPosition;
I have the method that does a calculation and adds the data to a collection list. Below is my code
IterateDtColl iterateDataList = new IterateDtColl();
double answer;
//Array to hold the previous initail tempreture
double[] TempArray = new double[9];
for (int tVal = 0; tVal < exdatalist.count(); tVal++)
{
ValidateDataColl validatelist = new ValidateDataColl();
//Assign my initial tempreture
if (iterateDataList.count() > 0)
{
TempArray[0] = iterateDataList.getexceldata(tVal - 1).Pi1;
TempArray[1] = iterateDataList.getexceldata(tVal - 1).Pi2;
TempArray[2] = iterateDataList.getexceldata(tVal - 1).Pi3;
TempArray[3] = iterateDataList.getexceldata(tVal - 1).Pi4;
TempArray[4] = iterateDataList.getexceldata(tVal - 1).Pi5;
TempArray[5] = iterateDataList.getexceldata(tVal - 1).Pi6;
TempArray[6] = iterateDataList.getexceldata(tVal - 1).Pi7;
TempArray[7] = iterateDataList.getexceldata(tVal - 1).Pi8;
TempArray[8] = iterateDataList.getexceldata(tVal - 1).Pi9;
}
else
{
TempArray[0] = Convert.ToDouble(initProbTxtBx.Text);
TempArray[1] = TempArray[0];
TempArray[2] = TempArray[0];
TempArray[3] = TempArray[0];
TempArray[4] = TempArray[0];
TempArray[5] = TempArray[0];
TempArray[6] = TempArray[0];
TempArray[7] = TempArray[0];
TempArray[8] = TempArray[0];
}
//Holds Value for last calculated values..
double[] LastCalValue = new double[9];
for (int iVal = 0; iVal < 9; iVal++)
{
answer = 0.0;
if (iVal == 0)
{
answer = (TempArray[iVal] + (r_val(dxval(lval, nval)) * (exdatalist.getexceldata(tVal).CentreTemp + initVal))) / (1 + (2 * r_val(dxval(lval, nval))));
}
else if (iVal == 8)
{
answer = (TempArray[iVal] + (r_val(dxval(lval, nval)) * (LastCalValue[iVal - 1] + exdatalist.getexceldata(tVal).SurfaceTemp))) / (1 + (2 * r_val(dxval(lval, nval))));
}
else
{
answer = (TempArray[iVal] + (r_val(dxval(lval, nval)) * (LastCalValue[iVal - 1] + initVal))) / (1 + (2 * r_val(dxval(lval, nval))));
}
//Hold the values at the present index so it can be used at the next index
LastCalValue[iVal] = answer;
//Adds the data to be validated to my collection list
validatelist.addvaliddt(new ValidateDataCl(initVal, LastCalValue[iVal], TempArray[iVal]));
}
I want to check that the difference between the initVal and LastCalValue[index] in the validatelist is less than 0.0001, if it is not, then do the calculation below till the condition is met.
for (int check = 0; check < validate.count(); check++)
{
double newAnswer;
double NewVal = 0.0;
if (check == 0)
{
//Set my new value to the value at the next index(Which then becomes my guess)
NewVal = validate.getvaliddata(check + 1).NewValue;
newAnswer = (validate.getvaliddata(check).InitTemp + (r_val(dxval(lval, nval)) * (CentreTemp + NewVal))) / (1 + (2 * r_val(dxval(lval, nval))));
}
else if (check == 8)
{
NewVal = OldVal[check - 1];
newAnswer = (validate.getvaliddata(check).InitTemp + (r_val(dxval(lval, nval)) * (NewVal + SurfaceTemp))) / (1 + (2 * r_val(dxval(lval, nval))));
}
else
{
NewVal = validate.getvaliddata(check + 1).NewValue;
newAnswer = (validate.getvaliddata(check).InitTemp + (r_val(dxval(lval, nval)) * (OldVal[check - 1] + NewVal))) / (1 + (2 * r_val(dxval(lval, nval))));
}
validate.getvaliddata(check).InitGuess = NewVal;
validate.getvaliddata(check).NewValue = newAnswer;
OldVal[check] = newAnswer;
}
//ValidateDataColl ValidatedList = CalNewData(validatelist, exdatalist.getexceldata(tVal).CentreTemp, exdatalist.getexceldata(tVal).SurfaceTemp);
iterateDataList.additerdt(new IterateClass(exdatalist.getexceldata(tVal).CentreTemp, ValidatedList.getvaliddata(0).NewValue, ValidatedList.getvaliddata(1).NewValue, ValidatedList.getvaliddata(2).NewValue, ValidatedList.getvaliddata(3).NewValue, ValidatedList.getvaliddata(4).NewValue, ValidatedList.getvaliddata(5).NewValue, ValidatedList.getvaliddata(6).NewValue, ValidatedList.getvaliddata(7).NewValue, ValidatedList.getvaliddata(8).NewValue, exdatalist.getexceldata(tVal).SurfaceTemp));
}
return iterateDataList;
How can I do that?