Repeating 2 methods to make into 1 method - c#

I have this repeating code , and I'm unsure of how I can make it in only 1 method.
public int isWonVertical()
{
for (int i = 0; i < columns; i++)
{
resetCounter();
for (int j = 0; j < rows; j++)
{
if (raster[j, i] == 1) counterPlayer1++;
else counterPlayer1 = 0;
if (raster[j, i] == 2) counterPlayer2++;
else counterPlayer2 = 0;
if (counterPlayer1 == tokenStreak) return 1;
if (counterPlayer2 == tokenStreak) return 2;
}
}
return 0;
}//isWonVertical
public int isWonHorizontal()
{
for (int i = 0; i < rows; i++)
{
resetCounter();
for (int j = 0; j < columns; j++)
{
if (raster[i, j] == 1) counterPlayer1++;
else counterPlayer1 = 0;
if (raster[i, j] == 2) counterPlayer2++;
else counterPlayer2 = 0;
if (counterPlayer1 == tokenStreak) return 1;
if (counterPlayer2 == tokenStreak) return 2;
}
}
return 0;
}//isWonHorizontal
The returns and resetCounter() I can all put in 1 method. But how do I make sure the for loops are different for vertical/horizontal. I assume it's with giving parameters with, and then checking wether I gave 'vertical' or 'horizontal' as a paramter. But i'm unsure how to make this actually work.
Thank you.

public int isWon(DirectionEnum enum)
{
int counter1 = enum == DirectionEnum.IsVertical ? columns : rows;
int counter2 = enum == DirectionEnum.IsHorizontal ? columns: rows;
for (int i = 0; i < counter1 ; i++)
{
resetCounter();
for (int j = 0; j < counter2; j++)
{
if (raster[i, j] == 1) counterPlayer1++;
else counterPlayer1 = 0;
if (raster[i, j] == 2) counterPlayer2++;
else counterPlayer2 = 0;
if (counterPlayer1 == tokenStreak) return 1;
if (counterPlayer2 == tokenStreak) return 2;
}
}
return 0;
}

How about his, two parameters, one for the inner array, one for the outer. Then your client (calling code) needs to decide what to use as inner or outer, either rows or columns
public int isWon(outerArray, innerArray)
{
for (int i = 0; i < outerArray; i++)
{
resetCounter();
for (int j = 0; j < innerArray; j++)
{
if (raster[i, j] == 1) counterPlayer1++;
else counterPlayer1 = 0;
if (raster[i, j] == 2) counterPlayer2++;
else counterPlayer2 = 0;
if (counterPlayer1 == tokenStreak) return 1;
if (counterPlayer2 == tokenStreak) return 2;
}
}
return 0;
}

Related

How to Break a For Loop From an If Statement Inside the Loop (C#)

I am working on an A* Pathfinding method that uses a custom class instead of nodes, but am having issues with my loops. The first for loop using int i is able to go up to 3 (Player1.instance.movement = 3), but I need to use an if statement inside of that loop to check if the target position has already been found. I am wondering if it is possible to break my for loop when my If statement is false.
public void GetNeighbors(Tile originTile)
{
Tile originalTile = originTile;
nextTile.Clear();
int minX = 0;
int minY = 0;
var originCostFunc = Mathf.Infinity;
for (int i = 0; i < Player1.instance.movement; i++)
{
for (int x = -1; x <= 1; x++)
{
for (int y = -1; y <= 1; y++)
{
if (x != y && y != x)
{
var costX = Mathf.Abs((originTile.transform.position.x + x) - originalTile.transform.position.x);
var costY = Mathf.Abs((originTile.transform.position.y + y) - originalTile.transform.position.y);
var distanceX = Mathf.Abs(targetPos.transform.position.x - (originTile.transform.position.x + x));
var distanceY = Mathf.Abs(targetPos.transform.position.y - (originTile.transform.position.y + y));
var costFunc = costX + costY + distanceX + distanceY;
if (costFunc <= originCostFunc)
{
originCostFunc = costFunc;
minX = x;
minY = y;
Debug.Log($"x: {x}, y: {y}");
}
}
}
}
nextTile.Add(GridManagerHandPlaced.instance.GetTileAtPosition(new Vector2(originTile.transform.position.x + minX, originTile.transform.position.y + minY)));
if (nextTile[i] != targetPos)
{
originTile = nextTile[i];
}
else
{
break;
}
}
DisplayPath();
}
You can break loop several times by condition.
bool breakLoop = false;
for (int i = 0; i < length; i++)
{
for (int j = 0; j < length; j++)
{
for (int k = 0; k < length; k++)
{
breakLoop = nextTile == target;
if (breakLoop)
break;
}
if (breakLoop)
break;
}
if (breakLoop)
break;
}
Or move search logic to separated method and return a value from any number of nested loops
string path = FindPath();
Display(path);
string FindPath()
{
for (int i = 0; i < length; i++)
{
for (int j = 0; j < length; j++)
{
for (int k = 0; k < length; k++)
{
if (nextTile == target)
return nextTile;
}
}
}
return null;
}
Never use goto operator.
This is one of the few valid cases where I'd use goto. In-fact, this is the example given in the docs for when it should be used.
void CheckMatrices(Dictionary<string, int[][]> matrixLookup, int target)
{
foreach (var (key, matrix) in matrixLookup)
{
for (int row = 0; row < matrix.Length; row++)
{
for (int col = 0; col < matrix[row].Length; col++)
{
if (matrix[row][col] == target)
{
goto Found;
}
}
}
Console.WriteLine($"Not found {target} in matrix {key}.");
continue;
Found:
Console.WriteLine($"Found {target} in matrix {key}.");
}
}
Note the syntax for the label is simply myLabel: and you can place it anywhere in procedurally executable code.
For sake of covering other ways of handling this situation, here is the boolean solution.
bool breakLoops = false;
for (int i = 0; i < length1; i++)
{
for (int ii = 0; ii < length2; ii++)
{
for (int iii = 0; iii < length3; iii++)
{
if (breakingCondition)
{
breakLoops = true;
break;
}
}
if (breakLoops) break;
}
if (breakLoops) break;
}
Simple and straightforward, but requires a break condition check at the end of each loop that you want to break out of.

element swapping in a 4x4 array with numbers

I am making a game like this one : https://i.stack.imgur.com/mnbFw.jpg. I am having trouble coding the algorithm to swap numbers between each others. In my game , the 0 acts as the empty tile. This algorithm was originally for a 3x3 grid but I simply switched the 3's to 4's. I think that this is what's causing issues but I can't seem to find why.
{
int j, i;
for (i = 1; i < 4; i++)
{
for (j = 0; j < 4; j++)
{
if (t1[i, j] == 0)
{
t1[i, j] = t1[i - 1, j];
t1[i - 1, j] = 0;
}
}
}
}
static void scan_above(int[,] t1)
{
int j, i;
for (i = 1; i >= 0; i--)
{
for (j = 0; j < 4; j++)
{
if (t1[i, j] == 0)
{
t1[i, j] = t1[i + 1, j];
t1[i + 1, j] = 0;
}
}
}
}
static void scan_left(int[,] t1)
{
int j, i;
for (j = 1; j >= 0; j--)
{
for (i = 0; i < 4; i++)
{
if (t1[i, j] == 0)
{
t1[i, j] = t1[i, j + 1];
t1[i, j + 1] = 0;
}
}
}
}
static void scan_right(int[,] t1)
{
int j, i;
for (j = 1; j < 4; j++)
{
for (i = 0; i < 4; i++)
{
if (t1[i, j] == 0)
{
t1[i, j] = t1[i, j - 1];
t1[i, j - 1] = 0;
}
}
}
}```
I'm confused about why you're looping through all the values in the matrix. Unless there are considerations that aren't included in the question, this is all it should take:
static void MoveRight(int xOfZero, int yOfZero)
{
int rightValue = spaces[xOfZero, yOfZero + 1];
spaces[xOfZero, yOfZero + 1] = 0;
spaces[xOfZero, yOfZero] = rightValue;
}
FYI I hastily put together my matrix so it's indexed backwards, where x is the row number and y is the column. You could easily follow the same steps to make a move for every direction.

Can't perambulate indexes in matrix the right way

Hello. I have this task to sum the numbers as shown. Tried everything I can, but still not the right answer. Can I have some guidance?
static void Main(string[] args)
{
string input = Console.ReadLine();
int n = (int)char.GetNumericValue(input[0]);
int m = (int)char.GetNumericValue(input[2]);
int[,] matrix = new int[n, m];
int sum = 0;
//fill matrix
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
matrix[i, j] = (j * 3 + 1) + i * 3;
}
}
for (int i = 0; i < matrix.GetLength(0) - 1; i+=1)
{
for (int j = 0; j < matrix.GetLength(1) - i; j+=1)
{
if (i % 2 == 0)
{
sum += matrix[i, j + i] + matrix[i + 1, j + 1];
}
}
}
Console.WriteLine(sum);
}
I think you would've a easier time hard coding the input (and naming them as "columns" and "rows" instead, much more readable).
What is the expected output? Not sure I'm following this sum. I'm guessing, 297? If so:
for (int i = 0; i < matrix.GetLength(0); i++)
{
for (int j = 0; j < matrix.GetLength(1); j++)
{
Console.Write(matrix[i, j] + " ");
if(j == 5) Console.WriteLine();
if (matrix[i, j] % 2 != 0)
{
if (i == 0 || i == matrix.GetLength(0) - 1
|| j == 0 || j == matrix.GetLength(0))
{
sum += (matrix[i, j]);
}
else
{
sum += (matrix[i, j] * 2);
}
}
}
}

How do I set the debugger to catch what changed the variable

I am implementing the NEH algorithm following this slide and video:
http://mams.rmit.edu.au/b5oatq61pmjl.pdf
https://www.youtube.com/watch?v=TcBzEyCQBxw
My problem during the test is the variable Sorted_list got changed which cause different results from what I expect:
This the portion where I have the problem but I couldn't know what it changes it(I used breakpoints and watch variable window):
for (int i = 0; i < kmsList.Count; i++)
{
for (int j = 0; j < kmsList[i].Length - 1; j++)
{
/*
*
* HERE Sorted_list GET MODIFIED UNEXPECTEDLY
*/
if (i == 0 && j == 0)
kmsList[0][0] = Sorted_list[0][0];
else if (i == 0)
kmsList[0][j] = kmsList[0][j - 1] + Sorted_list[0][j];
else if (j == 0)
kmsList[i][0] = kmsList[i - 1][0] + Sorted_list[i][0];
}
}
Complete implementation:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FINAL_NEH
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("entre the nmbr of jobs : ");
string row = Console.ReadLine();
Console.WriteLine("entre the nmbr of machines : ");
string column = Console.ReadLine();
int job = int.Parse(row.ToString());
int machine = int.Parse(column.ToString());
List<int[]> list = new List<int[]>();
// read the nmbrs and put it in list-----------------------------------------------------
for (int i = 0; i < job; i++)
{
list.Add(new int[machine + 1]);
for (int j = 0; j < machine; j++)
{
list[i][j] = int.Parse(Console.ReadLine());
}
list[i][list[i].Length - 1] = int.Parse((i + 1).ToString()); //Last Elemnt Is Job Number-
}
// show the list----------------------------------------------------------------------------
for (int i = 0; i < job; i++)
{
for (int j = 0; j < machine + 1; j++)
{
Console.Write("\t" + "[" + list[i][j] + "]");
}
Console.WriteLine();
}
// sort the list------------------------------------------------------------------------------
for (int i = 0; i < list.Count; i++)
{
for (int j = i + 1; j < list.Count; j++)
{
int sumI = 0, sumJ = 0;
for (int a = 0; a < list[i].Length - 1; a++)
{
sumI += list[i][a];
}
for (int a = 0; a < list[j].Length - 1; a++)
{
sumJ += list[j][a];
}
if (sumI < sumJ)
{
int[] temp = new int[int.Parse(job.ToString())];
temp = list[i];
list[i] = list[j];
list[j] = temp;
}
}
}
Console.Write("\n\n-----------------after sorting ------------------------------------\n\n");
// shaw the list after sorting------------------------------------------
for (int i = 0; i < job; i++)
{
for (int j = 0; j < machine + 1; j++)
{
Console.Write("\t" + "[" + list[i][j] + "]");
}
Console.WriteLine();
}
// clculate the maxpane of the first 2 jobs---------------------------------------
List<int[]> initMaxpane = new List<int[]>();
initMaxpane.Add((int[])list[0].Clone());
initMaxpane.Add((int[])list[1].Clone());
// calculer maxspan of first jobs..............................................
for (int i = 0; i < initMaxpane.Count; i++)
{
for (int j = 0; j < initMaxpane[i].Length - 1; j++)
{
if (j == 0 && i == 0)
initMaxpane[0][0] = list[i][j];
else if (i == 0)
initMaxpane[0][j] = (int)(initMaxpane[0][j - 1] + list[0][j]);
else if (j == 0)
initMaxpane[i][0] = (int)(initMaxpane[i - 1][0] + list[i][0]);
}
}
for (int i = 1; i < initMaxpane.Count; i++)
{
for (int j = 1; j < initMaxpane[i].Length - 1; j++)
{
if ((initMaxpane[i][j - 1] > initMaxpane[i - 1][j]))
initMaxpane[i][j] = (int)(initMaxpane[i][j - 1] + list[i][j]);
else
initMaxpane[i][j] = (int)(initMaxpane[i - 1][j] + list[i][j]);
}
}
int Cmax = initMaxpane[initMaxpane.Count - 1][initMaxpane[initMaxpane.Count - 1].Length - 2];
Console.WriteLine("\n\n-------the maxpane offirst jobs----------");
for (int i = 0; i < initMaxpane.Count; i++)
{
for (int j = 0; j < initMaxpane[i].Length; j++)
{
Console.Write("\t" + "[" + initMaxpane[i][j] + "]");
}
Console.WriteLine();
}
List<int[]> initMaxpane2 = new List<int[]>();
initMaxpane2.Add(list.ElementAt(1));
initMaxpane2.Add(list.ElementAt(0));
// calculer maxspan of first jobs reverse..............................................
for (int i = 0; i < initMaxpane2.Count; i++)
{
for (int j = 0; j < initMaxpane2[i].Length - 1; j++)
{
if (j == 0 && i == 0)
initMaxpane2[0][0] = list[i][j];
else if (i == 0)
initMaxpane2[0][j] = (int)(initMaxpane2[0][j - 1] + list[0][j]);
else if (j == 0)
initMaxpane2[i][0] = (int)(initMaxpane2[i - 1][0] + list[i][0]);
}
}
for (int i = 1; i < initMaxpane2.Count; i++)
{
for (int j = 1; j < initMaxpane2[i].Length - 1; j++)
{
if ((initMaxpane2[i][j - 1] > initMaxpane2[i - 1][j]))
initMaxpane2[i][j] = (int)(initMaxpane2[i][j - 1] + list[i][j]);
else
initMaxpane2[i][j] = (int)(initMaxpane2[i - 1][j] + list[i][j]);
}
}
int Cmax2 = initMaxpane2[initMaxpane2.Count - 1][initMaxpane2[initMaxpane2.Count - 1].Length - 2];
Console.WriteLine("\n\n-------the maxpane of first jobs (reverse)----------");
for (int i = 0; i < initMaxpane2.Count; i++)
{
for (int j = 0; j < initMaxpane2[i].Length; j++)
{
Console.Write("\t" + "[" + initMaxpane2[i][j] + "]");
}
Console.WriteLine();
}
List<int[]> MaxpaneList = new List<int[]>();
if (Cmax > Cmax2)
{
MaxpaneList.Add((int[])list[1].Clone());
MaxpaneList.Add((int[])list[0].Clone());
}
else
{
MaxpaneList.Add((int[])list[0].Clone());
MaxpaneList.Add((int[])list[1].Clone());
}
List<int[]> bestSequenceList = null;
List<int[]> kmsList = null;
List<int[]> Sorted_list = list.ToList();
int bestCma = 0;
//int maxspan = 0;
for (int jo = 2; jo < job; jo++)
{
for (int ins = 0; ins <= MaxpaneList.Count; ins++)
{
MaxpaneList.Insert(ins, list[jo]);
kmsList = MaxpaneList.ToList();
int Cma = 0;
for (int i = 0; i < kmsList.Count; i++)
{
for (int j = 0; j < kmsList[i].Length - 1; j++)
{
/*
*
* HERE Sorted_list GET MODIFIED UNEXPECTEDLY
*/
if (i == 0 && j == 0)
kmsList[0][0] = Sorted_list[0][0];
else if (i == 0)
kmsList[0][j] = kmsList[0][j - 1] + Sorted_list[0][j];
else if (j == 0)
kmsList[i][0] = kmsList[i - 1][0] + Sorted_list[i][0];
}
}
for (int i = 1; i < kmsList.Count; i++)
{
for (int j = 1; j < kmsList[i].Length - 1; j++)
{
if ((kmsList[i][j - 1] > kmsList[i - 1][j]))
kmsList[i][j] = kmsList[i][j - 1] + Sorted_list[i][j];
else
kmsList[i][j] = kmsList[i - 1][j] + Sorted_list[i][j];
}
}
Cma = kmsList[kmsList.Count - 1][kmsList[kmsList.Count - 1].Length - 2];
Console.WriteLine("\n\n\n------- the maxpane sequence ----------");
for (int i = 0; i < MaxpaneList.Count; i++)
{
for (int j = 0; j < MaxpaneList[i].Length; j++)
{
Console.Write("\t" + "[" + MaxpaneList[i][j] + "]");
}
Console.WriteLine();
}
Console.WriteLine("MAX : " + Cma + "\n\n\n");
if (ins == 0)
{
bestCma = Cma;
}
if (jo == 2 && ins == 0)
{
bestSequenceList = MaxpaneList.ToList();
bestCma = Cma;
}
else
{
if (bestCma > Cma)
{
bestSequenceList = MaxpaneList.ToList();
bestCma = Cma;
}
}
MaxpaneList.RemoveAt(ins);
}
MaxpaneList = bestSequenceList.ToList();
}
Console.ReadLine();
}
}
}
The issue lies in the following code (snippet):
List<int[]> Sorted_list = list.ToList();
ToList will create a new list, but because in this case int[] is a reference type then the new list will contain references to the same arrays as the original list.
Updating a value (of an array) referenced in the new list will also affect the equivalent value in the original list.
kmsList[0][0] = Sorted_list[0][0];
The solution is to create a real copy of 'list' and its items (in this case int[]):
List<int[]> Sorted_list = list.ConvertAll(myArray => (int[])myArray.Clone());
This piece of code clones all arrays within the list to a new variable Sorted_list.
A useful link that explains the difference between value and reference types is: https://msdn.microsoft.com/en-us/library/t63sy5hs.aspx
Reference Types
A reference type contains a pointer to another memory location that holds the data.
Reference types include the following:
String
All arrays, even if their elements are value types Class
types, such as Form
Delegates
When you create a List<> (or any other container) from another container (as you do when you call list.ToList()) you do not create copies of all of the elements in the container. You create new references to the items in the list that you're copying. In CS parlance it's a shallow copy and not a deep copy.
So, if you do this:
int[] ia = new[] {0, 1, 2, 3, 4};
int[] ib = new[] {5, 6, 7, 8, 9};
List<int[]> la = new List<int[]>() { ia, ib };
List<int[]> lb = la.ToList();
Both lists refer to the same two arrays, and if you change one array like this:
la[1][4] = 10;
Then lb[1][4] will also be 10 because the two lists each contain the same arrays. Copying the list does not copy the elements in the list.

How can I use hopfield network to learn more patterns?

Is there any relation between number of neurons and ability of Hopfield network to recognize patterns?
I write neural network program in C# to recognize patterns with Hopfield network. My network has 64 neurons. When I train network for 2 patterns, every things work nice and easy, but when I train network for more patterns, Hopfield can't find answer!
So, according to my code, how can I use Hopfield network to learn more patterns?
Should I make changes in this code?
There is my train() function:
public void Train(bool[,] pattern)
{
//N is number of rows in our square matrix
//Convert input pattern to bipolar
int[,] PatternBipolar = new int[N, N];
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
{
if (pattern[i, j] == true)
{
PatternBipolar[i, j] = 1;
}
else
{
PatternBipolar[i, j] = -1;
}
}
//convert to row matrix
int count1 = 0;
int[] RowMatrix = new int[(int)Math.Pow(N, 2)];
for (int j = 0; j < N; j++)
for (int i = 0; i < N; i++)
{
RowMatrix[count1] = PatternBipolar[i, j];
count1++;
}
//convert to column matrix
int count2 = 0;
int[] ColMatrix = new int[(int)Math.Pow(N, 2)];
for (int j = 0; j < N; j++)
for (int i = 0; i < N; i++)
{
ColMatrix[count2] = PatternBipolar[i, j];
count2++;
}
//multiplication
int[,] MultipliedMatrix = new int[(int)Math.Pow(N, 2), (int)Math.Pow(N, 2)];
for (int i = 0; i < (int)Math.Pow(N, 2); i++)
for (int j = 0; j < (int)Math.Pow(N, 2); j++)
{
MultipliedMatrix[i, j] = ColMatrix[i] * RowMatrix[j];
}
//cells in the northwest diagonal get set to zero
for (int i = 0; i < (int)Math.Pow(N, 2); i++)
MultipliedMatrix[i, i] = 0;
// WightMatrix + MultipliedMatrix
for (int i = 0; i < (int)Math.Pow(N, 2); i++)
for (int j = 0; j < (int)Math.Pow(N, 2); j++)
{
WeightMatrix[i, j] += MultipliedMatrix[i, j];
}
And there is Present() function (this function is used to return answer for a given pattern):
public void Present(bool[,] Pattern)
{
int[] output = new int[(int)(int)Math.Pow(N, 2)];
for (int j = 0; j < N; j++)
for (int i = 0; i < N; i++)
{
OutputShowMatrix[i, j] = 0;
}
//convert bool to binary
int[] PatternBinary = new int[(int)Math.Pow(N, 2)];
int count = 0;
for (int j = 0; j < N; j++)
for (int i = 0; i < N; i++)
{
if (Pattern[i, j] == true)
{
PatternBinary[count] = 1;
}
else
{
PatternBinary[count] = 0;
}
count++;
}
count = 0;
int activation = 0;
for (int j = 0; j < (int)Math.Pow(N, 2); j++)
{
for (int i = 0; i < (int)Math.Pow(N, 2); i++)
{
activation = activation + (PatternBinary[i] * WeightMatrix[i, j]);
}
if (activation > 0)
{
output[count] = 1;
}
else
{
output[count] = 0;
}
count++;
activation = 0;
}
count = 0;
for (int j = 0; j < N; j++)
for (int i = 0; i < N; i++)
{
OutputShowMatrix[i, j] = output[count++];
}
In below images I trained Hopfield for characters A and P and when input patterns are like A or P, network recognize them in true way
Then I train it for character C:
This is where every things go wrong!
Now if I enter pattern like C, this issue happen:
And if enter pattern like A, see what happen:
And if train more patterns, whole of grid become black!
I've spotted only one mistake in your code: you perform only one iteration of node value calculation, without verifying if the values have converged. I've fixed this method like this:
public bool[,] Present(bool[,] pattern)
{
bool[,] result = new bool[N, N];
int[] activation = new int[N * N];
int count = 0;
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
{
activation[count++] = pattern[i, j] ? 1 : 0;
}
bool convergence = false;
while (!convergence)
{
convergence = true;
var previousActivation = (int[])activation.Clone();
for (int i = 0; i < N * N; i++)
{
activation[i] = 0;
for (int j = 0; j < N * N; j++)
{
activation[i] += (previousActivation[j] * WeightMatrix[i, j]);
}
activation[i] = activation[i] > 0 ? 1 : 0;
if (activation[i] != previousActivation[i])
{
convergence = false;
}
}
}
count = 0;
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
{
result[i, j] = activation[count++] == 1;
}
return result;
}
This slightly improves the results, however probably should also be improved to calculate the values asynchronously to avoid cycles.
Unfortunately, this still introduces the behaviour you've described. This is results from the phenomena called spurious patterns. For the network to learn more than one pattern consider training it with a Hebb rule. You can read about the spurious patterns, stability and learning of the Hopfield network here and here.

Categories

Resources